forked from DevExpress/testcafe
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement test and fixture modifiers (DevExpress#1107)
* Implement test.only and fixture.only * Move logic for test.only filtering to bootstrapper. * Implement test.skip and fixture.skip * Add tests for test.skip * Fix test error. Implement test.page. Refactor. * Fix raw API. * Add test for test.page * Implement test.before and test.after hooks * Fix tests * Tests for test.before and test.after * Implement test.httpAuth. Add tests for test.before and test.after args * Test test.httpAuth. Fix compiler test file heuristics * Implement t.ctx * Make t.ctx assignable * Fix compiler filter RegExps
- Loading branch information
Showing
50 changed files
with
760 additions
and
238 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,57 @@ | ||
import { APIError } from '../../errors/runtime'; | ||
import MESSAGE from '../../errors/runtime/message'; | ||
import handleTagArgs from '../../utils/handle-tag-args'; | ||
import wrapTestFunction from './wrap-test-function'; | ||
import { assertObject, assertString } from '../../errors/runtime/type-assertions'; | ||
import TestingUnit from './testing-unit'; | ||
|
||
const PROTOCOL_RE = /^https?:\/\//; | ||
const IMPLICIT_PROTOCOL_RE = /^\/\//; | ||
export default class Fixture extends TestingUnit { | ||
constructor (globals) { | ||
super(globals); | ||
|
||
export default class Fixture { | ||
constructor (name, filename) { | ||
var nameType = typeof name; | ||
this.path = globals.filename; | ||
|
||
if (nameType !== 'string') | ||
throw new APIError('fixture', MESSAGE.fixtureNameIsNotAString, nameType); | ||
this.pageUrl = 'about:blank'; | ||
|
||
this.name = name; | ||
this.path = filename; | ||
this.pageUrl = 'about:blank'; | ||
this.beforeEachFn = null; | ||
this.afterEachFn = null; | ||
this.authCredentials = null; | ||
} | ||
|
||
page (url, ...rest) { | ||
this.pageUrl = handleTagArgs(url, rest); | ||
|
||
var urlType = typeof this.pageUrl; | ||
|
||
if (urlType !== 'string') | ||
throw new APIError('page', MESSAGE.fixturePageIsNotAString, urlType); | ||
|
||
if (!PROTOCOL_RE.test(this.pageUrl)) { | ||
var protocol = IMPLICIT_PROTOCOL_RE.test(this.pageUrl) ? 'http:' : 'http://'; | ||
|
||
this.pageUrl = protocol + this.pageUrl; | ||
} | ||
|
||
return this; | ||
return this.apiOrigin; | ||
} | ||
|
||
httpAuth (credentials) { | ||
assertObject('httpAuth', 'credentials', credentials); | ||
assertString('httpAuth', 'credentials.username', credentials.username); | ||
assertString('httpAuth', 'credentials.password', credentials.password); | ||
_add (name, ...rest) { | ||
name = handleTagArgs(name, rest); | ||
|
||
var nameType = typeof name; | ||
|
||
if (credentials.domain) | ||
assertString('httpAuth', 'credentials.domain', credentials.domain); | ||
if (credentials.workstation) | ||
assertString('httpAuth', 'credentials.workstation', credentials.workstation); | ||
if (nameType !== 'string') | ||
throw new APIError('apiOrigin', MESSAGE.fixtureNameIsNotAString, nameType); | ||
|
||
this.authCredentials = credentials; | ||
this.name = name; | ||
this.globals.currentFixture = this; | ||
|
||
return this; | ||
return this.apiOrigin; | ||
} | ||
|
||
beforeEach (fn) { | ||
_beforeEach$ (fn) { | ||
var fnType = typeof fn; | ||
|
||
if (fnType !== 'function') | ||
throw new APIError('beforeEach', MESSAGE.beforeEachIsNotAFunction, fnType); | ||
|
||
this.beforeEachFn = wrapTestFunction(fn); | ||
this.beforeEachFn = TestingUnit._wrapTestFunction(fn); | ||
|
||
return this; | ||
return this.apiOrigin; | ||
} | ||
|
||
afterEach (fn) { | ||
_afterEach$ (fn) { | ||
var fnType = typeof fn; | ||
|
||
if (fnType !== 'function') | ||
throw new APIError('afterEach', MESSAGE.afterEachIsNotAFunction, fnType); | ||
|
||
this.afterEachFn = wrapTestFunction(fn); | ||
this.afterEachFn = TestingUnit._wrapTestFunction(fn); | ||
|
||
return this; | ||
return this.apiOrigin; | ||
} | ||
} | ||
|
||
TestingUnit._makeAPIListForChildClass(Fixture); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,27 @@ | ||
import Fixture from './fixture'; | ||
import Test from './test'; | ||
import handleTagArgs from '../../utils/handle-tag-args'; | ||
|
||
export default class Globals { | ||
constructor (filename) { | ||
this.filename = filename; | ||
this.currentFixture = null; | ||
this.collectedTests = []; | ||
|
||
var globals = this; | ||
|
||
// NOTE: use named functions so that they appear in the stacks | ||
this.functions = { | ||
fixture (name, ...rest) { | ||
name = handleTagArgs(name, rest); | ||
|
||
globals.currentFixture = new Fixture(name, globals.filename); | ||
|
||
return globals.currentFixture; | ||
}, | ||
|
||
test (name, fn) { | ||
var test = new Test(name, fn, globals.currentFixture); | ||
|
||
globals.collectedTests.push(test); | ||
} | ||
}; | ||
} | ||
|
||
setup () { | ||
Object.keys(this.functions).forEach(name => { | ||
global[name] = this.functions[name]; | ||
Object.defineProperty(global, 'fixture', { | ||
get: () => new Fixture(this), | ||
configurable: true | ||
}); | ||
|
||
Object.defineProperty(global, 'test', { | ||
get: () => new Test(this), | ||
configurable: true | ||
}); | ||
} | ||
|
||
remove () { | ||
Object.keys(this.functions).forEach(name => delete global[name]); | ||
delete global.fixture; | ||
delete global.test; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,56 @@ | ||
import { APIError } from '../../errors/runtime'; | ||
import MESSAGE from '../../errors/runtime/message'; | ||
import wrapTestFunction from './wrap-test-function'; | ||
import TestingUnit from './testing-unit'; | ||
import { assertFunction } from '../../errors/runtime/type-assertions'; | ||
|
||
export default class Test { | ||
constructor (name, fn, fixture) { | ||
export default class Test extends TestingUnit { | ||
constructor (globals) { | ||
super(globals); | ||
|
||
this.fixture = globals.currentFixture; | ||
|
||
this.fn = null; | ||
this.beforeFn = null; | ||
this.afterFn = null; | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_add (name, fn) { | ||
var nameType = typeof name; | ||
|
||
if (nameType !== 'string') | ||
throw new APIError('test', MESSAGE.testNameIsNotAString, nameType); | ||
throw new APIError('apiOrigin', MESSAGE.testNameIsNotAString, nameType); | ||
|
||
var fnType = typeof fn; | ||
|
||
if (fnType !== 'function') | ||
throw new APIError('test', MESSAGE.testBodyIsNotAFunction, fnType); | ||
throw new APIError('apiOrigin', MESSAGE.testBodyIsNotAFunction, fnType); | ||
|
||
this.name = name; | ||
this.fn = TestingUnit._wrapTestFunction(fn); | ||
|
||
if (this.globals.collectedTests.indexOf(this) < 0) | ||
this.globals.collectedTests.push(this); | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_before$ (fn) { | ||
assertFunction('before', 'test.before hook', fn); | ||
|
||
this.beforeFn = TestingUnit._wrapTestFunction(fn); | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_after$ (fn) { | ||
assertFunction('after', 'test.after hook', fn); | ||
|
||
this.name = name; | ||
this.fixture = fixture; | ||
this.fn = wrapTestFunction(fn); | ||
this.afterFn = TestingUnit._wrapTestFunction(fn); | ||
|
||
return this.apiOrigin; | ||
} | ||
} | ||
|
||
TestingUnit._makeAPIListForChildClass(Test); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { APIError } from '../../errors/runtime'; | ||
import MESSAGE from '../../errors/runtime/message'; | ||
import handleTagArgs from '../../utils/handle-tag-args'; | ||
import { delegateAPI, getDelegatedAPIList } from '../../utils/delegated-api'; | ||
import { assertObject, assertString } from '../../errors/runtime/type-assertions'; | ||
import TestController from '../test-controller'; | ||
import clientFnTestRunTracker from '../../client-functions/test-run-tracker'; | ||
import processTestFnError from '../../errors/process-test-fn-error'; | ||
|
||
const PROTOCOL_RE = /^https?:\/\//; | ||
const IMPLICIT_PROTOCOL_RE = /^\/\//; | ||
|
||
export default class TestingUnit { | ||
constructor (globals) { | ||
this.globals = globals; | ||
|
||
this.name = null; | ||
this.pageUrl = null; | ||
this.authCredentials = null; | ||
this.only = false; | ||
this.skip = false; | ||
|
||
var unit = this; | ||
|
||
this.apiOrigin = function apiOrigin (...args) { | ||
return unit._add(...args); | ||
}; | ||
|
||
delegateAPI(this, this.apiOrigin, this.constructor.API_LIST, null, false); | ||
} | ||
|
||
_add () { | ||
throw new Error('Not implemented'); | ||
} | ||
|
||
_only$getter () { | ||
this.only = true; | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_skip$getter () { | ||
this.skip = true; | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_page$ (url, ...rest) { | ||
this.pageUrl = handleTagArgs(url, rest); | ||
|
||
var urlType = typeof this.pageUrl; | ||
|
||
if (urlType !== 'string') | ||
throw new APIError('page', MESSAGE.pageIsNotAString, urlType); | ||
|
||
if (!PROTOCOL_RE.test(this.pageUrl)) { | ||
var protocol = IMPLICIT_PROTOCOL_RE.test(this.pageUrl) ? 'http:' : 'http://'; | ||
|
||
this.pageUrl = protocol + this.pageUrl; | ||
} | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
_httpAuth$ (credentials) { | ||
assertObject('httpAuth', 'credentials', credentials); | ||
assertString('httpAuth', 'credentials.username', credentials.username); | ||
assertString('httpAuth', 'credentials.password', credentials.password); | ||
|
||
if (credentials.domain) | ||
assertString('httpAuth', 'credentials.domain', credentials.domain); | ||
if (credentials.workstation) | ||
assertString('httpAuth', 'credentials.workstation', credentials.workstation); | ||
|
||
this.authCredentials = credentials; | ||
|
||
return this.apiOrigin; | ||
} | ||
|
||
static _wrapTestFunction (fn) { | ||
return async testRun => { | ||
var result = null; | ||
var controller = new TestController(testRun); | ||
var markeredfn = clientFnTestRunTracker.addTrackingMarkerToFunction(testRun.id, fn); | ||
|
||
clientFnTestRunTracker.ensureEnabled(); | ||
|
||
try { | ||
result = await markeredfn(controller); | ||
} | ||
catch (err) { | ||
throw processTestFnError(err); | ||
} | ||
|
||
// NOTE: check if the last command in the test | ||
// function is missing the `await` keyword. | ||
controller._checkForMissingAwait(); | ||
|
||
return result; | ||
}; | ||
} | ||
|
||
static _makeAPIListForChildClass (ChildClass) { | ||
ChildClass.API_LIST = TestingUnit.API_LIST.concat(getDelegatedAPIList(ChildClass.prototype)); | ||
} | ||
} | ||
|
||
TestingUnit.API_LIST = getDelegatedAPIList(TestingUnit.prototype); | ||
|
||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.