@bucky24/jsbehave 0.12.9 → 0.13.1

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.
Files changed (3) hide show
  1. package/README.md +65 -66
  2. package/package.json +1 -1
  3. package/src/index.js +66 -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,29 @@ 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>]`
108
+ `concat variables <variable name> and <variable name>` - concats two variables, storing the result in the first variable
65
109
 
66
- `[endaction]`
110
+ `run test <test name>` - runs the test regardless if it has been run before
67
111
 
68
- `run action <action name>` runs the given action
112
+ `run action <action name>` - runs the given action
69
113
 
70
- `switch to window <index>` switches context to the window handle at the index (useful for popups)
114
+ `switch to window <index>` - switches context to the window handle at the index (useful for popups)
71
115
 
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
116
+ `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
117
 
74
118
  ## Tests
75
119
 
@@ -134,51 +178,6 @@ The following are configs that the jsbehave system will use for various operatio
134
178
  | screenshotDirectory | The directory where screenshots will be saved. Defaults to `.` |
135
179
  | screenshotOnFailure | Boolean. If true (default), takes a screenshot when the test fails. |
136
180
 
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
181
  ## Custom code
183
182
 
184
183
  In order to load custom code, put `load funcs <filename>` in your test file. Functions can be async.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bucky24/jsbehave",
3
- "version": "0.12.9",
3
+ "version": "0.13.1",
4
4
  "description": "A module that allows BDD testing for browser based testing in Selenium.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
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 default browser: no driver found");
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) {
@@ -404,11 +410,11 @@ async function compareContent([ selector, text ]) {
404
410
  if (text instanceof RegExp && text.test(value)) {
405
411
  return;
406
412
  }
407
- if (value.includes(text)) {
413
+ if (value?.includes(text)) {
408
414
  return;
409
415
  }
410
416
 
411
- throw new Error(`Expected element to have inner html of "${text}". Instead it had inner html of "${html}"`);
417
+ throw new Error(`Expected element to have inner html of "${text}". Instead it had inner html of "${html}" and value of "${value}"`);
412
418
  }
413
419
 
414
420
  function doSetVariable([ key, input ]) {
@@ -423,6 +429,12 @@ function concatVariable([ key, input ]) {
423
429
  setVariable(key, `${oldValue}${finalInput}`);
424
430
  }
425
431
 
432
+ function concatVariable([ key, key2 ]) {
433
+ const var1 = getVariable(key) || '';
434
+ const var2 = getVariable(key2) || "";
435
+ setVariable(key, `${var1}${var2}`);
436
+ }
437
+
426
438
  async function executeJS(code) {
427
439
  return driver().executeScript(code);
428
440
  }
@@ -526,6 +538,7 @@ const operations = {
526
538
  "expect element (.+) to have content (.+)": compareContent,
527
539
  "set variable (.+) to (.+)": doSetVariable,
528
540
  "concat variable (.+) with (.+)": concatVariable,
541
+ "concat variables (.+) and (.+)": concatVariables,
529
542
  "run test (.+)": doRunTest,
530
543
  "run action (.+)": doRunAction,
531
544
  [startActionRegex]: startBlock,
@@ -536,7 +549,7 @@ const operations = {
536
549
 
537
550
  async function handleLines(lines) {
538
551
  for (let i=0;i<lines.length;i++) {
539
- const line = lines[i];
552
+ const { lineNum, line } = lines[i];
540
553
  if (line === "") {
541
554
  continue;
542
555
  }
@@ -574,8 +587,15 @@ async function handleLines(lines) {
574
587
  const test = variables["jsbehave.activeBlock"];
575
588
  if (test) {
576
589
  console.log(`Test ${test} - FAILURE`);
577
- console.log(`Failed on line ${i+1}: "${line}" for "${operation}"`);
578
- console.log(error);
590
+ console.log(`Failed on line ${lineNum}: "${line}" for "${operation}"`);
591
+ const errorType = error.constructor.name;
592
+ if (errorType === "NoSuchElementError") {
593
+ console.log(`Could not find any matching element`);
594
+ } else {
595
+ console.log(error.constructor.name, error);
596
+ }
597
+ // newline
598
+ console.log();
579
599
  const screenshotOnFailure = getVariable("screenshotOnFailure") === 'true';
580
600
  if (screenshotOnFailure) {
581
601
  const screenshot = await takeScreenshot(test);
@@ -584,7 +604,7 @@ async function handleLines(lines) {
584
604
  } else {
585
605
  console.error(error);
586
606
  }
587
- return;
607
+ return false;
588
608
  }
589
609
  handled = true;
590
610
  break;
@@ -595,9 +615,12 @@ async function handleLines(lines) {
595
615
  console.log(`Unable to handle "${line}"`);
596
616
  }
597
617
  }
618
+
619
+ return true;
598
620
  }
599
621
 
600
622
  (async function main() {
623
+ const allFailures = [];
601
624
  for (const fileName of fileNames) {
602
625
  const contents = fs.readFileSync(fileName, "utf-8");
603
626
  const lines = contents.split(EOL);
@@ -617,7 +640,8 @@ async function handleLines(lines) {
617
640
  let testName = null;
618
641
  let allOrEach = null;
619
642
  let inAction = false;
620
- for (const line of lines) {
643
+ for (let i=0;i<lines.length;i++) {
644
+ const line = lines[i];
621
645
  if (line === "") {
622
646
  continue;
623
647
  }
@@ -660,7 +684,10 @@ async function handleLines(lines) {
660
684
  }
661
685
  }
662
686
 
663
- testLines.push(line);
687
+ testLines.push({
688
+ lineNum: i+1,
689
+ line,
690
+ });
664
691
 
665
692
  if (line.startsWith("[endtest")) {
666
693
  inTest = false;
@@ -697,6 +724,8 @@ async function handleLines(lines) {
697
724
  endLines = [...testLines];
698
725
  }
699
726
 
727
+ let anyError = false;
728
+
700
729
  if (specificTest) {
701
730
  if (!allTests[specificTest]) {
702
731
  console.log("No test case found for '" + specificTest + "'");
@@ -704,34 +733,49 @@ async function handleLines(lines) {
704
733
  return;
705
734
  }
706
735
 
707
- await handleLines(startLines);
736
+ let result = await handleLines(startLines);
737
+ if (!result) anyError = true;
708
738
  console.log("Running beforeAll");
709
739
  for (const before of beforeAll) {
710
- await handleLines(before);
740
+ result = await handleLines(before);
741
+ if (!result) anyError = true;
711
742
  }
712
- await runTest(specificTest, true);
743
+ result = await runTest(specificTest, true);
744
+ if (!result) anyError = true;
713
745
  console.log("Running afterAll");
714
746
  for (const after of afterAll) {
715
- await handleLines(after);
747
+ result = await handleLines(after);
748
+ if (!result) anyError = true;
716
749
  }
717
- await handleLines(endLines);
750
+ const anyError = await handleLines(endLines);
718
751
  } else {
719
- await handleLines(startLines);
752
+ let result = await handleLines(startLines);
753
+ if (!result) anyError = true;
720
754
  console.log("Running beforeAll");
721
755
  for (const before of beforeAll) {
722
- await handleLines(before);
756
+ result = await handleLines(before);
757
+ if (!result) anyError = true;
723
758
  }
724
759
  for (const testName in allTests) {
725
- await runTest(testName, true);
760
+ result = await runTest(testName, true);
761
+ if (!result) anyError = true;
726
762
  }
727
763
  console.log("Running afterAll");
728
764
  for (const after of afterAll) {
729
- await handleLines(after);
765
+ result = await handleLines(after);
766
+ if (!result) anyError = true;
730
767
  }
731
- await handleLines(endLines);
768
+ result = await handleLines(endLines);
769
+ if (!result) anyError = true;
770
+ }
771
+
772
+ if (anyError) {
773
+ allFailures.push(fileName);
732
774
  }
733
775
  }
734
776
 
777
+ console.log(`All failing tests:\n${allFailures.join("\n")}`);
778
+
735
779
  // force terminate
736
780
  process.exit(0);
737
781
  })();