From e71755c7c4d7fb284a33095c1cd2cb4b9e26d9df Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Feb 2024 23:21:43 +0100 Subject: [PATCH 1/2] Port `parseAssertAttributeInner` to validator --- src/commands/assert.js | 95 ++++++++++++++++++++---------------------- src/validator.js | 9 +++- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/commands/assert.js b/src/commands/assert.js index d23f8ef3d..911120a79 100644 --- a/src/commands/assert.js +++ b/src/commands/assert.js @@ -478,43 +478,51 @@ function parseAssertPropertyFalse(parser) { } function parseAssertAttributeInner(parser, assertFalse) { - const err = 'Read the documentation to see the accepted inputs'; - const elems = parser.elems; - const identifiers = ['ALL', 'CONTAINS', 'STARTS_WITH', 'ENDS_WITH', 'NEAR']; + const identifiers = ['CONTAINS', 'ENDS_WITH', 'STARTS_WITH', 'NEAR', 'ALL']; + const jsonValidator = { + kind: 'json', + keyTypes: { + 'string': [], + }, + valueTypes: { + 'string': [], 'number': [], 'ident': ['null'], + }, + }; + const ret = validator(parser, + { + kind: 'tuple', + elements: [ + { kind: 'selector' }, + jsonValidator, + { + kind: 'ident', + allowed: identifiers, + optional: true, + alternatives: [ + { + kind: 'array', + valueTypes: { + 'ident': identifiers, + }, + }, + ], + }, + ], + }, + ); + if (ret.error !== undefined) { + return ret; + } + + const tuple = ret.value; const warnings = []; - const enabledChecks = Object.create(null); + const enabledChecks = new Set(); - if (elems.length === 0) { - return { - 'error': 'expected a tuple, found nothing. ' + err, - }; - } else if (elems.length !== 1 || elems[0].kind !== 'tuple') { - return {'error': `expected a tuple, found \`${parser.getRawArgs()}\`. ${err}`}; - } - const tuple = elems[0].getRaw(); - if (tuple.length < 2 || tuple.length > 3) { - return { - 'error': 'invalid number of values in the tuple (expected 2 or 3, found ' + - tuple.length + '), ' + err, - }; - } else if (tuple[0].kind !== 'string') { - return { - 'error': 'expected a CSS selector or an XPath as first argument, ' + - `found ${tuple[0].getArticleKind()}`, - }; - } else if (tuple[1].kind !== 'json') { - return { - 'error': 'expected a JSON dictionary as second argument, found ' + - `\`${tuple[1].getErrorText()}\` (${tuple[1].getArticleKind()})`, - }; - } else if (tuple.length === 3) { - const ret = fillEnabledChecks(tuple[2], identifiers, enabledChecks, warnings, 'third'); - if (ret !== null) { - return ret; - } + if (tuple.length > 2) { + fillEnabledChecksV2(tuple[2], enabledChecks, warnings, 'third'); } - const selector = tuple[0].getSelector(); + const selector = tuple[0].value; const xpath = selector.isXPath ? 'XPath ' : 'selector '; const varName = 'parseAssertElemAttr'; @@ -525,17 +533,8 @@ function parseAssertAttributeInner(parser, assertFalse) { const { checks, hasSpecialChecks } = makeExtendedChecks( enabledChecks, assertFalse, 'nonMatchingAttrs', 'attribute', 'attr', varKey, varValue); - const json = tuple[1].getRaw(); - const entries = validateJson( - json, - {'string': [], 'number': [], 'ident': ['null']}, - 'attribute', - ); - if (entries.error !== undefined) { - return entries; - } + const json = tuple[1].value; const isPseudo = !selector.isXPath && selector.pseudo !== null; - warnings.push(...entries.warnings); if (isPseudo) { warnings.push(`Pseudo-elements (\`${selector.pseudo}\`) don't have attributes so \ the check will be performed on the element itself`); @@ -544,7 +543,7 @@ the check will be performed on the element itself`); // JSON.stringify produces a problematic output so instead we use this. const tests = []; const nullAttributes = []; - for (const [k, v] of Object.entries(entries.values)) { + for (const [k, v] of json) { if (v.kind !== 'ident') { tests.push(`"${k}":"${v.value}"`); } else { @@ -553,10 +552,8 @@ the check will be performed on the element itself`); } if (nullAttributes.length > 0 && hasSpecialChecks) { - const k = Object.entries(enabledChecks) - .filter(([k, v]) => v && k !== 'ALL') - .map(([k, _]) => k); - warnings.push(`Special checks (${k.join(', ')}) will be ignored for \`null\``); + const k = [...enabledChecks].filter(k => k !== 'ALL').join(', '); + warnings.push(`Special checks (${k}) will be ignored for \`null\``); } let noAttrError = ''; @@ -594,7 +591,7 @@ if (nonMatchingAttrs.length !== 0) { }`; let instructions; - if (enabledChecks['ALL'] === true) { + if (enabledChecks.has('ALL')) { instructions = `\ ${getAndSetElements(selector, varName, true)} for (let i = 0, len = ${varName}.length; i < len; ++i) { diff --git a/src/validator.js b/src/validator.js index d043177e9..0285be291 100644 --- a/src/validator.js +++ b/src/validator.js @@ -152,7 +152,7 @@ function validateIdent(parser, allowedSyntax, validator) { } else if (!allowedSyntax.allowed.includes(parser.value)) { return validator.makeError( `unexpected ${parser.kind} \`${parser.getErrorText()}\`. Allowed ${parser.kind}s are: \ -[${allowedSyntax.allowed.map(v => `\`${v}\``).join(', ')}]`, +${listValues(allowedSyntax.allowed)}`, ); } return parser; @@ -294,7 +294,7 @@ this JSON dict, allowed types are: ${Object.keys(allowedSyntax.valueTypes).join( } else if (allowedForValue.length !== 0 && !allowedForValue.includes(value.value)) { return validator.makeError( `unexpected ${value.kind} \`${value.getErrorText()}\`. Allowed ${value.kind}s are: \ -[${allowedForValue.map(v => `\`${v}\``).join(', ')}]`, +${listValues(allowedForValue)}`, ); } entries.set(key_s, { @@ -305,6 +305,11 @@ this JSON dict, allowed types are: ${Object.keys(allowedSyntax.valueTypes).join( return entries; } +function listValues(values) { + values.sort(); + return `[${values.map(v => `\`${v}\``).join(', ')}]`; +} + function isObject(obj) { return typeof obj === 'object' && !Array.isArray(obj) && obj !== null; } From e56902ef2e41d721dcefead515e256ea1177f231 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Feb 2024 23:21:50 +0100 Subject: [PATCH 2/2] Update error messages --- tests/test-js/api-output/parseAssertAttribute/err-1.toml | 6 +++++- tests/test-js/api-output/parseAssertAttribute/err-2.toml | 6 +++++- tests/test-js/api-output/parseAssertAttribute/err-5.toml | 6 +++++- tests/test-js/api-output/parseAssertAttribute/err-6.toml | 6 +++++- tests/test-js/api-output/parseAssertAttribute/err-7.toml | 6 +++++- tests/test-js/api-output/parseAssertAttribute/err-8.toml | 6 +++++- .../api-output/parseAssertAttribute/multiline-1.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-1.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-2.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-5.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-6.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-7.toml | 6 +++++- .../test-js/api-output/parseAssertAttributeFalse/err-8.toml | 6 +++++- .../api-output/parseAssertAttributeFalse/multiline-1.toml | 6 +++++- .../api-output/parseAssertDocumentProperty/err-6.toml | 2 +- .../api-output/parseAssertDocumentPropertyFalse/err-6.toml | 2 +- tests/test-js/api-output/parseAssertProperty/err-6.toml | 2 +- tests/test-js/api-output/parseAssertProperty/err-7.toml | 2 +- .../test-js/api-output/parseAssertPropertyFalse/err-6.toml | 2 +- .../test-js/api-output/parseAssertPropertyFalse/err-7.toml | 2 +- .../test-js/api-output/parseAssertWindowProperty/err-6.toml | 2 +- .../api-output/parseAssertWindowPropertyFalse/err-6.toml | 2 +- 22 files changed, 78 insertions(+), 22 deletions(-) diff --git a/tests/test-js/api-output/parseAssertAttribute/err-1.toml b/tests/test-js/api-output/parseAssertAttribute/err-1.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-1.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-1.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/err-2.toml b/tests/test-js/api-output/parseAssertAttribute/err-2.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-2.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-2.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/err-5.toml b/tests/test-js/api-output/parseAssertAttribute/err-5.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-5.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-5.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/err-6.toml b/tests/test-js/api-output/parseAssertAttribute/err-6.toml index 1cf6e5603..0fb5fd8d8 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-6.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-6.toml @@ -1 +1,5 @@ -error = """unknown identifier `all`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `all`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/err-7.toml b/tests/test-js/api-output/parseAssertAttribute/err-7.toml index 5f8ec2cee..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-7.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-7.toml @@ -1 +1,5 @@ -error = """unknown identifier `ALLO`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/err-8.toml b/tests/test-js/api-output/parseAssertAttribute/err-8.toml index 93095ec1b..3bb487547 100644 --- a/tests/test-js/api-output/parseAssertAttribute/err-8.toml +++ b/tests/test-js/api-output/parseAssertAttribute/err-8.toml @@ -1 +1,5 @@ -error = """attribute `b` is duplicated""" +level = 2 +error = """`b` key is duplicated in JSON dict""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttribute/multiline-1.toml b/tests/test-js/api-output/parseAssertAttribute/multiline-1.toml index 5f8ec2cee..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertAttribute/multiline-1.toml +++ b/tests/test-js/api-output/parseAssertAttribute/multiline-1.toml @@ -1 +1,5 @@ -error = """unknown identifier `ALLO`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-1.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-1.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-1.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-1.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-2.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-2.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-2.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-2.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-5.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-5.toml index f0b4d0fc3..9b472dfb8 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-5.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-5.toml @@ -1 +1,5 @@ -error = """expected a JSON dictionary as second argument, found `\"b\"` (a string)""" +level = 1 +error = """expected second element of the tuple to be a JSON dict, found `\"b\"` (a string)""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-6.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-6.toml index 1cf6e5603..0fb5fd8d8 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-6.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-6.toml @@ -1 +1,5 @@ -error = """unknown identifier `all`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `all`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-7.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-7.toml index 5f8ec2cee..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-7.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-7.toml @@ -1 +1,5 @@ -error = """unknown identifier `ALLO`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/err-8.toml b/tests/test-js/api-output/parseAssertAttributeFalse/err-8.toml index 93095ec1b..3bb487547 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/err-8.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/err-8.toml @@ -1 +1,5 @@ -error = """attribute `b` is duplicated""" +level = 2 +error = """`b` key is duplicated in JSON dict""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertAttributeFalse/multiline-1.toml b/tests/test-js/api-output/parseAssertAttributeFalse/multiline-1.toml index 5f8ec2cee..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertAttributeFalse/multiline-1.toml +++ b/tests/test-js/api-output/parseAssertAttributeFalse/multiline-1.toml @@ -1 +1,5 @@ -error = """unknown identifier `ALLO`. Available identifiers are: [`ALL`, `CONTAINS`, `STARTS_WITH`, `ENDS_WITH`, `NEAR`]""" +level = 2 +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" +path = [ +] +typeError = false diff --git a/tests/test-js/api-output/parseAssertDocumentProperty/err-6.toml b/tests/test-js/api-output/parseAssertDocumentProperty/err-6.toml index 91f7b3d59..9daa8ce6d 100644 --- a/tests/test-js/api-output/parseAssertDocumentProperty/err-6.toml +++ b/tests/test-js/api-output/parseAssertDocumentProperty/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`]""" +error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertDocumentPropertyFalse/err-6.toml b/tests/test-js/api-output/parseAssertDocumentPropertyFalse/err-6.toml index 91f7b3d59..9daa8ce6d 100644 --- a/tests/test-js/api-output/parseAssertDocumentPropertyFalse/err-6.toml +++ b/tests/test-js/api-output/parseAssertDocumentPropertyFalse/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`]""" +error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertProperty/err-6.toml b/tests/test-js/api-output/parseAssertProperty/err-6.toml index debf1d093..0fb5fd8d8 100644 --- a/tests/test-js/api-output/parseAssertProperty/err-6.toml +++ b/tests/test-js/api-output/parseAssertProperty/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`, `ALL`]""" +error = """unexpected ident `all`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertProperty/err-7.toml b/tests/test-js/api-output/parseAssertProperty/err-7.toml index fd7501b51..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertProperty/err-7.toml +++ b/tests/test-js/api-output/parseAssertProperty/err-7.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `ALLO`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`, `ALL`]""" +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertPropertyFalse/err-6.toml b/tests/test-js/api-output/parseAssertPropertyFalse/err-6.toml index debf1d093..0fb5fd8d8 100644 --- a/tests/test-js/api-output/parseAssertPropertyFalse/err-6.toml +++ b/tests/test-js/api-output/parseAssertPropertyFalse/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`, `ALL`]""" +error = """unexpected ident `all`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertPropertyFalse/err-7.toml b/tests/test-js/api-output/parseAssertPropertyFalse/err-7.toml index fd7501b51..e32991cdb 100644 --- a/tests/test-js/api-output/parseAssertPropertyFalse/err-7.toml +++ b/tests/test-js/api-output/parseAssertPropertyFalse/err-7.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `ALLO`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`, `ALL`]""" +error = """unexpected ident `ALLO`. Allowed idents are: [`ALL`, `CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertWindowProperty/err-6.toml b/tests/test-js/api-output/parseAssertWindowProperty/err-6.toml index 91f7b3d59..9daa8ce6d 100644 --- a/tests/test-js/api-output/parseAssertWindowProperty/err-6.toml +++ b/tests/test-js/api-output/parseAssertWindowProperty/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`]""" +error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false diff --git a/tests/test-js/api-output/parseAssertWindowPropertyFalse/err-6.toml b/tests/test-js/api-output/parseAssertWindowPropertyFalse/err-6.toml index 91f7b3d59..9daa8ce6d 100644 --- a/tests/test-js/api-output/parseAssertWindowPropertyFalse/err-6.toml +++ b/tests/test-js/api-output/parseAssertWindowPropertyFalse/err-6.toml @@ -1,5 +1,5 @@ level = 2 -error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `STARTS_WITH`, `NEAR`]""" +error = """unexpected ident `all`. Allowed idents are: [`CONTAINS`, `ENDS_WITH`, `NEAR`, `STARTS_WITH`]""" path = [ ] typeError = false