Skip to content

Commit 40329db

Browse files
committed
feat: Allow specifying test commands in separate modules
1 parent ad720cb commit 40329db

File tree

6 files changed

+110
-25
lines changed

6 files changed

+110
-25
lines changed

Gruntfile.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ module.exports = function (grunt) {
226226
});
227227
}
228228
}
229-
]
229+
],
230+
scenarios: 'test/scenarios/*.js'
230231
},
231232
'no-input': {
232233
options: {

README.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,17 @@ If the sub-task contains a property `commands`, this property is supposed to poi
203203
}
204204
```
205205

206-
You can use sub-tasks and commands to create test scenarios and execute them separately, or all of them.
206+
If the sub-task contains a property `scenarios`, this property is supposed to point to a JavaScript module path or to an array of JavaScript module paths, which would export the array of commands. Relative paths will be resolved to the current (process) directory. It allows to keep the Gruntfile legible and supply the test instructions from other files:
207+
208+
```js
209+
'html-dom-snapshot': {
210+
all: {
211+
scenarios: 'scenarios/*.js'
212+
}
213+
}
214+
```
215+
216+
You can use sub-tasks, `commands` and `scenarios` to structure your code and execute the tests separately, or all of them in one browser window.
207217

208218
### Instructions
209219

@@ -481,7 +491,7 @@ The module for the address book implementation would look like this:
481491

482492
```js
483493
module.exports = {
484-
options: {...},
494+
options: {...}, // optional task-specific options
485495
commands: [
486496
{
487497
url: 'https://localhost/addressbook'
@@ -492,6 +502,29 @@ module.exports = {
492502
}
493503
```
494504

505+
The same tests will be run in a single browser window, if the Gruntfile contains just a single sub-task and the tests are specified by scenario files:
506+
507+
```js
508+
'html-dom-snapshot': {
509+
all: {
510+
scenarios: 'test/scenarios/*.js'
511+
}
512+
}
513+
```
514+
515+
The directory "test/scenarios" would contain files "addressbook.js", "calendar.js", "inbox.js" and "tasks.js", which would specify only the array of commands; not the entire sub-task objects. For example, the address book implementation:
516+
517+
```js
518+
module.exports = {
519+
{
520+
options: {...}, // optional command-specific options
521+
url: 'https://localhost/addressbook'
522+
wait: '#addressbook.complete'
523+
},
524+
...
525+
]
526+
```
527+
495528
### Loading
496529
497530
Load the plugin in `Gruntfile.js`:
@@ -531,8 +564,8 @@ grunt.initConfig({
531564
},
532565

533566
'html-dom-snapshot': { // Takes new snapshots.
534-
'index': {
535-
url: 'https://localhost:8881'
567+
all: {
568+
...
536569
}
537570
},
538571

@@ -606,6 +639,7 @@ your code using Grunt.
606639
607640
## Release History
608641
642+
* 2018-01-30 [v0.3.0] Allow specifying test commands in separate modules
609643
* 2018-01-27 [v0.2.0] Allow saving screenshots in addition to snapshots
610644
* 2017-11-18 [v0.1.0] Allow separate navigation, page interaction and saving snapshots
611645
* 2017-11-12 [v0.0.1] Initial release
@@ -637,6 +671,7 @@ Licensed under the MIT license.
637671
[grunt-reg-viz]: https://github.com/prantlf/grunt-reg-viz
638672
[grunt-selenium-standalone]: https://github.com/zs-zs/grunt-selenium-standalone
639673
[keyboard key identifiers]: https://w3c.github.io/webdriver/webdriver-spec.html#keyboard-actions
674+
[v0.3.0]: https://github.com/prantlf/grunt-html-dom-snapshot/releases/tag/v0.3.0
640675
[v0.2.0]: https://github.com/prantlf/grunt-html-dom-snapshot/releases/tag/v0.2.0
641676
[v0.1.0]: https://github.com/prantlf/grunt-html-dom-snapshot/releases/tag/v0.1.0
642677
[v0.0.1]: https://github.com/prantlf/grunt-html-dom-snapshot/releases/tag/v0.0.1

tasks/html-dom-snapshot.js

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,15 @@ module.exports = function (grunt) {
3737
}),
3838
target = this.target,
3939
pages = data.pages,
40-
snapshots = options.dest;
41-
var lastViewport = options.viewport;
40+
snapshots = options.dest,
41+
client = webdriverio.remote({
42+
desiredCapabilities: options.browserCapabilities
43+
});
44+
var lastViewport = options.viewport,
45+
urlCount = 0,
46+
snapshotCount = 0,
47+
screenshotCount = 0,
48+
commands;
4249
if (pages) {
4350
grunt.log.warn('The property "pages" is deprecated. ' +
4451
'Use "commands" with the same content.');
@@ -49,29 +56,13 @@ module.exports = function (grunt) {
4956
options.snapshots = snapshots;
5057
delete options.dest;
5158
}
52-
const commands = data.commands || pages || [
53-
Object.assign({
54-
file: target
55-
}, data)
56-
],
57-
client = webdriverio.remote({
58-
desiredCapabilities: options.browserCapabilities
59-
});
60-
var urlCount = 0,
61-
snapshotCount = 0,
62-
screenshotCount = 0;
6359

6460
grunt.verbose.writeln('Open web browser window for the target "' +
6561
target + '".');
6662
client.init()
6763
.then(setViewportSize)
68-
.then(function () {
69-
return commands.reduce(function (promise, command) {
70-
return promise.then(function () {
71-
return performCommand(command);
72-
});
73-
}, Promise.resolve());
74-
})
64+
.then(gatherCommands)
65+
.then(performCommands)
7566
.then(function () {
7667
grunt.log.ok(commands.length + ' ' +
7768
grunt.util.pluralize(commands.length, 'command/commands') +
@@ -92,6 +83,43 @@ module.exports = function (grunt) {
9283
})
9384
.then(done);
9485

86+
function gatherCommands() {
87+
let scenarios = data.scenarios;
88+
commands = data.commands || pages;
89+
if (scenarios) {
90+
if (!Array.isArray(scenarios)) {
91+
scenarios = [scenarios];
92+
}
93+
const currentDirectory = process.cwd();
94+
commands = scenarios
95+
.reduce(function (scenarios, scenario) {
96+
return scenarios.concat(grunt.file.expand(scenario));
97+
}, [])
98+
.reduce(function (scenarios, scenario) {
99+
grunt.verbose.writeln('Load scenario "' + scenario + '".');
100+
if (!path.isAbsolute(scenario)) {
101+
scenario = path.join(currentDirectory, scenario);
102+
}
103+
return scenarios.concat(require(scenario));
104+
}, commands || []);
105+
}
106+
if (!commands) {
107+
commands = [
108+
Object.assign({
109+
file: target
110+
}, data)
111+
];
112+
}
113+
}
114+
115+
function performCommands() {
116+
return commands.reduce(function (promise, command) {
117+
return promise.then(function () {
118+
return performCommand(command);
119+
});
120+
}, Promise.resolve());
121+
}
122+
95123
function setViewportSize() {
96124
grunt.verbose.writeln('Resize viewport to ' + lastViewport.width +
97125
'x' + lastViewport.height + '.');

test/pages/scenario1.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>scenario1</title>
5+
</head>
6+
<body>scenario1</body>
7+
</html>

test/scenarios/scenario1.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
3+
module.exports = [
4+
{
5+
url: 'http://localhost:8881/test/pages/scenario1.html',
6+
file: 'scenario1'
7+
}
8+
];

test/test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,11 @@ exports['html-dom-snapshot'] = {
8585
expected = original.replace('<body class="first">', '<body class="first second third">');
8686
test.equal(expected, third, 'dynamic-third.html');
8787
test.done();
88+
},
89+
90+
'scenario1': function (test) {
91+
const pages = readPages('scenario1.html');
92+
test.equal(pages.expected, pages.actual, 'scenario1.html');
93+
test.done();
8894
}
8995
};

0 commit comments

Comments
 (0)