Skip to content

Commit 051dec3

Browse files
committed
refactor, add action name to command, add actionResult to reportTestActionDone
1 parent 3b8f5db commit 051dec3

File tree

11 files changed

+129
-52
lines changed

11 files changed

+129
-52
lines changed
File renamed without changes.

src/api/test-controller/custom-actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export default class CustomActions {
2222
this[delegatedAPI(name)] = (...args) => {
2323
const callsite = getCallsiteForMethod(name) || void 0;
2424

25-
return this._testController._enqueueCommand(RunCustomActionCommand, { fn, args }, this._validateCommand, callsite);
25+
return this._testController._enqueueCommand(RunCustomActionCommand, { fn, args, name }, this._validateCommand, callsite);
2626
};
2727
});
2828

src/api/wrap-custom-action.ts

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,12 @@
1-
import TestController from './test-controller';
21
import testRunTracker from './test-run-tracker';
3-
import TestRun from '../test-run';
4-
import TestCafeErrorList from '../errors/error-list';
5-
import { MissingAwaitError } from '../errors/test-run';
6-
import addRenderedWarning from '../notifications/add-rendered-warning';
7-
import WARNING_MESSAGES from '../notifications/warning-message';
8-
import { addErrors, addWarnings } from './test-controller/add-errors';
2+
import wrapTestFunction, { WrapTestFunctionExecutorArguments } from './wrap-test-function';
93

104
export default function wrapCustomAction (fn: Function): Function {
11-
return async (testRun: TestRun, functionArgs: any) => {
12-
let result = null;
13-
const errList = new TestCafeErrorList();
14-
15-
testRun.controller = new TestController(testRun);
16-
5+
const executor = async function ({ testRun, functionArgs }: WrapTestFunctionExecutorArguments): Promise<any> {
176
const markeredfn = testRunTracker.addTrackingMarkerToFunction(testRun.id, fn, testRun.controller);
187

19-
testRun.observedCallsites.clear();
20-
testRunTracker.ensureEnabled();
21-
22-
try {
23-
result = await markeredfn(...functionArgs);
24-
}
25-
catch (err) {
26-
errList.addError(err);
27-
}
28-
29-
if (!errList.hasUncaughtErrorsInTestCode) {
30-
for (const { callsite, actionId } of testRun.observedCallsites.awaitedSnapshotWarnings.values())
31-
addRenderedWarning(testRun.warningLog, { message: WARNING_MESSAGES.excessiveAwaitInAssertion, actionId }, callsite);
32-
33-
addWarnings(testRun.observedCallsites.unawaitedSnapshotCallsites, WARNING_MESSAGES.missingAwaitOnSnapshotProperty, testRun);
34-
addErrors(testRun.observedCallsites.callsitesWithoutAwait, MissingAwaitError, errList);
35-
}
36-
37-
if (errList.hasErrors)
38-
throw errList;
39-
40-
return result;
8+
return await markeredfn(...functionArgs);
419
};
10+
11+
return wrapTestFunction(fn, executor);
4212
}

src/api/wrap-test-function.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
1-
import TestController from './test-controller';
21
import testRunTracker from './test-run-tracker';
32
import TestRun from '../test-run';
3+
import TestController from './test-controller';
44
import TestCafeErrorList from '../errors/error-list';
55
import { MissingAwaitError } from '../errors/test-run';
66
import addRenderedWarning from '../notifications/add-rendered-warning';
77
import WARNING_MESSAGES from '../notifications/warning-message';
8-
import { addErrors, addWarnings } from './test-controller/add-errors';
8+
import { addErrors, addWarnings } from './test-controller/add-message';
9+
10+
export interface WrapTestFunctionExecutorArguments {
11+
testRun: TestRun;
12+
functionArgs: any[];
13+
fn: Function;
14+
}
915

10-
export default function wrapTestFunction (fn: Function): Function {
11-
return async (testRun: TestRun) => {
12-
let result = null;
13-
const errList = new TestCafeErrorList();
14-
const markeredfn = testRunTracker.addTrackingMarkerToFunction(testRun.id, fn);
16+
const defaultExecutor = async function ({ testRun, fn }: WrapTestFunctionExecutorArguments): Promise<any> {
17+
const markeredfn = testRunTracker.addTrackingMarkerToFunction(testRun.id, fn);
18+
19+
return await markeredfn(testRun.controller);
20+
};
21+
22+
export default function wrapTestFunction (fn: Function, executor: Function = defaultExecutor): Function {
23+
return async (testRun: TestRun, functionArgs: any) => {
24+
let result = null;
25+
const errList = new TestCafeErrorList();
1526

1627
testRun.controller = new TestController(testRun);
1728

1829
testRun.observedCallsites.clear();
19-
2030
testRunTracker.ensureEnabled();
2131

2232
try {
23-
result = await markeredfn(testRun.controller);
33+
result = await executor({ fn, functionArgs, testRun });
2434
}
2535
catch (err) {
2636
errList.addError(err);
2737
}
2838

2939
if (!errList.hasUncaughtErrorsInTestCode) {
30-
for (const { callsite, actionId } of testRun.observedCallsites.awaitedSnapshotWarnings.values())
31-
addRenderedWarning(testRun.warningLog, { message: WARNING_MESSAGES.excessiveAwaitInAssertion, actionId }, callsite);
40+
for (const { callsite, actionId } of testRun.observedCallsites.awaitedSnapshotWarnings.values()) {
41+
addRenderedWarning(testRun.warningLog, {
42+
message: WARNING_MESSAGES.excessiveAwaitInAssertion,
43+
actionId,
44+
}, callsite);
45+
}
3246

3347
addWarnings(testRun.observedCallsites.unawaitedSnapshotCallsites, WARNING_MESSAGES.missingAwaitOnSnapshotProperty, testRun);
3448
addErrors(testRun.observedCallsites.callsitesWithoutAwait, MissingAwaitError, errList);
@@ -40,3 +54,4 @@ export default function wrapTestFunction (fn: Function): Function {
4054
return result;
4155
};
4256
}
57+

src/errors/runtime/templates.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/reporter/command/command-formatter.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { isEmpty } from 'lodash';
22
import { ExecuteSelectorCommand, ExecuteClientFunctionCommand } from '../../test-run/commands/observation';
33
import {
44
NavigateToCommand,
5-
PressKeyCommand,
5+
PressKeyCommand, RunCustomActionCommand,
66
SetNativeDialogHandlerCommand,
77
TypeTextCommand,
88
UseRoleCommand,
@@ -54,6 +54,9 @@ export class CommandFormatter {
5454
else
5555
this._assignProperties(this._command, formattedCommand);
5656

57+
if (this._command instanceof RunCustomActionCommand)
58+
this._assignCustomActionResult(formattedCommand);
59+
5760
this._maskConfidentialInfo(formattedCommand);
5861

5962
return formattedCommand;
@@ -125,6 +128,11 @@ export class CommandFormatter {
125128
return command.url;
126129
}
127130

131+
private _assignCustomActionResult (formatedCommand: FormattedCommand) :void {
132+
if (this._result !== void 0)
133+
formatedCommand.actionResult = this._result;
134+
}
135+
128136
private _assignProperties (command: CommandBase, formattedCommand: FormattedCommand): void {
129137
if (!this._command.getReportedProperties)
130138
return;

src/test-run/commands/actions.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ export class RemoveRequestHooksCommand extends ActionCommandBase {
281281
export class RunCustomActionCommand extends ActionCommandBase {
282282
public constructor (obj: object, testRun: TestRun, validateProperties: boolean);
283283
public fn: Function;
284+
public name: string;
284285
public args: any;
286+
public actionResult: any;
285287
}
286288

src/test-run/commands/actions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ export class RunCustomActionCommand extends ActionCommandBase {
779779
getAssignableProperties () {
780780
return [
781781
{ name: 'fn', type: functionArgument, required: true },
782+
{ name: 'name', type: stringArgument, required: true },
782783
{ name: 'args', required: false },
783784
];
784785
}

test/functional/fixtures/custom-actions/actions.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ async function typeToInputAndCheckResult (inputSelector, buttonSelector, resultS
1717
.expect(await this.custom.getSpanTextBySelector(resultSelector)).eql(inputText);
1818
}
1919

20+
function getTextValue () {
21+
return 'some text';
22+
}
23+
2024
module.exports = {
2125
getSpanTextBySelector,
2226
clickBySelector,
2327
typeTextAndClickButton,
2428
typeToInputAndCheckResult,
29+
getTextValue,
2530
};

test/functional/fixtures/custom-actions/test.js

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ const {
22
clickBySelector,
33
getSpanTextBySelector,
44
typeTextAndClickButton,
5-
typeToInputAndCheckResult,
5+
typeToInputAndCheckResult, getTextValue,
66
} = require('./actions');
77

8-
const { expect } = require('chai');
9-
const config = require('../../config');
8+
const { expect } = require('chai');
9+
const config = require('../../config');
10+
const { createReporter } = require('../../utils/reporter');
1011

1112
(config.experimentalDebug ? describe.skip : describe)('[API] Custom Actions', function () {
1213
it('Should run custom click action', function () {
@@ -40,6 +41,14 @@ const config = require('../../config');
4041
});
4142
});
4243

44+
it('Should run non-async custom action', function () {
45+
return runTests('./testcafe-fixtures/index.js', 'Should run non-async custom action', {
46+
customActions: {
47+
getTextValue,
48+
},
49+
});
50+
});
51+
4352
it('Should throw an exception inside custom action', function () {
4453
return runTests('./testcafe-fixtures/index.js', 'Should throw an exception inside custom action', {
4554
customActions: { clickBySelector },
@@ -58,5 +67,66 @@ const config = require('../../config');
5867
expect(errs[0]).contains('TypeError: t.custom.clickBySelector is not a function');
5968
});
6069
});
70+
71+
it('Should report all actions in correct order', function () {
72+
function ReporterRecord (phase, actionName, command) {
73+
this.phase = phase;
74+
this.actionName = actionName;
75+
if (command.type !== 'run-custom-action')
76+
return this;
77+
78+
delete command.actionId;
79+
delete command.fn;
80+
delete command.args;
81+
82+
this.command = command;
83+
}
84+
85+
const result = [];
86+
const expectedResult = [
87+
{ phase: 'start', actionName: 'runCustomAction', command: { type: 'run-custom-action', name: 'typeToInputAndCheckResult' } },
88+
{ phase: 'start', actionName: 'runCustomAction', command: { type: 'run-custom-action', name: 'typeTextAndClickButton' } },
89+
{ phase: 'start', actionName: 'typeText' },
90+
{ phase: 'end', actionName: 'typeText' },
91+
{ phase: 'start', actionName: 'click' },
92+
{ phase: 'end', actionName: 'click' },
93+
{ phase: 'end', actionName: 'runCustomAction', command: { type: 'run-custom-action', name: 'typeTextAndClickButton' } },
94+
{ phase: 'start', actionName: 'runCustomAction', command: { type: 'run-custom-action', name: 'getSpanTextBySelector' } },
95+
{ phase: 'start', actionName: 'execute-selector' },
96+
{ phase: 'end', actionName: 'execute-selector' },
97+
{
98+
phase: 'end',
99+
actionName: 'runCustomAction',
100+
command: {
101+
type: 'run-custom-action',
102+
name: 'getSpanTextBySelector',
103+
actionResult: 'Some text',
104+
},
105+
},
106+
{ phase: 'start', actionName: 'eql' },
107+
{ phase: 'end', actionName: 'eql' },
108+
{ phase: 'end', actionName: 'runCustomAction', command: { type: 'run-custom-action', name: 'typeToInputAndCheckResult' } },
109+
];
110+
111+
const reporter = createReporter({
112+
reportTestActionStart: (name, { command }) => {
113+
result.push(new ReporterRecord('start', name, command));
114+
},
115+
reportTestActionDone: (name, { command }) => {
116+
result.push(new ReporterRecord('end', name, command));
117+
},
118+
});
119+
120+
return runTests('./testcafe-fixtures/index.js', 'Should run custom action inside another custom action', {
121+
customActions: {
122+
typeToInputAndCheckResult,
123+
typeTextAndClickButton,
124+
getSpanTextBySelector,
125+
},
126+
reporter,
127+
}).then(() => {
128+
expect(result).to.deep.equal(expectedResult);
129+
});
130+
});
61131
});
62132

0 commit comments

Comments
 (0)