diff --git a/goml-script.md b/goml-script.md index 19f76c58..f2f9ccc1 100644 --- a/goml-script.md +++ b/goml-script.md @@ -1618,12 +1618,12 @@ set-local-storage: {"key": null} **set-property** command allows to update an element's property. Example: ``` -set-property: ("details", {"open": "false"}) +set-property: ("details", {"open": false}) // Same but with a XPath: set-property: ("//details", {"property-name": "property-value"}) // Setting multiple properties at once: -set-property: ("details", {"open": "false", "another": "x"}) +set-property: ("details", {"open": false, "another": "x"}) // Same but with a XPath: set-property: ("//details", {"open": "false", "another": "x"}) diff --git a/src/commands/dom_modifiers.js b/src/commands/dom_modifiers.js index 24f89021..10fe6fea 100644 --- a/src/commands/dom_modifiers.js +++ b/src/commands/dom_modifiers.js @@ -29,6 +29,7 @@ function innerParseCssAttribute( jsonValidator.valueTypes.ident = { allowed: ['null'], }; + jsonValidator.valueTypes.boolean = {}; } const ret = validator(parser, { @@ -55,7 +56,7 @@ function innerParseCssAttribute( } const code = []; for (const [key, value] of attributes) { - code.push(callback(key, value, value.kind === 'ident')); + code.push(callback(key, value, value.kind)); } const func = allowObjectPath ? ` function setObjValue(object, path, value) { @@ -92,9 +93,12 @@ ${indentString(code.join('\n'), 1)} // * ("selector", JSON dict) function parseSetAttribute(parser) { return innerParseCssAttribute(parser, 'attribute', 'parseSetAttributeElem', true, - (key, value, isIdent) => { - if (!isIdent) { - return `e.setAttribute("${key}","${value.value}");`; + (key, value, kind) => { + if (kind !== 'ident') { + if (kind !== 'boolean' && kind !== 'number') { + return `e.setAttribute("${key}","${value.value}");`; + } + return `e.setAttribute("${key}",${value.value});`; } return `e.removeAttribute("${key}");`; }, false); @@ -106,9 +110,11 @@ function parseSetAttribute(parser) { // * ("selector", JSON dict) function parseSetProperty(parser) { return innerParseCssAttribute(parser, 'property', 'parseSetPropertyElem', true, - (key, value, isIdent) => { + (key, value, kind) => { const k_s = value.key.kind === 'object-path' ? key : `["${key}"]`; - const arg = isIdent ? 'undefined' : `"${value.value}"`; + const arg = kind === 'ident' ? 'undefined' : + // eslint-disable-next-line no-extra-parens + (kind === 'boolean' || kind === 'number' ? `${value.value}` : `"${value.value}"`); return `setObjValue(e, ${k_s}, ${arg});`; }, true); } @@ -119,7 +125,7 @@ function parseSetProperty(parser) { // * ("selector", JSON dict) function parseSetCss(parser) { return innerParseCssAttribute(parser, 'CSS property', 'parseSetCssElem', false, - (key, value, _isIdent) => `e.style["${key}"] = "${value.value}";`, false); + (key, value, _kind) => `e.style["${key}"] = "${value.value}";`, false); } // Possible inputs: diff --git a/src/commands/utils.js b/src/commands/utils.js index 2c58a37d..c0cb5136 100644 --- a/src/commands/utils.js +++ b/src/commands/utils.js @@ -126,7 +126,6 @@ ${varValue} + '\` (for NEAR check)'); }`; } } - // eslint-disable-next-line no-extra-parens const hasSpecialChecks = checks.length !== 0; if (checks.length === 0) { if (assertFalse) { diff --git a/tests/api-output/parseSetAttribute/basic-7.toml b/tests/api-output/parseSetAttribute/basic-7.toml new file mode 100644 index 00000000..a5204aea --- /dev/null +++ b/tests/api-output/parseSetAttribute/basic-7.toml @@ -0,0 +1,7 @@ +instructions = [ + """const parseSetAttributeElem = await page.$(\"a\"); +if (parseSetAttributeElem === null) { throw '\"a\" not found'; } +await page.evaluate(e => { + e.setAttribute(\"b\",true); +}, parseSetAttributeElem);""", +] diff --git a/tests/api-output/parseSetAttribute/basic-8.toml b/tests/api-output/parseSetAttribute/basic-8.toml new file mode 100644 index 00000000..e89c6df1 --- /dev/null +++ b/tests/api-output/parseSetAttribute/basic-8.toml @@ -0,0 +1,7 @@ +instructions = [ + """const parseSetAttributeElem = await page.$(\"a\"); +if (parseSetAttributeElem === null) { throw '\"a\" not found'; } +await page.evaluate(e => { + e.setAttribute(\"b\",12); +}, parseSetAttributeElem);""", +] diff --git a/tests/api-output/parseSetAttribute/err-10.toml b/tests/api-output/parseSetAttribute/err-10.toml index b57108c1..2d8b91fd 100644 --- a/tests/api-output/parseSetAttribute/err-10.toml +++ b/tests/api-output/parseSetAttribute/err-10.toml @@ -1 +1 @@ -error = """type \"json\" (`{\"a\": \"x\"}`) is not allowed as value in this JSON dict, allowed types are: [`ident`, `number`, `string`] (second element of the tuple)""" +error = """type \"json\" (`{\"a\": \"x\"}`) is not allowed as value in this JSON dict, allowed types are: [`boolean`, `ident`, `number`, `string`] (second element of the tuple)""" diff --git a/tests/api-output/parseSetAttribute/err-11.toml b/tests/api-output/parseSetAttribute/err-11.toml index 2ef8a8dc..50f41b00 100644 --- a/tests/api-output/parseSetAttribute/err-11.toml +++ b/tests/api-output/parseSetAttribute/err-11.toml @@ -1 +1 @@ -error = """type \"array\" (`[\"a\"]`) is not allowed as value in this JSON dict, allowed types are: [`ident`, `number`, `string`] (second element of the tuple)""" +error = """type \"array\" (`[\"a\"]`) is not allowed as value in this JSON dict, allowed types are: [`boolean`, `ident`, `number`, `string`] (second element of the tuple)""" diff --git a/tests/api-output/parseSetCss/basic-7.toml b/tests/api-output/parseSetCss/basic-7.toml new file mode 100644 index 00000000..482ffac9 --- /dev/null +++ b/tests/api-output/parseSetCss/basic-7.toml @@ -0,0 +1 @@ +error = """type \"boolean\" (`true`) is not allowed as value in this JSON dict, allowed types are: [`number`, `string`] (second element of the tuple)""" diff --git a/tests/api-output/parseSetCss/basic-8.toml b/tests/api-output/parseSetCss/basic-8.toml new file mode 100644 index 00000000..86973631 --- /dev/null +++ b/tests/api-output/parseSetCss/basic-8.toml @@ -0,0 +1,7 @@ +instructions = [ + """const parseSetCssElem = await page.$(\"a\"); +if (parseSetCssElem === null) { throw '\"a\" not found'; } +await page.evaluate(e => { + e.style[\"b\"] = \"12\"; +}, parseSetCssElem);""", +] diff --git a/tests/api-output/parseSetProperty/basic-7.toml b/tests/api-output/parseSetProperty/basic-7.toml new file mode 100644 index 00000000..c2c9195d --- /dev/null +++ b/tests/api-output/parseSetProperty/basic-7.toml @@ -0,0 +1,24 @@ +instructions = [ + """const parseSetPropertyElem = await page.$(\"a\"); +if (parseSetPropertyElem === null) { throw '\"a\" not found'; } +await page.evaluate(e => { + function setObjValue(object, path, value) { + for (let i = 0; i < path.length - 1; ++i) { + const subPath = path[i]; + if (object[subPath] === undefined || object[subPath] === null) { + if (value === undefined) { + return; + } + object[subPath] = {}; + } + object = object[subPath]; + } + if (value === undefined) { + delete object[path[path.length - 1]]; + } else { + object[path[path.length - 1]] = value; + } + } + setObjValue(e, [\"b\"], true); +}, parseSetPropertyElem);""", +] diff --git a/tests/api-output/parseSetProperty/basic-8.toml b/tests/api-output/parseSetProperty/basic-8.toml new file mode 100644 index 00000000..4656eb12 --- /dev/null +++ b/tests/api-output/parseSetProperty/basic-8.toml @@ -0,0 +1,24 @@ +instructions = [ + """const parseSetPropertyElem = await page.$(\"a\"); +if (parseSetPropertyElem === null) { throw '\"a\" not found'; } +await page.evaluate(e => { + function setObjValue(object, path, value) { + for (let i = 0; i < path.length - 1; ++i) { + const subPath = path[i]; + if (object[subPath] === undefined || object[subPath] === null) { + if (value === undefined) { + return; + } + object[subPath] = {}; + } + object = object[subPath]; + } + if (value === undefined) { + delete object[path[path.length - 1]]; + } else { + object[path[path.length - 1]] = value; + } + } + setObjValue(e, [\"b\"], 12); +}, parseSetPropertyElem);""", +] diff --git a/tests/api-output/parseSetProperty/err-10.toml b/tests/api-output/parseSetProperty/err-10.toml index b57108c1..2d8b91fd 100644 --- a/tests/api-output/parseSetProperty/err-10.toml +++ b/tests/api-output/parseSetProperty/err-10.toml @@ -1 +1 @@ -error = """type \"json\" (`{\"a\": \"x\"}`) is not allowed as value in this JSON dict, allowed types are: [`ident`, `number`, `string`] (second element of the tuple)""" +error = """type \"json\" (`{\"a\": \"x\"}`) is not allowed as value in this JSON dict, allowed types are: [`boolean`, `ident`, `number`, `string`] (second element of the tuple)""" diff --git a/tests/api-output/parseSetProperty/err-11.toml b/tests/api-output/parseSetProperty/err-11.toml index 2ef8a8dc..50f41b00 100644 --- a/tests/api-output/parseSetProperty/err-11.toml +++ b/tests/api-output/parseSetProperty/err-11.toml @@ -1 +1 @@ -error = """type \"array\" (`[\"a\"]`) is not allowed as value in this JSON dict, allowed types are: [`ident`, `number`, `string`] (second element of the tuple)""" +error = """type \"array\" (`[\"a\"]`) is not allowed as value in this JSON dict, allowed types are: [`boolean`, `ident`, `number`, `string`] (second element of the tuple)""" diff --git a/tools/api.js b/tools/api.js index af31f876..f5157ec2 100644 --- a/tools/api.js +++ b/tools/api.js @@ -557,6 +557,9 @@ function checkAttributeProperty(x, func) { func('("a", {"b": "c", "d": "e"})', 'basic-4'); func('("a", {"b": null})', 'basic-5'); func('("a", {"b": null, "a": "b"})', 'basic-6'); + // This one will fail for `set-css`. + func('("a", {"b": true})', 'basic-7'); + func('("a", {"b": 12})', 'basic-8'); // XPath func('("/a", "b", "c")', 'xpath-1');