Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.

Commit 7b1853a

Browse files
feat: "skip" and "only" methods for tests API
1 parent 0b9e7bb commit 7b1853a

File tree

10 files changed

+932
-406
lines changed

10 files changed

+932
-406
lines changed

doc/tests.md

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -71,47 +71,6 @@ All methods are chainable:
7171
(See `tolerance`option description in [config](./config.md) documentation
7272
for details).
7373

74-
* `skip([browser])` — skip all tests and nested suites for:
75-
76-
- `skip()` — all browsers;
77-
78-
- `skip('id')` — browser with specified `id`;
79-
80-
- `skip('id', comment)` — browser with specified `id` and show `comment` in the report;
81-
82-
- `skip(/some RegExp/)` — browser with `id` which matches `/some RegExp/`;
83-
84-
- `skip(/some RegExp/, comment)` — browser with `id` which matches `/some RegExp/` and show `comment` in the report;
85-
86-
- `skip(['id1', /RegExp1/, ...])` — multiple browsers;
87-
88-
- `skip(['id1', /RegExp1/, ...], comment)` — multiple browsers and show `comment` in the report.
89-
90-
All browsers from subsequent calls to `.skip()` are added to the skip list:
91-
92-
```js
93-
suite
94-
.skip('id1')
95-
.skip(/RegExp1/);
96-
```
97-
98-
is equivalent to
99-
100-
```js
101-
suite.skip([
102-
'id1',
103-
/RegExp1/
104-
]);
105-
```
106-
107-
* `browsers([browser])` — run all tests and nested suites in specified browsers:
108-
109-
- `browsers('id')` — browser with specified `id`;
110-
111-
- `browsers(/some RegExp/)` — browser `id` which matches `/some RegExp/`;
112-
113-
- `browsers(['id1', /RegExp1/, ...])` — multiple browsers.
114-
11574
* `capture(stateName, [options], callback(actions, find))` — defines a new
11675
state to capture. Optional callback describes a sequence of actions to bring
11776
the page to this state, starting from a **previous** state of the suite.
@@ -169,6 +128,72 @@ All methods are chainable:
169128
* `after(callback(actions, find))` — use this function to execute some code
170129
after the last state. The arguments of a callback are the same as for
171130
`capture` and `before` callbacks and context is shared between all of them.
131+
132+
### Skip tests
133+
134+
Sometimes you need to skip tests in specific browsers. For example, tested features
135+
are not available in some browsers yet.
136+
137+
* `skip.in([browser])` — skip all tests and nested suites for:
138+
139+
- `skip.in('id')` — browser with specified `id`;
140+
141+
- `skip.in('id', comment)` — browser with specified `id` and show `comment` in the report;
142+
143+
- `skip.in(/some RegExp/)` — browser with `id` which matches `/some RegExp/`;
144+
145+
- `skip.in(/some RegExp/, comment)` — browser with `id` which matches `/some RegExp/`
146+
and show `comment` in the report;
147+
148+
- `skip.in(['id1', /RegExp1/, ...])` — multiple browsers;
149+
150+
- `skip.in(['id1', /RegExp1/, ...], comment)` — multiple browsers and show `comment` in the report.
151+
152+
To skip all tests in suite you can use `skip.in(/.*/)`.
153+
154+
All browsers from subsequent calls to `.skip.in` are added to the skip list:
155+
156+
```js
157+
suite
158+
.skip.in('id1')
159+
.skip.in(/RegExp1/);
160+
```
161+
162+
is equivalent to
163+
164+
```js
165+
suite.skip.in([
166+
'id1',
167+
/RegExp1/
168+
]);
169+
```
170+
171+
* ~`skip([browser])`~_deprecated_.
172+
Works the same way as `skip.in`, except to skip all tests you can also write `skip()`.
173+
174+
* `skip.notIn([browser])` — skip all tests and nested suites for all browsers,
175+
except ones in the arguments. Accepts same arguments as `skip.in`.
176+
177+
To skip test silently, use `only.in` function. This way, skipped browsers will not appear in the report.
178+
179+
* `only.in([browser])` — run all tests and nested suites in specified browsers:
180+
181+
- `only.in('id')` — browser with specified `id`;
182+
183+
- `only.in(/some RegExp/)` — browser `id` which matches `/some RegExp/`;
184+
185+
- `only.in('id1', /RegExp1/, ...)` — multiple browsers, also accepts an array as argument.
186+
187+
* ~`browsers([browser])`~_deprecated_. Use `only.in` instead.
188+
189+
* `only.notIn([browser])` — run all tests and nested suites in all browsers, except
190+
ones in the arguments. Accepts same arguments as `only.in`.
191+
192+
For example:
193+
```js
194+
suite.only.in(['chrome', 'firefox']);
195+
suite.only.notIn(/ie/, 'opera');
196+
```
172197

173198
## Nested suites
174199

@@ -180,7 +205,7 @@ browser, even if URL was not changed.
180205
```js
181206
gemini.suite('parent', function(parent) {
182207
parent.setUrl('/some/path')
183-
.setCaptureElements('.selector1', '.selector2');
208+
.setCaptureElements('.selector1', '.selector2')
184209
.capture('state');
185210

186211
gemini.suite('first child', function(child) {
@@ -194,7 +219,7 @@ gemini.suite('parent', function(parent) {
194219
child.setCaptureElements('.next-selector')
195220
.capture('third state', function(actions, elements) {
196221
// ...
197-
})
222+
});
198223

199224
gemini.suite('grandchild', function(grandchild) {
200225
//child suites can have own childs
@@ -206,7 +231,7 @@ gemini.suite('parent', function(parent) {
206231
gemini.suite('third child', function(child) {
207232
//this suite uses completely different URL and set of elements
208233
child.setUrl('/some/another/path')
209-
.setCaptureElements('.different-selector');
234+
.setCaptureElements('.different-selector')
210235
.capture('fifth state');
211236
});
212237
});

lib/suite.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = class Suite {
1616
constructor(name) {
1717
this.name = name;
1818
this.url = null;
19-
this.skipped = false;
19+
this.skipped = [];
2020
this.captureSelectors = null;
2121
this.tolerance = null;
2222
this.ignoreSelectors = [];
@@ -52,24 +52,10 @@ module.exports = class Suite {
5252
}
5353

5454
skip(browserSkipMatcher) {
55-
if (this.skipped === true) {
56-
return;
57-
}
58-
59-
if (!browserSkipMatcher) {
60-
this.skipped = true;
61-
} else {
62-
this.skipped = _.isArray(this.skipped)
63-
? this.skipped.concat(browserSkipMatcher)
64-
: [browserSkipMatcher];
65-
}
55+
this.skipped = this.skipped.concat(browserSkipMatcher);
6656
}
6757

6858
shouldSkip(browserId) {
69-
if (_.isBoolean(this.skipped)) {
70-
return this.skipped;
71-
}
72-
7359
return this.skipped.some((browserSkipMatcher) => {
7460
if (browserSkipMatcher.matches(browserId)) {
7561
this.skipComment = browserSkipMatcher.comment;

lib/tests-api/skip/index.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
const _ = require('lodash');
4+
5+
module.exports = class Skip {
6+
constructor(suite) {
7+
this._suite = suite;
8+
}
9+
10+
_validateArgs(browsers) {
11+
if (!this._isArrayOfStringsAndRegExps(browsers)) {
12+
throw new TypeError('Browsers must be an array with strings and RegExp objects');
13+
}
14+
}
15+
16+
_shouldSkip(browsers, {negate} = {}) {
17+
const fn = negate ? _.every : _.some;
18+
return (browserId) => fn(this._mkBrowsersMatcher(browsers, {negate}), (matcher) => matcher(browserId));
19+
}
20+
21+
_mkBrowsersMatcher(browsers, {negate}) {
22+
const mkMatcher = (browser) => _.isRegExp(browser) ? browser.test.bind(browser) : _.isEqual.bind(null, browser);
23+
24+
return browsers.map((browser) => negate ? _.negate(mkMatcher(browser)) : mkMatcher(browser));
25+
}
26+
27+
_isArrayOfStringsAndRegExps(arr) {
28+
return _.isArray(arr) && _.every(arr, (item) => _.isString(item) || _.isRegExp(item));
29+
}
30+
31+
in() {
32+
return new Error('Not implemented');
33+
}
34+
35+
notIn() {
36+
return new Error('Not implemented');
37+
}
38+
39+
buildAPI() {
40+
return new Error('Not implemented');
41+
}
42+
};

lib/tests-api/skip/only-builder.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'use strict';
2+
3+
const Skip = require('./index');
4+
const _ = require('lodash');
5+
6+
module.exports = class OnlyBuilder extends Skip {
7+
static create(suite) {
8+
return new OnlyBuilder(suite);
9+
}
10+
11+
constructor(suite) {
12+
super(suite);
13+
}
14+
15+
in(...browsers) {
16+
return this._process(browsers);
17+
}
18+
19+
notIn(...browsers) {
20+
return this._process(browsers, {negate: true});
21+
}
22+
23+
_process(browsers, opts = {negate: false}) {
24+
browsers = normalizeArgs(browsers);
25+
this._validateArgs(browsers);
26+
27+
this._suite.browsers = this._suite.browsers.filter(this._shouldSkip(browsers, opts));
28+
return this;
29+
}
30+
31+
buildAPI(context) {
32+
const only = {
33+
in: (...browsers) => {
34+
this.in(...browsers);
35+
return context;
36+
},
37+
notIn: (...browsers) => {
38+
this.notIn(...browsers);
39+
return context;
40+
}
41+
};
42+
const browsers = (...browsers) => {
43+
this.in(...browsers);
44+
return context;
45+
};
46+
47+
return {only, browsers};
48+
}
49+
};
50+
51+
function normalizeArgs(browsers) {
52+
if (browsers.length === 0) {
53+
return;
54+
}
55+
if (browsers.length === 1 && _.isArray(browsers[0])) {
56+
return browsers[0];
57+
}
58+
return browsers;
59+
}

lib/tests-api/skip/skip-builder.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use strict';
2+
3+
const Skip = require('./index');
4+
5+
module.exports = class SkipBuilder extends Skip {
6+
static create(suite) {
7+
return new SkipBuilder(suite);
8+
}
9+
10+
constructor(suite) {
11+
super(suite);
12+
}
13+
14+
in(browsers, comment) {
15+
return this._process(browsers, comment);
16+
}
17+
18+
notIn(browsers, comment) {
19+
return this._process(browsers, comment, {negate: true});
20+
}
21+
22+
_process(browsers, comment, opts = {negate: false}) {
23+
browsers = [].concat(browsers);
24+
this._validateArgs(browsers);
25+
26+
this._suite.skip({matches: this._shouldSkip(browsers, opts), comment});
27+
return this;
28+
}
29+
30+
buildAPI(context) {
31+
const skip = (browsers, comment) => {
32+
if (!browsers) {
33+
browsers = /.*/;
34+
}
35+
36+
this.in(browsers, comment);
37+
return context;
38+
};
39+
40+
skip.in = (browsers, comment) => {
41+
this.in(browsers, comment);
42+
return context;
43+
};
44+
45+
skip.notIn = (browsers, comment) => {
46+
this.notIn(browsers, comment);
47+
return context;
48+
};
49+
50+
return {skip};
51+
}
52+
};

0 commit comments

Comments
 (0)