Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions goml-script.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,16 @@ store-value: (effect, ":hover")
set-text: ("element" + |variable|, "something " + 2 + " something else")
```

Rules of concatenation are simple: if any of the element is a string, then it'll concatenate as a string. Examples:
Operations are handled from the left to the right. Operations between parens are performed first:

```ignore
1 + 2 + "a" // gives string "12a"
1 + 2 // gives number 3
1 + 2 + "a" + (4 * 3)
// first the parens
1 + 2 + "a" + 12
// then from left to right
3 + "a" + 12
"3a" + 12
"3a12"
```

This is just a sub-part of expressions which allow more things.
Expand Down
17 changes: 8 additions & 9 deletions src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ function replaceVariable(elem, variables, functionArgs, forceVariableAsString, e
if (associatedValue instanceof Element) {
// Nothing to be done in here.
return associatedValue;
} else if (['number', 'string', 'boolean'].includes(typeof associatedValue)) {
if (typeof associatedValue === 'boolean') {
return new IdentElement(
associatedValue.toString(), startPos, endPos, lineNumber);
} else if (typeof associatedValue === 'number' ||
// eslint-disable-next-line no-extra-parens
(!forceVariableAsString && matchInteger(associatedValue) === true)) {
return new NumberElement(associatedValue, startPos, endPos, lineNumber);
}
} else if (typeof associatedValue === 'boolean') {
return new IdentElement(
associatedValue.toString(), startPos, endPos, lineNumber);
} else if (typeof associatedValue === 'number' ||
// eslint-disable-next-line no-extra-parens
(!forceVariableAsString && matchInteger(associatedValue) === true)) {
return new NumberElement(associatedValue, startPos, endPos, lineNumber);
} else if (typeof associatedValue === 'string') {
return new StringElement(
associatedValue,
startPos,
Expand Down
10 changes: 5 additions & 5 deletions src/commands/navigation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Commands changing the current location or reloading the page.

const { cleanString } = require('../parser.js');
const { hasError } = require('../utils.js');
const { validator } = require('../validator.js');

Expand All @@ -22,7 +21,8 @@ function parseGoTo(parser) {
return ret;
}

const path = ret.value.value.trim();
const path = ret.value.getStringValue();
const code = ret.value.displayInCode();

let goto_arg;
const permissions = 'await arg.browser.overridePermissions(page.url(), arg.permissions);';
Expand All @@ -32,11 +32,11 @@ function parseGoTo(parser) {
|| path.startsWith('www.') === true
|| path.startsWith('file://') === true
) {
goto_arg = `"${cleanString(path)}"`;
goto_arg = code;
} else if (path.startsWith('.')) {
goto_arg = `page.url().split("/").slice(0, -1).join("/") + "/${cleanString(path)}"`;
goto_arg = `page.url().split("/").slice(0, -1).join("/") + "/" + ${code}`;
} else if (path.startsWith('/')) {
goto_arg = `page.url().split("/").slice(0, -1).join("/") + "${cleanString(path)}"`;
goto_arg = `page.url().split("/").slice(0, -1).join("/") + ${code}`;
} else {
return {'error': `a relative path or a full URL was expected, found \`${path}\``};
}
Expand Down
85 changes: 30 additions & 55 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function isLetter(c) {
function matchInteger(s) {
if (typeof s === 'number' || s instanceof Number) {
return true;
} else if (typeof s === 'string' || s instanceof String) {
} else if ((typeof s === 'string' || s instanceof String) && s.length !== 0) {
for (let i = s.length - 1; i >= 0; --i) {
if (!isNumber(s.charAt(i))) {
return false;
Expand Down Expand Up @@ -158,39 +158,6 @@ function isArrayElementCompatible(expected, elem) {
return expected.kind === elem.kind;
}

// Used to concatenate all elements into a string, like `1 + "a" + 12` -> "1a12".
function concatExprAsString(elems) {
let out = '';
for (const elem of elems) {
if (elem.kind === 'operator') {
continue;
} else if (['number', 'string', 'boolean'].includes(elem.kind)) {
out += elem.value;
} else {
out += concatExprAsString(elem.value);
}
}
return out;
}

function concatExprAsObjectPath(elems) {
let s = '';
const parts = [];

for (const elem of elems) {
if (elem.kind === 'operator') {
continue;
} else if (elem.kind !== 'object-path') {
s += concatExprAsString([elem]);
} else {
elem.value[0].value = s + elem.value[0].value;
parts.push(...elem.value);
s = '';
}
}
return parts;
}

// This function is used when generating an expression interpreted as a boolean.
function concatExprAsExpr(elems) {
const out = [];
Expand Down Expand Up @@ -261,24 +228,19 @@ function canBeCompared(kind1, kind2) {
}

function convertAsString(elem) {
if (elem.value.some(v => v.kind === 'object-path')) {
return new ObjectPathElement(
concatExprAsObjectPath(elem.value),
elem.startPos,
elem.endPos,
elem.fullText,
elem.line,
elem.error,
);
}
return new StringElement(
concatExprAsString(elem.value),
elem.startPos,
elem.endPos,
elem.fullText,
elem.line,
elem.error,
);
const pos = elem.value.findIndex(v => v.kind === 'object-path');
elem.kind = 'string';
if (pos !== -1) {
// We remove the object-path from the expression.
const objPath = elem.value.pop();
// We remove the first item of the object path and push it at the end of the expression.
elem.value.push(...objPath.value.splice(0, 1));
// We put the expression as the first element of the object path.
objPath.value.splice(0, 0, elem);
// All done!
return objPath;
}
return elem;
}

function convertExprAs(elem, convertAs) {
Expand Down Expand Up @@ -363,7 +325,8 @@ class Element {
}

isRecursive() {
// Only Tuple and JSON elements are "recursive" (meaning they can contain sub-levels).
// Expression, Array, Tuple and JSON elements are "recursive" (meaning they can contain
// sub-levels).
return false;
}

Expand Down Expand Up @@ -433,6 +396,18 @@ class ExpressionElement extends Element {
super('expression', value, startPos, endPos, fullText, line, error);
}

isRecursive() {
return true;
}

displayInCode() {
return this.value.map(v => v.displayInCode()).join('');
}

getStringValue() {
return this.value.map(v => v.getStringValue()).join('');
}

clone() {
const elems = this.value.map(elem => elem.clone());
return new this.constructor(
Expand Down Expand Up @@ -537,8 +512,8 @@ class ObjectPathElement extends Element {
super('object-path', value, startPos, endPos, fullText, line, error);
}

getStringValue(trim, clean = true) {
const content = this.value.map(v => `"${v.getStringValue(clean)}"`).join(',');
getStringValue() {
const content = this.value.map(v => `${v.displayInCode()}`).join(',');
return `[${content}]`;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/api-output/parseGoTo/basic-4.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
instructions = [
"""const url = page.url().split(\"/\").slice(0, -1).join(\"/\") + \"/./a\";
"""const url = page.url().split(\"/\").slice(0, -1).join(\"/\") + \"/\" + \"./a\";
try {
await page.goto(url);
} catch(exc) {
Expand Down
2 changes: 1 addition & 1 deletion tests/api-output/parseGoTo/var-1.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
instructions = [
"""const url = \"file://foo/a\";
"""const url = \"file://\"+\"foo\"+\"/a\";
try {
await page.goto(url);
} catch(exc) {
Expand Down
2 changes: 1 addition & 1 deletion tests/api-output/parseGoTo/var-3.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
instructions = [
"""const url = \"http://foo/tadam/fa\";
"""const url = \"http://foo/\"+\"tadam/\"+\"fa\";
try {
await page.goto(url);
} catch(exc) {
Expand Down
2 changes: 1 addition & 1 deletion tests/api-output/parseGoTo/var-4.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
instructions = [
"""const url = \"http://foo/tadam/fa\";
"""const url = \"http://foo/\"+\"tadam\"+\"/fa\";
try {
await page.goto(url);
} catch(exc) {
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/assert-expr.goml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ assert: ["1", "2"] != ["1", "2"]
store-value: (var, (1 + 2) * 4 + 1)
assert: |var| == 13
assert: |var| != 12 && 1 < 2
assert: 1 + 2 + "a" == "3a"
assert: 1 + 2 + "a" + (4 * 3) == "3a12"

// Should fail.
assert: |var| != 13
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/assert-expr.output
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

assert-expr... FAILED
[ERROR] `tests/ui/assert-expr.goml` line 15: Condition `!compareArrayLike(["1", "2"], ["1", "2"])` was evaluated as false: for command `assert: ["1", "2"] != ["1", "2"]`
[ERROR] `tests/ui/assert-expr.goml` line 23: Condition `13 != 13` was evaluated as false: for command `assert: |var| != 13`
[ERROR] `tests/ui/assert-expr.goml` line 24: assert didn't fail: for command `assert-false: |var| == 13`
[ERROR] `tests/ui/assert-expr.goml` line 25: Condition `"a" == 13` was evaluated as false: for command `assert: |var2| == |var|`
[ERROR] `tests/ui/assert-expr.goml` line 26: Condition `compareJson({"b": 3}, {"a": 2})` was evaluated as false: for command `assert: {"b": 3} == |var3|`
[ERROR] `tests/ui/assert-expr.goml` line 27: Condition `compareArrayLike([1, "a"], [2, 3])` was evaluated as false: for command `assert: (1, "a") == (2, 3)`
[ERROR] `tests/ui/assert-expr.goml` line 28: Condition `compareArrayLike([1, 2], ["a", "b"])` was evaluated as false: for command `assert: [1, 2] == ["a", "b"]`
[ERROR] `tests/ui/assert-expr.goml` line 25: Condition `13 != 13` was evaluated as false: for command `assert: |var| != 13`
[ERROR] `tests/ui/assert-expr.goml` line 26: assert didn't fail: for command `assert-false: |var| == 13`
[ERROR] `tests/ui/assert-expr.goml` line 27: Condition `"a" == 13` was evaluated as false: for command `assert: |var2| == |var|`
[ERROR] `tests/ui/assert-expr.goml` line 28: Condition `compareJson({"b": 3}, {"a": 2})` was evaluated as false: for command `assert: {"b": 3} == |var3|`
[ERROR] `tests/ui/assert-expr.goml` line 29: Condition `compareArrayLike([1, "a"], [2, 3])` was evaluated as false: for command `assert: (1, "a") == (2, 3)`
[ERROR] `tests/ui/assert-expr.goml` line 30: Condition `compareArrayLike([1, 2], ["a", "b"])` was evaluated as false: for command `assert: [1, 2] == ["a", "b"]`


<= doc-ui tests done: 0 succeeded, 1 failed
2 changes: 1 addition & 1 deletion tests/ui/debug.output
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ debug...
[DEBUG] Done!
[DEBUG] EXECUTING (line 2) "arg.screenshotComparison = false;"
[DEBUG] Done!
[DEBUG] EXECUTING (line 3) "const url = "file://$CURRENT_DIR/tests/html_files/elements.html";
[DEBUG] EXECUTING (line 3) "const url = "file://"+"$CURRENT_DIR"+"/"+"tests/html_files"+"/elements.html";
try {
await page.goto(url);
} catch(exc) {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/debug2.output
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ debug2...
[DEBUG] Done!
[DEBUG] EXECUTING (line 2) "arg.screenshotComparison = false;"
[DEBUG] Done!
[DEBUG] EXECUTING (line 3) "const url = "file://$CURRENT_DIR/tests/html_files/elements.html";
[DEBUG] EXECUTING (line 3) "const url = "file://"+"$CURRENT_DIR"+"/"+"tests/html_files"+"/elements.html";
try {
await page.goto(url);
} catch(exc) {
Expand Down
6 changes: 5 additions & 1 deletion tools/doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require('path');
const { ORDERS } = require('../src/commands.js');
const docFile = path.join(__dirname, '../goml-script.md');

const {Assert, print} = require('./utils.js');
const {Assert, plural, print} = require('./utils.js');

function compareCommands(x, commands) {
print(`Checking ${commands.length} commands from documentation (\
Expand Down Expand Up @@ -80,7 +80,11 @@ function checkDoc(x = new Assert()) {
if (x.getTotalRanTests() === 0) {
x.addError('No commands found in doc...');
}

const errors = x.getTotalErrors();
print('');
print(`<= Ending ${x.getTotalRanTests()} ${plural('test', x.getTotalRanTests())} with ` +
`${x.getTotalErrors()} ${plural('error', errors)}`);
x.endTestSuite(false);
return errors;
}
Expand Down
Loading