Skip to content

Commit 97329b2

Browse files
inikulinAlexanderMoskovkin
authored andcommitted
Unify errors rendering (closes #600) (#622)
* Implement `t.select` * Unify error messages: test run errors * Fix rebase errors * Unify error messages: runtime errors * Move buildReporterPlugin to embedding utils * Bump version
1 parent e5330f8 commit 97329b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+227
-255
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "testcafe",
3-
"version": "0.0.17",
3+
"version": "0.0.18",
44
"main": "lib/index",
55
"bin": {
66
"testcafe": "./bin/testcafe"

src/errors/runtime/message.js

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/errors/test-run/index.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,8 @@ export class ActionUnsupportedDeviceTypeError extends ActionArgumentErrorBase {
209209

210210
// Selector errors
211211
export class ActionSelectorError extends TestRunErrorBase {
212-
constructor (errMsg) {
213-
super(TYPE.actionSelectorError);
214-
215-
this.errMsg = errMsg;
216-
}
217-
}
218-
219-
export class ActionAdditionalSelectorError extends TestRunErrorBase {
220212
constructor (selectorName, errMsg) {
221-
super(TYPE.actionAdditionalSelectorError);
213+
super(TYPE.actionSelectorError);
222214

223215
this.selectorName = selectorName;
224216
this.errMsg = errMsg;

src/errors/test-run/templates.js

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ function markup (err, msgMarkup) {
2222

2323
export default {
2424
[TYPE.actionPositiveIntegerOptionError]: err => markup(err, `
25-
The <code>${err.optionName}</code> option is expected to be a positive integer, but it was <code>${err.actualValue}</code>.
25+
The "${err.optionName}" option is expected to be a positive integer, but it was ${err.actualValue}.
2626
2727
${err.getCallsiteMarkup()}
2828
`),
2929

3030
[TYPE.actionBooleanOptionError]: err => markup(err, `
31-
The <code>${err.optionName}</code> option is expected to be a boolean value, but it was <code>${err.actualValue}</code>.
31+
The "${err.optionName}" option is expected to be a boolean value, but it was ${err.actualValue}.
3232
3333
${err.getCallsiteMarkup()}
3434
`),
@@ -54,61 +54,61 @@ export default {
5454
`),
5555

5656
[TYPE.uncaughtErrorInClientFunctionCode]: err => markup(err, `
57-
An error occurred in <code>${err.instantiationCallsiteName}</code> code:
57+
An error occurred in ${err.instantiationCallsiteName} code:
5858
5959
${escapeHtml(err.errMsg)}
6060
6161
${err.getCallsiteMarkup()}
6262
`),
6363

6464
[TYPE.clientFunctionExecutionInterruptionError]: err => markup(err, `
65-
<code>${err.instantiationCallsiteName}</code> execution was interrupted by page unload. This problem may appear if you trigger page navigation from <code>${err.instantiationCallsiteName}</code> code.
65+
${err.instantiationCallsiteName} execution was interrupted by page unload. This problem may appear if you trigger page navigation from ${err.instantiationCallsiteName} code.
6666
6767
${err.getCallsiteMarkup()}
6868
`),
6969

7070
[TYPE.uncaughtNonErrorObjectInTestCode]: err => markup(err, `
71-
Uncaught ${err.objType} "${escapeHtml(err.objStr)}" was thrown. Throw <code>Error</code> instead.
71+
Uncaught ${err.objType} "${escapeHtml(err.objStr)}" was thrown. Throw Error instead.
7272
`),
7373

7474
[TYPE.actionOptionsTypeError]: err => markup(err, `
75-
Action options is expected to be an object, <code>null</code> or <code>undefined</code> but it was <code>${err.actualType}</code>.
75+
Action options is expected to be an object, null or undefined but it was ${err.actualType}.
7676
7777
${err.getCallsiteMarkup()}
7878
`),
7979

8080
[TYPE.actionUnsupportedUrlProtocolError]: err => markup(err, `
81-
The <code>${err.argumentName}</code> argument specifies a URL that uses an unsupported <code>${err.protocol}://</code> protocol. Only HTTP and HTTPS are supported, as well as protocol-relative and relative URLs.
81+
The "${err.argumentName}" argument specifies a URL that uses an unsupported ${err.protocol}:// protocol. Only HTTP and HTTPS are supported, as well as protocol-relative and relative URLs.
8282
8383
${err.getCallsiteMarkup()}
8484
`),
8585

8686
[TYPE.actionStringArgumentError]: err => markup(err, `
87-
The <code>${err.argumentName}</code> argument is expected to be a non-empty string, but it was <code>${err.actualValue}</code>.
87+
The "${err.argumentName}" argument is expected to be a non-empty string, but it was ${err.actualValue}.
8888
8989
${err.getCallsiteMarkup()}
9090
`),
9191

9292
[TYPE.actionStringOrStringArrayArgumentError]: err => markup(err, `
93-
The <code>${err.argumentName}</code> argument is expected to be a non-empty string or a string array, but it was ${err.actualValue}.
93+
The "${err.argumentName}" argument is expected to be a non-empty string or a string array, but it was ${err.actualValue}.
9494
9595
${err.getCallsiteMarkup()}
9696
`),
9797

9898
[TYPE.actionStringArrayElementError]: err => markup(err, `
99-
Elements of the <code>${err.argumentName}</code> argument are expected to be non-empty strings, but the element at index <code>${err.elementIndex}</code> was ${err.actualValue}.
99+
Elements of the "${err.argumentName}" argument are expected to be non-empty strings, but the element at index ${err.elementIndex} was ${err.actualValue}.
100100
101101
${err.getCallsiteMarkup()}
102102
`),
103103

104104
[TYPE.actionIntegerArgumentError]: err => markup(err, `
105-
The <code>${err.argumentName}</code> argument is expected to be an integer, but it was <code>${err.actualValue}</code>.
105+
The "${err.argumentName}" argument is expected to be an integer, but it was ${err.actualValue}.
106106
107107
${err.getCallsiteMarkup()}
108108
`),
109109

110110
[TYPE.actionPositiveIntegerArgumentError]: err => markup(err, `
111-
The <code>${err.argumentName}</code> argument is expected to be a positive integer, but it was <code>${err.actualValue}</code>.
111+
The "${err.argumentName}" argument is expected to be a positive integer, but it was ${err.actualValue}.
112112
113113
${err.getCallsiteMarkup()}
114114
`),
@@ -126,13 +126,13 @@ export default {
126126
`),
127127

128128
[TYPE.actionAdditionalElementNotFoundError]: err => markup(err, `
129-
The specified <code>${err.argumentName}</code> does not match any element in the DOM tree.
129+
The specified "${err.argumentName}" does not match any element in the DOM tree.
130130
131131
${err.getCallsiteMarkup()}
132132
`),
133133

134134
[TYPE.actionAdditionalElementIsInvisibleError]: err => markup(err, `
135-
The element that matches the specified <code>${err.argumentName}</code> is not visible.
135+
The element that matches the specified "${err.argumentName}" is not visible.
136136
137137
${err.getCallsiteMarkup()}
138138
`),
@@ -144,7 +144,7 @@ export default {
144144
`),
145145

146146
[TYPE.actionElementNonContentEditableError]: err => markup(err, `
147-
The element that matches the specified <code>${err.argumentName}</code> is expected to have the contentEditable attribute enabled or the entire document should be in design mode.
147+
The element that matches the specified "${err.argumentName}" is expected to have the contentEditable attribute enabled or the entire document should be in design mode.
148148
149149
${err.getCallsiteMarkup()}
150150
`),
@@ -169,25 +169,25 @@ export default {
169169
`),
170170

171171
[TYPE.actionElementNotTextAreaError]: err => markup(err, `
172-
The action element is expected to be a textarea.
172+
The action element is expected to be a &lt;textarea&gt;.
173173
174174
${err.getCallsiteMarkup()}
175175
`),
176176

177177
[TYPE.actionElementNotIframeError]: err => markup(err, `
178-
The action element is expected to be an iframe.
178+
The action element is expected to be an &lt;iframe&gt.
179179
180180
${err.getCallsiteMarkup()}
181181
`),
182182

183183
[TYPE.actionIncorrectKeysError]: err => markup(err, `
184-
The <code>${err.argumentName}</code> argument contains an incorrect key or key combination.
184+
The "${err.argumentName}" argument contains an incorrect key or key combination.
185185
186186
${err.getCallsiteMarkup()}
187187
`),
188188

189189
[TYPE.actionUnsupportedDeviceTypeError]: err => markup(err, `
190-
The <code>${err.argumentName}</code> argument specifies an unsupported <code>${err.actualValue}</code> device. For a list of supported devices, refer to <a href="http://viewportsizes.com">http://viewportsizes.com</a>
190+
The "${err.argumentName}" argument specifies an unsupported "${err.actualValue}" device. For a list of supported devices, refer to <a href="http://viewportsizes.com">http://viewportsizes.com</a>.
191191
192192
${err.getCallsiteMarkup()}
193193
`),
@@ -217,7 +217,7 @@ export default {
217217
`),
218218

219219
[TYPE.missingAwaitError]: err => markup(err, `
220-
A call to an async function is not awaited. Use the <code>await</code> keyword before actions, assertions or chains of them to ensure that they run in the right sequence.
220+
A call to an async function is not awaited. Use the "await" keyword before actions, assertions or chains of them to ensure that they run in the right sequence.
221221
222222
${err.getCallsiteMarkup()}
223223
`),
@@ -229,27 +229,19 @@ export default {
229229
`),
230230

231231
[TYPE.domNodeClientFunctionResultError]: err => markup(err, `
232-
<code>${err.instantiationCallsiteName}</code> cannot return DOM elements. Use <code>Selector</code> functions for this purpose.
232+
${err.instantiationCallsiteName} cannot return DOM elements. Use Selector functions for this purpose.
233233
234234
${err.getCallsiteMarkup()}
235235
`),
236236

237237
[TYPE.nonDomNodeSelectorResultError]: err => markup(err, `
238-
<code>${err.instantiationCallsiteName}</code> can only return a DOM node, <code>null</code> or <code>undefined</code>. Use ClientFunction to return other values.
238+
${err.instantiationCallsiteName} can only return a DOM node, null or undefined. Use ClientFunction to return other values.
239239
240240
${err.getCallsiteMarkup()}
241241
`),
242242

243243
[TYPE.actionSelectorError]: err => markup(err, `
244-
Action <code>selector</code> error:
245-
246-
${escapeHtml(err.errMsg)}
247-
248-
${err.getCallsiteMarkup()}
249-
`),
250-
251-
[TYPE.actionAdditionalSelectorError]: err => markup(err, `
252-
Action <code>${err.selectorName}</code> error:
244+
Action "${err.selectorName}" argument error:
253245
254246
${escapeHtml(err.errMsg)}
255247

src/errors/test-run/type.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export default {
1818
actionIntegerArgumentError: 'actionIntegerArgumentError',
1919
actionPositiveIntegerArgumentError: 'actionPositiveIntegerArgumentError',
2020
actionSelectorError: 'actionSelectorError',
21-
actionAdditionalSelectorError: 'actionAdditionalSelectorError',
2221
actionUnsupportedUrlProtocolError: 'actionUnsupportedUrlProtocolError',
2322
actionElementNotFoundError: 'actionElementNotFoundError',
2423
actionElementIsInvisibleError: 'actionElementIsInvisibleError',

src/index.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,17 @@ async function createTestCafe (hostname, port1, port2) {
4444
return new TestCafe(hostname, port1, port2);
4545
}
4646

47-
// Plugin testing utils
48-
createTestCafe.pluginTestingUtils = {
47+
// Embedding utils
48+
createTestCafe.embeddingUtils = {
49+
TestRunErrorFormattableAdapter: TestRunErrorFormattableAdapter,
50+
4951
buildReporterPlugin (pluginFactory, outStream) {
5052
var plugin = pluginFactory();
5153

5254
return new ReporterPluginHost(plugin, outStream);
5355
}
5456
};
5557

56-
// Embedding utils
57-
createTestCafe.embeddingUtils = {
58-
TestRunErrorFormattableAdapter: TestRunErrorFormattableAdapter
59-
};
60-
6158
// Common API
6259
Object.keys(commonAPI).forEach(key => createTestCafe[key] = commonAPI[key]);
6360

src/reporter/plugin-host.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default class ReporterPluginHost {
4141
createErrorDecorator () {
4242
return {
4343
'span step-name': str => `"${str}"`,
44-
'span user-agent': str => this.chalk.gray(str),
44+
'span user-agent': str => this.chalk.red(str),
4545

4646
'span subtitle': str => `- ${this.chalk.bold(str)} -\n`,
4747

src/test-run/commands/actions.js

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,23 @@ import {
1212
stringOrStringArrayArgument
1313
} from './validations/argument';
1414

15-
import { ActionSelectorError, ActionAdditionalSelectorError } from '../../errors/test-run';
15+
import { ActionSelectorError } from '../../errors/test-run';
1616
import { APIError } from '../../errors/runtime';
1717

1818

1919
// Initializers
20-
function createSelectorInitializer (createError) {
21-
return (name, val) => {
22-
try {
23-
var factory = new SelectorFactory(val, null, { instantiation: 'Selector' });
24-
25-
return factory.getCommand([], { visibilityCheck: true });
26-
}
27-
catch (err) {
28-
var msg = err.constructor === APIError ? err.rawMessage : err.message;
29-
30-
throw createError(name, msg);
31-
}
32-
};
33-
}
20+
function initSelector (name, val) {
21+
try {
22+
var factory = new SelectorFactory(val, null, { instantiation: 'Selector' });
23+
24+
return factory.getCommand([], { visibilityCheck: true });
25+
}
26+
catch (err) {
27+
var msg = err.constructor === APIError ? err.rawMessage : err.message;
3428

35-
var initSelector = createSelectorInitializer((name, msg) => new ActionSelectorError(msg));
36-
var initAdditionalSelector = createSelectorInitializer((name, msg) => new ActionAdditionalSelectorError(name, msg));
29+
throw new ActionSelectorError(name, msg);
30+
}
31+
}
3732

3833
function initClickOptions (name, val) {
3934
return new ClickOptions(val, true);
@@ -184,7 +179,7 @@ export class DragToElementCommand extends Assignable {
184179
_getAssignableProperties () {
185180
return [
186181
{ name: 'selector', init: initSelector, required: true },
187-
{ name: 'destinationSelector', init: initAdditionalSelector, required: true },
182+
{ name: 'destinationSelector', init: initSelector, required: true },
188183
{ name: 'options', type: actionOptions, init: initMouseOptions, required: true }
189184
];
190185
}
@@ -224,8 +219,8 @@ export class SelectEditableContentCommand extends Assignable {
224219

225220
_getAssignableProperties () {
226221
return [
227-
{ name: 'startSelector', init: initAdditionalSelector, required: true },
228-
{ name: 'endSelector', init: initAdditionalSelector }
222+
{ name: 'startSelector', init: initSelector, required: true },
223+
{ name: 'endSelector', init: initSelector }
229224
];
230225
}
231226
}

test/functional/fixtures/api/es-next/click/test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('[API] t.click()', function () {
2626
only: 'chrome'
2727
})
2828
.catch(function (errs) {
29-
expect(errs[0]).to.contains('The offsetX option is expected to be a positive integer, but it was -3.');
29+
expect(errs[0]).to.contains('The "offsetX" option is expected to be a positive integer, but it was -3.');
3030
expect(errs[0]).to.contains(
3131
' 11 |test(\'Incorrect action selector\', async t => {' +
3232
' 12 | await t.click(123);' +
@@ -50,9 +50,9 @@ describe('[API] t.click()', function () {
5050
})
5151
.catch(function (errs) {
5252
expect(errs[0]).to.contains(
53-
'Action selector error: Selector is expected to be initialized with a ' +
53+
'Action "selector" argument error: Selector is expected to be initialized with a ' +
5454
'function, CSS selector string, another Selector, node snapshot or a Promise returned ' +
55-
'by a Selector, but "number" was passed.'
55+
'by a Selector, but number was passed.'
5656
);
5757
expect(errs[0]).to.contains(
5858
'7 | .page `http://localhost:3000/fixtures/api/es-next/click/pages/index.html`;' +

0 commit comments

Comments
 (0)