[FIX] qweb: accept assignations in qweb expressions

closes #560
closes #569
This commit is contained in:
Géry Debongnie
2019-12-12 13:17:51 +01:00
committed by aab-odoo
parent b283e65ad4
commit 4e22dbcad6
5 changed files with 85 additions and 1 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = {
// note that the space after typeof is relevant. It makes sure that the formatted
// expression has a space after typeof
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>".split(",");
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=".split(",");
type Tokenizer = (expr: string) => Token | false;
+18
View File
@@ -2026,6 +2026,24 @@ describe("other directives with t-component", () => {
expect(flag).toBe(true);
});
test("t-on with inline statement", async () => {
class Child extends Component<any, any> {
static template = xml`<span>child</span>`;
}
class Parent extends Component<any, any> {
static template = xml`<div><Child t-on-click="state.n = state.n + 1"/></div>`;
static components = { Child };
state = {n: 3};
}
const parent = new Parent();
await parent.mount(fixture);
expect(parent.state.n).toBe(3);
fixture.querySelector("span")!.click();
expect(parent.state.n).toBe(4);
});
test("t-on with handler bound to argument", async () => {
expect.assertions(3);
env.qweb.addTemplates(`
@@ -2308,6 +2308,34 @@ exports[`t-on t-on with inline statement 1`] = `
}"
`;
exports[`t-on t-on with inline statement, part 2 1`] = `
"function anonymous(context, extra
) {
// Template name: \\"test\\"
let scope = Object.create(context);
var h = this.h;
let c1 = [], p1 = {key:1,on:{}};
var vn1 = h('button', p1, c1);
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}scope['state'].flag=!scope['state'].flag};
c1.push({text: \`Toggle\`});
return vn1;
}"
`;
exports[`t-on t-on with inline statement, part 3 1`] = `
"function anonymous(context, extra
) {
// Template name: \\"test\\"
let scope = Object.create(context);
var h = this.h;
let c1 = [], p1 = {key:1,on:{}};
var vn1 = h('button', p1, c1);
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}scope['state'].n=scope['someFunction'](3)};
c1.push({text: \`Toggle\`});
return vn1;
}"
`;
exports[`t-on t-on with prevent and self modifiers (order matters) 1`] = `
"function anonymous(context, extra
) {
+31
View File
@@ -1293,6 +1293,37 @@ describe.only("t-on", () => {
expect(owner.state.counter).toBe(2);
});
test("t-on with inline statement, part 2", () => {
qweb.addTemplate("test", `<button t-on-click="state.flag = !state.flag">Toggle</button>`);
let owner = {
state: {
flag: true
}
};
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
expect(owner.state.flag).toBe(true);
(<HTMLElement>node).click();
expect(owner.state.flag).toBe(false);
(<HTMLElement>node).click();
expect(owner.state.flag).toBe(true);
});
test("t-on with inline statement, part 3", () => {
qweb.addTemplate("test", `<button t-on-click="state.n = someFunction(3)">Toggle</button>`);
let owner = {
someFunction(n) {
return n + 1;
},
state: {
n: 11
}
};
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
expect(owner.state.n).toBe(11);
(<HTMLElement>node).click();
expect(owner.state.n).toBe(4);
});
test("t-on with prevent and/or stop modifiers", async () => {
expect.assertions(7);
qweb.addTemplate(
+7
View File
@@ -170,4 +170,11 @@ describe("expression evaluation", () => {
"scope['list'].map((elem,index)=>elem+index)"
);
});
test("assignation", () => {
expect(compileExpr("a = b", {})).toBe("scope['a']=scope['b']");
expect(compileExpr("a += b", {})).toBe("scope['a']+=scope['b']");
expect(compileExpr("a -= b", {})).toBe("scope['a']-=scope['b']");
expect(compileExpr("a.b = !a.b", {})).toBe("scope['a'].b=!scope['a'].b");
});
});