Source: execute-async-expression-test.js
const { noop } = require('lodash');
const nanoid = require('nanoid');
const expect = require('chai').expect;
const TestRun = require('../../lib/test-run/index');
const TestController = require('../../lib/api/test-controller');
const COMMAND_TYPE = require('../../lib/test-run/commands/type');
const markerSymbol = require('../../lib/test-run/marker-symbol');
const debugLogger = require('../../lib/notifications/debug-logger');
const assertTestRunError = require('./helpers/assert-test-run-error');
let callsite = 0;
function createTestRunMock () {
function TestRunMock () {
this.session = { id: nanoid(7) };
this.test = { name: 'Test', testFile: { filename: __filename } };
this.debugLog = { command: noop };
this.controller = new TestController(this);
this.driverTaskQueue = [];
this.emit = noop;
this.debugLogger = debugLogger;
this[markerSymbol] = true;
this.browserConnection = {
isHeadlessBrowser: () => false,
userAgent: 'Chrome'
};
}
TestRunMock.prototype = TestRun.prototype;
return new TestRunMock();
}
async function executeAsyncExpression (expression, testRun = createTestRunMock()) {
callsite++;
return await testRun.executeCommand({
type: COMMAND_TYPE.executeAsyncExpression,
expression
}, callsite.toString());
}
async function executeExpression (expression, customVarName, testRun = createTestRunMock()) {
return testRun.executeCommand({
type: COMMAND_TYPE.executeExpression,
resultVariableName: customVarName,
expression
});
}
async function assertError (expression, expectedMessage, expectedLine, expectedColumn) {
let catched = false;
try {
await executeAsyncExpression(expression);
}
catch (err) {
catched = true;
expect(err.errMsg).eql(expectedMessage);
expect(err.line).eql(expectedLine);
expect(err.column).eql(expectedColumn);
expect(err.callsite).eql(callsite.toString());
expect(err.expression).eql(expression);
}
expect(catched).eql(true);
}
async function assertTestCafeError (expression, expectedFileName) {
let catched = false;
try {
await executeAsyncExpression(expression);
}
catch (err) {
catched = true;
assertTestRunError(err, expectedFileName, false);
}
expect(catched).eql(true);
}
describe('Code steps', () => {
beforeEach(() => {
callsite = 0;
});
it('basic', async () => {
const res = await executeAsyncExpression('return 1+1;');
expect(res).eql(2);
});
it('error', async () => {
await assertError('u=void 0;u.t=5;', 'Cannot set property \'t\' of undefined', 1, 13, '1');
await assertError(
'let q = void 0;\n' +
' q.t = 5;'
, 'Cannot set property \'t\' of undefined', 2, 13, '2');
await assertError(
'let q = 3;\n' +
'q = 4;\n' +
'throw new Error(\'custom error\')'
, 'custom error', 3, 7, '3');
});
describe('TestCafe errors', () => {
it('Test run error', async () => {
await assertTestCafeError("await t.wait('10');", '../data/execute-async-expression/test-run-error');
});
it('Runtime run error', async () => {
await assertTestCafeError('const s = Selector();', '../data/execute-async-expression/runtime-error');
});
});
it('sync expression does not spoil global context', async () => {
const testRun = createTestRunMock();
await executeExpression('1+1', 'myCustomVar1', testRun);
await executeExpression('1+myCustomVar1', 'myCustomVar2', testRun);
expect(typeof myCustomVar1).eql('undefined');
expect(typeof myCustomVar2).eql('undefined');
expect(await executeExpression('myCustomVar1', void 0, testRun)).eql(2);
expect(await executeExpression('myCustomVar2', void 0, testRun)).eql(3);
});
it('shared context with global variables', async () => {
const testRun = createTestRunMock();
await executeAsyncExpression('result = 10;', testRun);
const res = await executeAsyncExpression('return result + 3', testRun);
expect(res).eql(13);
expect(typeof result).eql('undefined');
});
it('shared context with local variables', async () => {
const testRun = createTestRunMock();
await executeAsyncExpression('const result = 10;', testRun);
try {
await executeAsyncExpression('return result + 3', testRun);
}
catch (err) {
expect(err.code).eql('E66');
expect(err.errMsg).eql('result is not defined');
}
});
it('different context', async () => {
await executeAsyncExpression('result = 10;');
try {
await executeAsyncExpression('result + 3');
}
catch (err) {
expect(err.code).eql('E66');
expect(err.errMsg).eql('result is not defined');
}
});
it('promises', () => {
return executeAsyncExpression(`
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hooray!');
}, 20);
});
`)
.then(result => {
expect(result).eql('hooray!');
});
});
it('async/await', () => {
return executeAsyncExpression(`
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hooray!');
}, 20);
});
const result = await promise;
return result;
`)
.then(result => {
expect(result).eql('hooray!');
});
});
it('require - absolute', async () => {
await executeAsyncExpression(`
return require('testcafe-hammerhead');
`)
.then(result => {
expect(result).eql(require('testcafe-hammerhead'));
});
});
it('require - relative', async () => {
await executeAsyncExpression(`
return require('./helpers/console-wrapper');
`)
.then(result => {
expect(result).eql(require('./helpers/console-wrapper'));
});
});
it('globals', async () => {
const result = await executeAsyncExpression(`
Buffer.from('test');
const timeout = setTimeout(function () {});
const immediate = setImmediate(function () {});
const interval = setInterval(function () {});
clearTimeout(timeout);
clearImmediate(immediate);
clearInterval(interval);
return { __dirname, __filename };
`);
expect(result.__dirname).eql(__dirname);
expect(result.__filename).eql(__filename);
});
it('Selector/ClientFunction/Role/RequestMock/RequestHook/RequestLogger', async () => {
await executeAsyncExpression(`
const selector = Selector('button');
const clientFunction = ClientFunction(() => {});
const role = Role('http://example.com', () => {});
const mock = RequestMock();
const logger = RequestLogger();
const hook = new RequestHook();
`);
});
describe('test controller', () => {
it('basic', async () => {
await executeAsyncExpression(`
await t.wait(10);
`);
});
it('shared context', async () => {
const testRun = createTestRunMock();
await executeAsyncExpression(`
t.testRun.sharedVar = 1;
`, testRun);
await executeAsyncExpression(`
if (!t.testRun.sharedVar)
t.testRun.sharedVar = 2;
`, testRun);
expect(testRun.sharedVar).eql(1);
});
it('different context', async () => {
const testRun1 = createTestRunMock();
const testRun2 = createTestRunMock();
await executeAsyncExpression(`
t.testRun.sharedVar = 1;
`, testRun1);
await executeAsyncExpression(`
if (!t.testRun.sharedVar)
t.testRun.sharedVar = 2;
`, testRun2);
expect(testRun1.sharedVar).eql(1);
expect(testRun2.sharedVar).eql(2);
});
it('debug', async () => {
const testRun = createTestRunMock();
let debugMsg = '';
let err = null;
testRun._enqueueCommand = () => Promise.resolve();
const initialWrite = process.stdout.write;
process.stdout.write = chunk => {
debugMsg += chunk.toString();
};
try {
await executeAsyncExpression('await t.debug();', testRun);
}
catch (e) {
err = e;
}
process.stdout.write = initialWrite;
expect(err).eql(null);
expect(debugMsg).contains('Chrome');
expect(debugMsg).contains('DEBUGGER PAUSE');
});
});
});