mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
feat(testrunner): modifiers and attributes (#1538)
This generalizes test modifiers to support custom ones.
This commit is contained in:
parent
c01ad84bd4
commit
b61198458c
@ -17,7 +17,6 @@
|
|||||||
const util = require('util');
|
const util = require('util');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const inspector = require('inspector');
|
const inspector = require('inspector');
|
||||||
const path = require('path');
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const Multimap = require('./Multimap');
|
const Multimap = require('./Multimap');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@ -452,12 +451,47 @@ class TestPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function specBuilder(defaultTimeout, action) {
|
function specBuilder(defaultTimeout, modifiers, attributes, action) {
|
||||||
let mode = TestMode.Run;
|
let mode = TestMode.Run;
|
||||||
let expectation = TestExpectation.Ok;
|
let expectation = TestExpectation.Ok;
|
||||||
let repeat = 1;
|
let repeat = 1;
|
||||||
let timeout = defaultTimeout;
|
let timeout = defaultTimeout;
|
||||||
|
|
||||||
|
const spec = {
|
||||||
|
Modes: { ...TestMode },
|
||||||
|
Expectations: { ...TestExpectation },
|
||||||
|
mode() {
|
||||||
|
return mode;
|
||||||
|
},
|
||||||
|
setMode(m) {
|
||||||
|
if (mode !== TestMode.Focus)
|
||||||
|
mode = m;
|
||||||
|
},
|
||||||
|
expectations() {
|
||||||
|
return [expectation];
|
||||||
|
},
|
||||||
|
setExpectations(e) {
|
||||||
|
if (Array.isArray(e)) {
|
||||||
|
if (e.length > 1)
|
||||||
|
throw new Error('');
|
||||||
|
e = e[0];
|
||||||
|
}
|
||||||
|
expectation = e;
|
||||||
|
},
|
||||||
|
timeout() {
|
||||||
|
return timeout;
|
||||||
|
},
|
||||||
|
setTimeout(t) {
|
||||||
|
timeout = t;
|
||||||
|
},
|
||||||
|
repeat() {
|
||||||
|
return repeat;
|
||||||
|
},
|
||||||
|
setRepeat(r) {
|
||||||
|
repeat = r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const func = (...args) => {
|
const func = (...args) => {
|
||||||
for (let i = 0; i < repeat; ++i)
|
for (let i = 0; i < repeat; ++i)
|
||||||
action(mode, expectation, timeout, ...args);
|
action(mode, expectation, timeout, ...args);
|
||||||
@ -466,25 +500,20 @@ function specBuilder(defaultTimeout, action) {
|
|||||||
repeat = 1;
|
repeat = 1;
|
||||||
timeout = defaultTimeout;
|
timeout = defaultTimeout;
|
||||||
};
|
};
|
||||||
|
for (const { name, callback } of modifiers) {
|
||||||
func.skip = condition => {
|
func[name] = (...args) => {
|
||||||
if (condition)
|
callback(spec, ...args);
|
||||||
mode = TestMode.Skip;
|
|
||||||
return func;
|
return func;
|
||||||
};
|
};
|
||||||
func.fail = condition => {
|
}
|
||||||
if (condition)
|
for (const { name, callback } of attributes) {
|
||||||
expectation = TestExpectation.Fail;
|
Object.defineProperty(func, name, {
|
||||||
return func;
|
get: () => {
|
||||||
};
|
callback(spec);
|
||||||
func.slow = () => {
|
|
||||||
timeout = 3 * defaultTimeout;
|
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
func.repeat = count => {
|
});
|
||||||
repeat = count;
|
}
|
||||||
return func;
|
|
||||||
};
|
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,6 +536,8 @@ class TestRunner extends EventEmitter {
|
|||||||
this._timeout = timeout === 0 ? INFINITE_TIMEOUT : timeout;
|
this._timeout = timeout === 0 ? INFINITE_TIMEOUT : timeout;
|
||||||
this._parallel = parallel;
|
this._parallel = parallel;
|
||||||
this._breakOnFailure = breakOnFailure;
|
this._breakOnFailure = breakOnFailure;
|
||||||
|
this._modifiers = [];
|
||||||
|
this._attributes = [];
|
||||||
|
|
||||||
if (MAJOR_NODEJS_VERSION >= 8 && disableTimeoutWhenInspectorIsEnabled) {
|
if (MAJOR_NODEJS_VERSION >= 8 && disableTimeoutWhenInspectorIsEnabled) {
|
||||||
if (inspector.url()) {
|
if (inspector.url()) {
|
||||||
@ -516,24 +547,47 @@ class TestRunner extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.describe = specBuilder(this._timeout, (mode, expectation, timeout, ...args) => this._addSuite(mode, expectation, ...args));
|
|
||||||
this.fdescribe = specBuilder(this._timeout, (mode, expectation, timeout, ...args) => this._addSuite(TestMode.Focus, expectation, ...args));
|
|
||||||
this.xdescribe = specBuilder(this._timeout, (mode, expectation, timeout, ...args) => this._addSuite(TestMode.Skip, expectation, ...args));
|
|
||||||
this.it = specBuilder(this._timeout, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, mode, expectation, timeout));
|
|
||||||
this.fit = specBuilder(this._timeout, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, TestMode.Focus, expectation, timeout));
|
|
||||||
this.xit = specBuilder(this._timeout, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, TestMode.Skip, expectation, timeout));
|
|
||||||
this.dit = specBuilder(this._timeout, (mode, expectation, timeout, name, callback) => {
|
|
||||||
const test = this._addTest(name, callback, TestMode.Focus, expectation, INFINITE_TIMEOUT);
|
|
||||||
const N = callback.toString().split('\n').length;
|
|
||||||
for (let i = 0; i < N; ++i)
|
|
||||||
this._debuggerLogBreakpointLines.set(test.location.filePath, i + test.location.lineNumber);
|
|
||||||
});
|
|
||||||
this._debuggerLogBreakpointLines = new Multimap();
|
this._debuggerLogBreakpointLines = new Multimap();
|
||||||
|
|
||||||
this.beforeAll = this._addHook.bind(this, 'beforeAll');
|
this.beforeAll = this._addHook.bind(this, 'beforeAll');
|
||||||
this.beforeEach = this._addHook.bind(this, 'beforeEach');
|
this.beforeEach = this._addHook.bind(this, 'beforeEach');
|
||||||
this.afterAll = this._addHook.bind(this, 'afterAll');
|
this.afterAll = this._addHook.bind(this, 'afterAll');
|
||||||
this.afterEach = this._addHook.bind(this, 'afterEach');
|
this.afterEach = this._addHook.bind(this, 'afterEach');
|
||||||
|
|
||||||
|
this._modifiers.push({ name: 'skip', callback: (t, condition) => condition && t.setMode(t.Modes.Skip) });
|
||||||
|
this._modifiers.push({ name: 'fail', callback: (t, condition) => condition && t.setExpectations(t.Expectations.Fail) });
|
||||||
|
this._modifiers.push({ name: 'slow', callback: (t, condition) => condition && t.setTimeout(t.timeout() * 3) });
|
||||||
|
this._modifiers.push({ name: 'repeat', callback: (t, count) => t.setRepeat(count) });
|
||||||
|
this._attributes.push({ name: 'focus', callback: t => t.setMode(t.Modes.Focus) });
|
||||||
|
this._buildSpecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildSpecs() {
|
||||||
|
this.describe = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, ...args) => this._addSuite(mode, expectation, ...args));
|
||||||
|
this.fdescribe = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, ...args) => this._addSuite(TestMode.Focus, expectation, ...args));
|
||||||
|
this.xdescribe = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, ...args) => this._addSuite(TestMode.Skip, expectation, ...args));
|
||||||
|
this.it = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, mode, expectation, timeout));
|
||||||
|
this.fit = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, TestMode.Focus, expectation, timeout));
|
||||||
|
this.xit = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, name, callback) => this._addTest(name, callback, TestMode.Skip, expectation, timeout));
|
||||||
|
this.dit = specBuilder(this._timeout, this._modifiers, this._attributes, (mode, expectation, timeout, name, callback) => {
|
||||||
|
const test = this._addTest(name, callback, TestMode.Focus, expectation, INFINITE_TIMEOUT);
|
||||||
|
const N = callback.toString().split('\n').length;
|
||||||
|
for (let i = 0; i < N; ++i)
|
||||||
|
this._debuggerLogBreakpointLines.set(test.location.filePath, i + test.location.lineNumber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildSpec() {
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier(name, callback) {
|
||||||
|
this._modifiers.push({ name, callback });
|
||||||
|
this._buildSpecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute(name, callback) {
|
||||||
|
this._attributes.push({ name, callback });
|
||||||
|
this._buildSpecs();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadTests(module, ...args) {
|
loadTests(module, ...args) {
|
||||||
|
|||||||
@ -159,6 +159,49 @@ module.exports.addTests = function({testRunner, expect}) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('TestRunner attributes', () => {
|
||||||
|
it('should work', async() => {
|
||||||
|
const t = newTestRunner({timeout: 123});
|
||||||
|
const log = [];
|
||||||
|
|
||||||
|
t.modifier('foo', (t, ...args) => {
|
||||||
|
log.push('foo');
|
||||||
|
|
||||||
|
expect(t.Modes.Run).toBeTruthy();
|
||||||
|
expect(t.Modes.Skip).toBeTruthy();
|
||||||
|
expect(t.Modes.Focus).toBeTruthy();
|
||||||
|
expect(t.mode()).toBe(t.Modes.Run);
|
||||||
|
expect(t.Expectations.Ok).toBeTruthy();
|
||||||
|
expect(t.Expectations.Fail).toBeTruthy();
|
||||||
|
expect(t.expectations()).toEqual([t.Expectations.Ok]);
|
||||||
|
expect(t.timeout()).toBe(123);
|
||||||
|
expect(t.repeat()).toBe(1);
|
||||||
|
|
||||||
|
expect(args.length).toBe(2);
|
||||||
|
expect(args[0]).toBe('uno');
|
||||||
|
expect(args[1]).toBe('dos');
|
||||||
|
|
||||||
|
t.setMode(t.Modes.Focus);
|
||||||
|
t.setExpectations([t.Expectations.Fail]);
|
||||||
|
t.setTimeout(234);
|
||||||
|
t.setRepeat(42);
|
||||||
|
});
|
||||||
|
|
||||||
|
t.attribute('bar', t => {
|
||||||
|
log.push('bar');
|
||||||
|
expect(t.mode()).toBe(t.Modes.Focus);
|
||||||
|
t.setMode(t.Modes.Skip);
|
||||||
|
expect(t.mode()).toBe(t.Modes.Focus);
|
||||||
|
expect(t.expectations()).toEqual([t.Expectations.Fail]);
|
||||||
|
expect(t.timeout()).toBe(234);
|
||||||
|
expect(t.repeat()).toBe(42);
|
||||||
|
});
|
||||||
|
|
||||||
|
t.it.foo('uno', 'dos').bar('test', () => { });
|
||||||
|
expect(log).toEqual(['foo', 'bar']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('TestRunner hooks', () => {
|
describe('TestRunner hooks', () => {
|
||||||
it('should run all hooks in proper order', async() => {
|
it('should run all hooks in proper order', async() => {
|
||||||
const log = [];
|
const log = [];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user