@bucky24/jsbehave 0.12.8 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -67
- package/package.json +1 -1
- package/src/index.js +60 -22
package/README.md
CHANGED
|
@@ -9,23 +9,77 @@ In order to use this, you must have the webdriver for your chosen browser access
|
|
|
9
9
|
|
|
10
10
|
Running `jsbehave` directly will locate all files that end in `.behave` and will run them.
|
|
11
11
|
|
|
12
|
+
## Blocks
|
|
13
|
+
|
|
14
|
+
### Test Block
|
|
15
|
+
|
|
16
|
+
Defines a block of operations that runs when the test framework is triggered.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
[test <test name>]
|
|
20
|
+
...
|
|
21
|
+
[endtest]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Action Block
|
|
25
|
+
|
|
26
|
+
Defines an Action. This is similar to a test in that it is a block of operations. Actions are not run automatically, however, and require a specific Operation to run them.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
[action <action name>]`
|
|
30
|
+
...
|
|
31
|
+
[endaction]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Before and After blocks
|
|
35
|
+
|
|
36
|
+
Code in these blocks looks like the following:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
[before all]
|
|
40
|
+
open chrome
|
|
41
|
+
[endbefore]
|
|
42
|
+
|
|
43
|
+
[before each]
|
|
44
|
+
reload page
|
|
45
|
+
[endbefore]
|
|
46
|
+
|
|
47
|
+
[test blah]
|
|
48
|
+
|
|
49
|
+
[endtest]
|
|
50
|
+
|
|
51
|
+
[after each]
|
|
52
|
+
# cleanup
|
|
53
|
+
[endafter]
|
|
54
|
+
|
|
55
|
+
[after all]
|
|
56
|
+
close browser
|
|
57
|
+
[endafter]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`[before all]` blocks will run before all the tests. `[before each]` runs before each test. `[after each]` runs after each test, and `[after all]` runs after all the tests are done. This is similar to most other test systems.
|
|
61
|
+
|
|
12
62
|
## Operations
|
|
13
63
|
|
|
14
64
|
`open <browser>` (note the name for this browser is `default`)
|
|
15
65
|
|
|
66
|
+
`open <browser> as <name>` - opens a new browser and attaches its session to the given name
|
|
67
|
+
|
|
68
|
+
`set active browser to <name>` - sets the current active browser (the one that operations will be run on)
|
|
69
|
+
|
|
70
|
+
`close browser` - closes the active browser
|
|
71
|
+
|
|
72
|
+
`close browser <name>` - closes browser with given name
|
|
73
|
+
|
|
16
74
|
`navigate to <url>`
|
|
17
75
|
|
|
18
76
|
`type <text> into <selector>`
|
|
19
77
|
|
|
20
78
|
`wait for title to be <text>`
|
|
21
79
|
|
|
22
|
-
`[test <string>]`
|
|
23
|
-
|
|
24
|
-
`[endtest]`
|
|
25
|
-
|
|
26
80
|
`click <selector>`
|
|
27
81
|
|
|
28
|
-
`sleep <number>`
|
|
82
|
+
`sleep <number of seconds, can be fractional>`
|
|
29
83
|
|
|
30
84
|
`wait until located <selector>`
|
|
31
85
|
|
|
@@ -37,39 +91,27 @@ Running `jsbehave` directly will locate all files that end in `.behave` and will
|
|
|
37
91
|
|
|
38
92
|
`expect element <selector> to not exist`
|
|
39
93
|
|
|
40
|
-
`close browser`
|
|
41
|
-
|
|
42
94
|
`reload page`
|
|
43
95
|
|
|
44
|
-
`require test <test name>` runs the test only if it has not already been run
|
|
96
|
+
`require test <test name>` - runs the test only if it has not already been run
|
|
45
97
|
|
|
46
98
|
`expect elements <selector> to have count of <count>`
|
|
47
99
|
|
|
48
100
|
`expect variable <variable> to match <text>`
|
|
49
101
|
|
|
50
|
-
`open <browser> as <name>`
|
|
51
|
-
|
|
52
|
-
`close browser <name>`
|
|
53
|
-
|
|
54
|
-
`set active browser to <name>`
|
|
55
|
-
|
|
56
102
|
`expect element <selector> to have content <text>`
|
|
57
103
|
|
|
58
104
|
`set variable <variable name> to <text>`
|
|
59
105
|
|
|
60
106
|
`concat variable <variable name> with <text>`
|
|
61
107
|
|
|
62
|
-
`run test <test name>` runs the test regardless if it has been run before
|
|
63
|
-
|
|
64
|
-
`[action <action name>]`
|
|
65
|
-
|
|
66
|
-
`[endaction]`
|
|
108
|
+
`run test <test name>` - runs the test regardless if it has been run before
|
|
67
109
|
|
|
68
|
-
`run action <action name>` runs the given action
|
|
110
|
+
`run action <action name>` - runs the given action
|
|
69
111
|
|
|
70
|
-
`switch to window <index>` switches context to the window handle at the index (useful for popups)
|
|
112
|
+
`switch to window <index>` - switches context to the window handle at the index (useful for popups)
|
|
71
113
|
|
|
72
|
-
`read content from element <selector> into variable <variable name>` Takes the value or inner html from the element and stores it in the given variable
|
|
114
|
+
`read content from element <selector> into variable <variable name>` - Takes the value or inner html from the element and stores it in the given variable
|
|
73
115
|
|
|
74
116
|
## Tests
|
|
75
117
|
|
|
@@ -134,51 +176,6 @@ The following are configs that the jsbehave system will use for various operatio
|
|
|
134
176
|
| screenshotDirectory | The directory where screenshots will be saved. Defaults to `.` |
|
|
135
177
|
| screenshotOnFailure | Boolean. If true (default), takes a screenshot when the test fails. |
|
|
136
178
|
|
|
137
|
-
## Before and After blocks
|
|
138
|
-
|
|
139
|
-
Code in these blocks looks like the following:
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
[before all]
|
|
143
|
-
open chrome
|
|
144
|
-
[endbefore]
|
|
145
|
-
|
|
146
|
-
[before each]
|
|
147
|
-
reload page
|
|
148
|
-
[endbefore]
|
|
149
|
-
|
|
150
|
-
[test blah]
|
|
151
|
-
|
|
152
|
-
[endtest]
|
|
153
|
-
|
|
154
|
-
[after each]
|
|
155
|
-
# cleanup
|
|
156
|
-
[endafter]
|
|
157
|
-
|
|
158
|
-
[after all]
|
|
159
|
-
close browser
|
|
160
|
-
[endafter]
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
`[before all]` blocks will run before all the tests. `[before each]` runs before each test. `[after each]` runs after each test, and `[after all]` runs after all the tests are done. This is similar to most other test systems.
|
|
164
|
-
|
|
165
|
-
## Action blocks
|
|
166
|
-
|
|
167
|
-
Code in these blocks looks like the following:
|
|
168
|
-
```
|
|
169
|
-
[action some action]
|
|
170
|
-
open chrome
|
|
171
|
-
[endaction]
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
These actions are identical to test blocks, except they are not automatically run when tests are run. They can be run as follows:
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
[test a test]
|
|
178
|
-
run action some action
|
|
179
|
-
[endtest]
|
|
180
|
-
```
|
|
181
|
-
|
|
182
179
|
## Custom code
|
|
183
180
|
|
|
184
181
|
In order to load custom code, put `load funcs <filename>` in your test file. Functions can be async.
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -22,6 +22,7 @@ if (process.argv.length > 2) {
|
|
|
22
22
|
.filter(e => {
|
|
23
23
|
return e.isFile() && e.name.endsWith(".behave");
|
|
24
24
|
})
|
|
25
|
+
.filter(e => !e.path.includes('node_modules'))
|
|
25
26
|
.map(e => path.join(e.path, e.name));
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -251,7 +252,7 @@ function closeBrowser() {
|
|
|
251
252
|
const activeBrowser = getVariable("jsbehave.active_driver");
|
|
252
253
|
const driver = getVariable(`jsbehave.driver.${activeBrowser}`);
|
|
253
254
|
if (!driver) {
|
|
254
|
-
throw new Error("Unable to close
|
|
255
|
+
throw new Error("Unable to close active browser: no driver found");
|
|
255
256
|
}
|
|
256
257
|
delete variables[`jsbehave.driver.${activeBrowser}`];
|
|
257
258
|
return driver.close();
|
|
@@ -268,15 +269,18 @@ async function noop() {
|
|
|
268
269
|
|
|
269
270
|
async function runTest(name, showTitle=false) {
|
|
270
271
|
for (const before of beforeEach) {
|
|
271
|
-
await handleLines(before);
|
|
272
|
+
const result = await handleLines(before);
|
|
273
|
+
if (!result) return false;
|
|
272
274
|
}
|
|
273
275
|
if (showTitle) {
|
|
274
276
|
console.log("Running '" + name + "'");
|
|
275
277
|
}
|
|
276
278
|
const content = allTests[name];
|
|
277
|
-
await handleLines(content);
|
|
279
|
+
const result = await handleLines(content);
|
|
280
|
+
if (!result) return false;
|
|
278
281
|
for (const after of afterEach) {
|
|
279
|
-
await handleLines(after);
|
|
282
|
+
const result = await handleLines(after);
|
|
283
|
+
if (!result) return false;
|
|
280
284
|
}
|
|
281
285
|
|
|
282
286
|
const testsRun = getVariable("jsbehave.run_tests");
|
|
@@ -284,6 +288,8 @@ async function runTest(name, showTitle=false) {
|
|
|
284
288
|
...testsRun,
|
|
285
289
|
name,
|
|
286
290
|
];
|
|
291
|
+
|
|
292
|
+
return true;
|
|
287
293
|
}
|
|
288
294
|
|
|
289
295
|
async function runAction(name, showTitle=false) {
|
|
@@ -381,7 +387,8 @@ function setActiveBrowser([ name ]) {
|
|
|
381
387
|
function closeBrowserWithName([ name ]) {
|
|
382
388
|
const driver = getVariable(`jsbehave.driver.${name}`);
|
|
383
389
|
if (!driver) {
|
|
384
|
-
|
|
390
|
+
console.log(`Unable to close browser with name "${name}": no driver found`);
|
|
391
|
+
return;
|
|
385
392
|
}
|
|
386
393
|
delete variables[`jsbehave.driver.${name}`];
|
|
387
394
|
return driver.close();
|
|
@@ -450,7 +457,7 @@ async function takeScreenshot(test) {
|
|
|
450
457
|
console.error(`Unable to take screenshot - driver does not exist`);
|
|
451
458
|
return;
|
|
452
459
|
}
|
|
453
|
-
const image = activeDriver.takeScreenshot();
|
|
460
|
+
const image = await activeDriver.takeScreenshot();
|
|
454
461
|
const useTest = test.replace(/ /g, "_");
|
|
455
462
|
let configPath = getVariable("screenshotDirectory");
|
|
456
463
|
const fileName = `test_${useTest}_failure_${activeBrowser}.png`;
|
|
@@ -535,7 +542,7 @@ const operations = {
|
|
|
535
542
|
|
|
536
543
|
async function handleLines(lines) {
|
|
537
544
|
for (let i=0;i<lines.length;i++) {
|
|
538
|
-
const line = lines[i];
|
|
545
|
+
const { lineNum, line } = lines[i];
|
|
539
546
|
if (line === "") {
|
|
540
547
|
continue;
|
|
541
548
|
}
|
|
@@ -573,8 +580,15 @@ async function handleLines(lines) {
|
|
|
573
580
|
const test = variables["jsbehave.activeBlock"];
|
|
574
581
|
if (test) {
|
|
575
582
|
console.log(`Test ${test} - FAILURE`);
|
|
576
|
-
console.log(`Failed on line ${
|
|
577
|
-
|
|
583
|
+
console.log(`Failed on line ${lineNum}: "${line}" for "${operation}"`);
|
|
584
|
+
const errorType = error.constructor.name;
|
|
585
|
+
if (errorType === "NoSuchElementError") {
|
|
586
|
+
console.log(`Could not find any matching element`);
|
|
587
|
+
} else {
|
|
588
|
+
console.log(error.constructor.name, error);
|
|
589
|
+
}
|
|
590
|
+
// newline
|
|
591
|
+
console.log();
|
|
578
592
|
const screenshotOnFailure = getVariable("screenshotOnFailure") === 'true';
|
|
579
593
|
if (screenshotOnFailure) {
|
|
580
594
|
const screenshot = await takeScreenshot(test);
|
|
@@ -583,7 +597,7 @@ async function handleLines(lines) {
|
|
|
583
597
|
} else {
|
|
584
598
|
console.error(error);
|
|
585
599
|
}
|
|
586
|
-
return;
|
|
600
|
+
return false;
|
|
587
601
|
}
|
|
588
602
|
handled = true;
|
|
589
603
|
break;
|
|
@@ -594,9 +608,12 @@ async function handleLines(lines) {
|
|
|
594
608
|
console.log(`Unable to handle "${line}"`);
|
|
595
609
|
}
|
|
596
610
|
}
|
|
611
|
+
|
|
612
|
+
return true;
|
|
597
613
|
}
|
|
598
614
|
|
|
599
615
|
(async function main() {
|
|
616
|
+
const allFailures = [];
|
|
600
617
|
for (const fileName of fileNames) {
|
|
601
618
|
const contents = fs.readFileSync(fileName, "utf-8");
|
|
602
619
|
const lines = contents.split(EOL);
|
|
@@ -616,7 +633,8 @@ async function handleLines(lines) {
|
|
|
616
633
|
let testName = null;
|
|
617
634
|
let allOrEach = null;
|
|
618
635
|
let inAction = false;
|
|
619
|
-
for (
|
|
636
|
+
for (let i=0;i<lines.length;i++) {
|
|
637
|
+
const line = lines[i];
|
|
620
638
|
if (line === "") {
|
|
621
639
|
continue;
|
|
622
640
|
}
|
|
@@ -659,7 +677,10 @@ async function handleLines(lines) {
|
|
|
659
677
|
}
|
|
660
678
|
}
|
|
661
679
|
|
|
662
|
-
testLines.push(
|
|
680
|
+
testLines.push({
|
|
681
|
+
lineNum: i+1,
|
|
682
|
+
line,
|
|
683
|
+
});
|
|
663
684
|
|
|
664
685
|
if (line.startsWith("[endtest")) {
|
|
665
686
|
inTest = false;
|
|
@@ -696,6 +717,8 @@ async function handleLines(lines) {
|
|
|
696
717
|
endLines = [...testLines];
|
|
697
718
|
}
|
|
698
719
|
|
|
720
|
+
let anyError = false;
|
|
721
|
+
|
|
699
722
|
if (specificTest) {
|
|
700
723
|
if (!allTests[specificTest]) {
|
|
701
724
|
console.log("No test case found for '" + specificTest + "'");
|
|
@@ -703,34 +726,49 @@ async function handleLines(lines) {
|
|
|
703
726
|
return;
|
|
704
727
|
}
|
|
705
728
|
|
|
706
|
-
await handleLines(startLines);
|
|
729
|
+
let result = await handleLines(startLines);
|
|
730
|
+
if (!result) anyError = true;
|
|
707
731
|
console.log("Running beforeAll");
|
|
708
732
|
for (const before of beforeAll) {
|
|
709
|
-
await handleLines(before);
|
|
733
|
+
result = await handleLines(before);
|
|
734
|
+
if (!result) anyError = true;
|
|
710
735
|
}
|
|
711
|
-
await runTest(specificTest, true);
|
|
736
|
+
result = await runTest(specificTest, true);
|
|
737
|
+
if (!result) anyError = true;
|
|
712
738
|
console.log("Running afterAll");
|
|
713
739
|
for (const after of afterAll) {
|
|
714
|
-
await handleLines(after);
|
|
740
|
+
result = await handleLines(after);
|
|
741
|
+
if (!result) anyError = true;
|
|
715
742
|
}
|
|
716
|
-
await handleLines(endLines);
|
|
743
|
+
const anyError = await handleLines(endLines);
|
|
717
744
|
} else {
|
|
718
|
-
await handleLines(startLines);
|
|
745
|
+
let result = await handleLines(startLines);
|
|
746
|
+
if (!result) anyError = true;
|
|
719
747
|
console.log("Running beforeAll");
|
|
720
748
|
for (const before of beforeAll) {
|
|
721
|
-
await handleLines(before);
|
|
749
|
+
result = await handleLines(before);
|
|
750
|
+
if (!result) anyError = true;
|
|
722
751
|
}
|
|
723
752
|
for (const testName in allTests) {
|
|
724
|
-
await runTest(testName, true);
|
|
753
|
+
result = await runTest(testName, true);
|
|
754
|
+
if (!result) anyError = true;
|
|
725
755
|
}
|
|
726
756
|
console.log("Running afterAll");
|
|
727
757
|
for (const after of afterAll) {
|
|
728
|
-
await handleLines(after);
|
|
758
|
+
result = await handleLines(after);
|
|
759
|
+
if (!result) anyError = true;
|
|
729
760
|
}
|
|
730
|
-
await handleLines(endLines);
|
|
761
|
+
result = await handleLines(endLines);
|
|
762
|
+
if (!result) anyError = true;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (anyError) {
|
|
766
|
+
allFailures.push(fileName);
|
|
731
767
|
}
|
|
732
768
|
}
|
|
733
769
|
|
|
770
|
+
console.log(`All failing tests:\n${allFailures.join("\n")}`);
|
|
771
|
+
|
|
734
772
|
// force terminate
|
|
735
773
|
process.exit(0);
|
|
736
774
|
})();
|