mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
committed by
Géry Debongnie
parent
54e1734f2f
commit
79983de4ed
+2
-8
@@ -81,13 +81,7 @@ export class Context extends EventBus {
|
|||||||
const subscriptions = this.subscriptions.update;
|
const subscriptions = this.subscriptions.update;
|
||||||
const groups = partitionBy(subscriptions, s => (s.owner ? s.owner.__owl__.depth : -1));
|
const groups = partitionBy(subscriptions, s => (s.owner ? s.owner.__owl__.depth : -1));
|
||||||
for (let group of groups) {
|
for (let group of groups) {
|
||||||
const proms = Promise.all(
|
const proms = group.map(sub => sub.callback.call(sub.owner, rev));
|
||||||
group.map(sub => {
|
|
||||||
if (sub.owner ? sub.owner.__owl__.isMounted : true) {
|
|
||||||
return sub.callback.call(sub.owner, rev);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
// at this point, each component in the current group has registered a
|
// at this point, each component in the current group has registered a
|
||||||
// top level fiber in the scheduler. It could happen that rendering these
|
// top level fiber in the scheduler. It could happen that rendering these
|
||||||
// components is done (if they have no children). This is why we manually
|
// components is done (if they have no children). This is why we manually
|
||||||
@@ -96,7 +90,7 @@ export class Context extends EventBus {
|
|||||||
// promise to resolve earlier, which means that there is a chance of
|
// promise to resolve earlier, which means that there is a chance of
|
||||||
// processing the next group in the same frame.
|
// processing the next group in the same frame.
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
await proms;
|
await Promise.all(proms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -111,9 +111,9 @@ export function useStore(selector, options: SelectorOptions = {}): any {
|
|||||||
|
|
||||||
useContextWithCB(store, component, function(): Promise<void> | void {
|
useContextWithCB(store, component, function(): Promise<void> | void {
|
||||||
let shouldRender = false;
|
let shouldRender = false;
|
||||||
updateFunctions.forEach(function(updateFn) {
|
for (let fn of updateFunctions) {
|
||||||
shouldRender = updateFn() || shouldRender;
|
shouldRender = fn() || shouldRender;
|
||||||
});
|
}
|
||||||
if (shouldRender) {
|
if (shouldRender) {
|
||||||
return component.render();
|
return component.render();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -572,6 +572,31 @@ describe("connecting a component to store", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("store changes occuring when mounting a component are notified", async () => {
|
||||||
|
const initialState = { x: { val: 1 } };
|
||||||
|
const actions = {
|
||||||
|
setValue({ state }, val) {
|
||||||
|
state.x.val = val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Parent extends Component<any, any> {
|
||||||
|
static template = xml`<div><t t-esc="x.val"/></div>`;
|
||||||
|
x = useStore(state => {
|
||||||
|
return Object.assign({}, state.x);
|
||||||
|
});
|
||||||
|
dispatch = useDispatch();
|
||||||
|
}
|
||||||
|
Parent.prototype.__render = jest.fn(Parent.prototype.__render);
|
||||||
|
Parent.env.store = new Store({ state: initialState, actions });
|
||||||
|
|
||||||
|
const parent = new Parent();
|
||||||
|
const prom = parent.mount(fixture);
|
||||||
|
parent.dispatch("setValue", 2);
|
||||||
|
await prom;
|
||||||
|
expect(fixture.innerHTML).toBe("<div>2</div>");
|
||||||
|
expect(Parent.prototype.__render).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
test("correct update order when parent/children are connected", async () => {
|
test("correct update order when parent/children are connected", async () => {
|
||||||
const steps: string[] = [];
|
const steps: string[] = [];
|
||||||
|
|
||||||
@@ -899,6 +924,46 @@ describe("connecting a component to store", () => {
|
|||||||
expect(steps).toEqual(["on:update", "off:update"]);
|
expect(steps).toEqual(["on:update", "off:update"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("connected child component destroyed by dispatched action", async () => {
|
||||||
|
let steps: any = [];
|
||||||
|
|
||||||
|
class Child extends Component<any, any> {
|
||||||
|
static template = xml`<div><t t-esc="store.val"/></div>`;
|
||||||
|
store = useStore(s => {
|
||||||
|
steps.push("child selector");
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
class Parent extends Component<any, any> {
|
||||||
|
static template = xml`<div><Child t-if="store.child" /></div>`;
|
||||||
|
static components = { Child };
|
||||||
|
store = useStore(s => {
|
||||||
|
steps.push("parent selector");
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
dispatch = useDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = { child: true, val: 1 };
|
||||||
|
const actions = {
|
||||||
|
toggleChild({ state }) {
|
||||||
|
state.child = !state.child;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const store = new Store({ state, actions });
|
||||||
|
(<any>env).store = store;
|
||||||
|
const parent = new Parent();
|
||||||
|
|
||||||
|
await parent.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toBe("<div><div>1</div></div>");
|
||||||
|
expect(steps).toEqual(["parent selector", "child selector"]);
|
||||||
|
|
||||||
|
parent.dispatch("toggleChild");
|
||||||
|
await nextTick();
|
||||||
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
|
expect(steps).toEqual(["parent selector", "child selector", "parent selector"]);
|
||||||
|
});
|
||||||
|
|
||||||
test("dispatch an action", async () => {
|
test("dispatch an action", async () => {
|
||||||
class App extends Component<any, any> {
|
class App extends Component<any, any> {
|
||||||
static template = xml`<div><t t-esc="store.counter"/></div>`;
|
static template = xml`<div><t t-esc="store.counter"/></div>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user