Skip to content

Commit

Permalink
Merge pull request #616 from GuillaumeGomez/wait-false
Browse files Browse the repository at this point in the history
Add `wait-for-document-property-false` and `wait-for-window-property-false` commands
  • Loading branch information
GuillaumeGomez authored Sep 26, 2024
2 parents 03978e1 + d83d59a commit d57a12a
Show file tree
Hide file tree
Showing 45 changed files with 1,703 additions and 9 deletions.
60 changes: 58 additions & 2 deletions goml-script.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,14 @@ Here's the command list:
* [`wait-for-css`](#wait-for-css)
* [`wait-for-css-false`](#wait-for-css-false)
* [`wait-for-document-property`](#wait-for-document-property)
* [`wait-for-document-property-false`](#wait-for-document-property-false)
* [`wait-for-local-storage`](#wait-for-local-storage)
* [`wait-for-position`](#wait-for-position)
* [`wait-for-property`](#wait-for-property)
* [`wait-for-text`](#wait-for-text)
* [`wait-for-size`](#wait-for-size)
* [`wait-for-window-property`](#wait-for-window-property)
* [`wait-for-window-property-false`](#wait-for-window-property-false)
* [`write`](#write)
* [`write-into`](#write-into)

Expand Down Expand Up @@ -2053,7 +2055,7 @@ wait-for-document-property: {"key": "value", "key2": "value2"}
wait-for-document-property: {"key"."sub-key": "value"}
```

You can use more specific checks as well by using one of the following identifiers: CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".
You can use more specific checks as well by using one of the following identifiers: "CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".

Examples:

Expand All @@ -2062,6 +2064,33 @@ wait-for-document-property: ({"key": "value"}, ENDS_WITH)
wait-for-document-property: ({"key": "value", "key2": "value2"}, [ENDS_WITH, STARTS_WITH])
```

If you want to wait for at least one of the properties to not have the expected value, take a look at [`wait-for-document-property-false`](#wait-for-document-property-false).

#### wait-for-document-property-false

**wait-for-document-property-false** command waits for at least one of the document objects properties to not have the expected values. It'll wait up to 30 seconds by default before failing (can be changed with the [`timeout`](#timeout) command).

Examples:

```
wait-for-document-property-false: {"key": "value"}
wait-for-document-property-false: {"key": "value", "key2": "value2"}
// You can also use object-paths:
wait-for-document-property-false: {"key"."sub-key": "value"}
```

You can use more specific checks as well by using one of the following identifiers: "CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".

Examples:

```
wait-for-document-property-false: ({"key": "value"}, ENDS_WITH)
wait-for-document-property-false: ({"key": "value", "key2": "value2"}, [ENDS_WITH, STARTS_WITH])
```

If you want to wait for all properties to have the expected value, take a look at [`wait-for-document-property`](#wait-for-document-property).

#### wait-for-local-storage

**wait-for-local-storage** command waits for the local storage keys to have the expected values. It'll wait up to 30 seconds by default before failing (can be changed with the [`timeout`](#timeout) command).
Expand Down Expand Up @@ -2192,7 +2221,7 @@ wait-for-window-property: {"key": "value", "key2": "value2"}
wait-for-window-property: {"key"."sub-key": "value"}
```

You can use more specific checks as well by using one of the following identifiers: CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".
You can use more specific checks as well by using one of the following identifiers: "CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".

Examples:

Expand All @@ -2201,6 +2230,33 @@ wait-for-window-property: ({"key": "value"}, ENDS_WITH)
wait-for-window-property: ({"key": "value", "key2": "value2"}, [ENDS_WITH, STARTS_WITH])
```

If you want to wait for at least one of the properties to not have the expected value, take a look at [`wait-for-window-property-false`](#wait-for-window-property-false).

#### wait-for-window-property-false

**wait-for-window-property-false** command waits for at least one of the window objects properties to not have the expected values. It'll wait up to 30 seconds by default before failing (can be changed with the [`timeout`](#timeout) command).

Examples:

```
wait-for-window-property-false: {"key": "value"}
wait-for-window-property-false: {"key": "value", "key2": "value2"}
// You can also use object-paths:
wait-for-window-property-false: {"key"."sub-key": "value"}
```

You can use more specific checks as well by using one of the following identifiers: "CONTAINS", "ENDS_WITH", "STARTS_WITH", or "NEAR".

Examples:

```
wait-for-window-property-false: ({"key": "value"}, ENDS_WITH)
wait-for-window-property-false: ({"key": "value", "key2": "value2"}, [ENDS_WITH, STARTS_WITH])
```

If you want to wait for all properties to have the expected value, take a look at [`wait-for-window-property`](#wait-for-window-property).

#### write

**write** command sends keyboard inputs on the currently focused element. Examples:
Expand Down
2 changes: 2 additions & 0 deletions src/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ const ORDERS = {
'wait-for-count': commands.parseWaitForCount,
'wait-for-count-false': commands.parseWaitForCountFalse,
'wait-for-document-property': commands.parseWaitForDocumentProperty,
'wait-for-document-property-false': commands.parseWaitForDocumentPropertyFalse,
'wait-for-local-storage': commands.parseWaitForLocalStorage,
'wait-for-position': commands.parseWaitForPosition,
'wait-for-property': commands.parseWaitForProperty,
'wait-for-size': commands.parseWaitForSize,
'wait-for-text': commands.parseWaitForText,
'wait-for-window-property': commands.parseWaitForWindowProperty,
'wait-for-window-property-false': commands.parseWaitForWindowPropertyFalse,
'write': commands.parseWrite,
'write-into': commands.parseWriteInto,
};
Expand Down
2 changes: 2 additions & 0 deletions src/commands/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ module.exports = {
'parseWaitForCount': wait.parseWaitForCount,
'parseWaitForCountFalse': wait.parseWaitForCountFalse,
'parseWaitForDocumentProperty': wait.parseWaitForDocumentProperty,
'parseWaitForDocumentPropertyFalse': wait.parseWaitForDocumentPropertyFalse,
'parseWaitForLocalStorage': wait.parseWaitForLocalStorage,
'parseWaitForPosition': wait.parseWaitForPosition,
'parseWaitForProperty': wait.parseWaitForProperty,
'parseWaitForSize': wait.parseWaitForSize,
'parseWaitForText': wait.parseWaitForText,
'parseWaitForWindowProperty': wait.parseWaitForWindowProperty,
'parseWaitForWindowPropertyFalse': wait.parseWaitForWindowPropertyFalse,
'parseWrite': input.parseWrite,
'parseWriteInto': input.parseWriteInto,
};
33 changes: 28 additions & 5 deletions src/commands/wait.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ throw new Error("The following local storage entries still don't match: [" + err
};
}

function parseWaitForObjectProperty(parser, objName) {
function parseWaitForObjectProperty(parser, objName, waitFalse) {
const identifiers = ['CONTAINS', 'ENDS_WITH', 'NEAR', 'STARTS_WITH'];
const jsonValidator = {
kind: 'json',
Expand Down Expand Up @@ -353,6 +353,13 @@ function parseWaitForObjectProperty(parser, objName) {
warnings.push(`Special checks (${k}) will be ignored for \`null\``);
}

let comp = '===';
let errorMessage = `"The following ${objName} properties still don't match: [" + errs + "]"`;
if (waitFalse) {
comp = '!==';
errorMessage = `"The ${objName} properties still all match"`;
}

const instructions = getWaitForElems(
varName,
`\
Expand Down Expand Up @@ -386,12 +393,12 @@ ${indentString(checks.join('\n'), 3)}
}
return errors;
});
if (${varName}.length === 0) {
if (${varName}.length ${comp} 0) {
break;
}`,
`\
const errs = ${varName}.join(", ");
throw new Error("The following ${objName} properties still don't match: [" + errs + "]");`,
throw new Error(${errorMessage});`,
);

return {
Expand All @@ -406,14 +413,28 @@ throw new Error("The following ${objName} properties still don't match: [" + err
//
// * JSON dict
function parseWaitForDocumentProperty(parser) {
return parseWaitForObjectProperty(parser, 'document');
return parseWaitForObjectProperty(parser, 'document', false);
}

// Possible inputs:
//
// * JSON dict
function parseWaitForDocumentPropertyFalse(parser) {
return parseWaitForObjectProperty(parser, 'document', true);
}

// Possible inputs:
//
// * JSON dict
function parseWaitForWindowProperty(parser) {
return parseWaitForObjectProperty(parser, 'window');
return parseWaitForObjectProperty(parser, 'window', false);
}

// Possible inputs:
//
// * JSON dict
function parseWaitForWindowPropertyFalse(parser) {
return parseWaitForObjectProperty(parser, 'window', true);
}

// Possible inputs:
Expand Down Expand Up @@ -1219,10 +1240,12 @@ module.exports = {
'parseWaitForCss': parseWaitForCss,
'parseWaitForCssFalse': parseWaitForCssFalse,
'parseWaitForDocumentProperty': parseWaitForDocumentProperty,
'parseWaitForDocumentPropertyFalse': parseWaitForDocumentPropertyFalse,
'parseWaitForLocalStorage': parseWaitForLocalStorage,
'parseWaitForPosition': parseWaitForPosition,
'parseWaitForProperty': parseWaitForProperty,
'parseWaitForText': parseWaitForText,
'parseWaitForWindowProperty': parseWaitForWindowProperty,
'parseWaitForWindowPropertyFalse': parseWaitForWindowPropertyFalse,
'parseWaitForSize': parseWaitForSize,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
instructions = [
]
warnings = [
]
wait = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
instructions = [
]
warnings = [
]
wait = false
68 changes: 68 additions & 0 deletions tests/api-output/parseWaitForDocumentPropertyFalse/basic-3.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
instructions = [
"""const timeLimit = page.getDefaultTimeout();
const timeAdd = 50;
let allTime = 0;
let property = null;
while (true) {
property = await page.evaluate(() => {
function checkObjectPaths(object, path, callback, notFoundCallback) {
const found = [];
for (const subPath of path) {
found.push(subPath);
if (object === undefined || object === null) {
notFoundCallback(found);
return;
}
object = object[subPath];
}
callback(object);
}
const errors = [];
const propertyDict = [[[\"a\"],\"b\"]];
const undefProps = [];
for (const prop of undefProps) {
checkObjectPaths(document, prop, val => {
if (val !== undefined && val !== null) {
const p = prop.map(p => `\"${p}\"`).join('.');
errors.push(\"Expected property `\" + p + \"` to not exist, found: `\" + val + \"`\");
}
}, _notFound => {},
);
}
for (const [propertyKey, propertyValue] of propertyDict) {
checkObjectPaths(document, propertyKey, val => {
if (val === undefined) {
const p = propertyKey.map(p => `\"${p}\"`).join('.');
errors.push(\"document doesn't have a property `\" + p + \"`\");
return;
}
const property = String(val);
if (property !== propertyValue) {
errors.push(\"expected `\" + propertyValue + \"` for document property `\" + propertyKey + \"`, found `\" + property + \"`\");
}
}, _notFound => {
const p = propertyKey.map(p => `\"${p}\"`).join('.');
errors.push(\"document doesn't have a property `\" + p + \"`\");
});
}
return errors;
});
if (property.length !== 0) {
break;
}
await new Promise(r => setTimeout(r, timeAdd));
if (timeLimit === 0) {
continue;
}
allTime += timeAdd;
if (allTime >= timeLimit) {
const errs = property.join(\", \");
throw new Error(\"The document properties still all match\");
}
}""",
]
wait = false
checkResult = true
warnings = [
]
68 changes: 68 additions & 0 deletions tests/api-output/parseWaitForDocumentPropertyFalse/basic-4.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
instructions = [
"""const timeLimit = page.getDefaultTimeout();
const timeAdd = 50;
let allTime = 0;
let property = null;
while (true) {
property = await page.evaluate(() => {
function checkObjectPaths(object, path, callback, notFoundCallback) {
const found = [];
for (const subPath of path) {
found.push(subPath);
if (object === undefined || object === null) {
notFoundCallback(found);
return;
}
object = object[subPath];
}
callback(object);
}
const errors = [];
const propertyDict = [[[\"a\"],\"b\"]];
const undefProps = [];
for (const prop of undefProps) {
checkObjectPaths(document, prop, val => {
if (val !== undefined && val !== null) {
const p = prop.map(p => `\"${p}\"`).join('.');
errors.push(\"Expected property `\" + p + \"` to not exist, found: `\" + val + \"`\");
}
}, _notFound => {},
);
}
for (const [propertyKey, propertyValue] of propertyDict) {
checkObjectPaths(document, propertyKey, val => {
if (val === undefined) {
const p = propertyKey.map(p => `\"${p}\"`).join('.');
errors.push(\"document doesn't have a property `\" + p + \"`\");
return;
}
const property = String(val);
if (property !== propertyValue) {
errors.push(\"expected `\" + propertyValue + \"` for document property `\" + propertyKey + \"`, found `\" + property + \"`\");
}
}, _notFound => {
const p = propertyKey.map(p => `\"${p}\"`).join('.');
errors.push(\"document doesn't have a property `\" + p + \"`\");
});
}
return errors;
});
if (property.length !== 0) {
break;
}
await new Promise(r => setTimeout(r, timeAdd));
if (timeLimit === 0) {
continue;
}
allTime += timeAdd;
if (allTime >= timeLimit) {
const errs = property.join(\", \");
throw new Error(\"The document properties still all match\");
}
}""",
]
wait = false
checkResult = true
warnings = [
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
error = """recursive types (`{\"b\": \"c\"}`) are not allowed as value in this JSON dict"""
Loading

0 comments on commit d57a12a

Please sign in to comment.