forked from DevExpress/testcafe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
command-formatter.ts
119 lines (92 loc) · 4.14 KB
/
command-formatter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { ExecuteSelectorCommand, ExecuteClientFunctionCommand } from '../../test-run/commands/observation';
import { NavigateToCommand, SetNativeDialogHandlerCommand, UseRoleCommand } from '../../test-run/commands/actions';
import { createReplicator, SelectorNodeTransform } from '../../client-functions/replicator';
import { Command, FormattedCommand, SelectorInfo } from './interfaces';
import { ActionOptions } from '../../test-run/commands/options';
import diff from '../../utils/diff';
export class CommandFormatter {
private _elements: HTMLElement[] = [];
private readonly _command: Command;
private readonly _result: unknown;
public constructor (command: Command, result: unknown) {
this._command = command;
this._result = result;
}
public format (): FormattedCommand {
const formattedCommand: FormattedCommand = { type: this._command.type };
if (this._command instanceof ExecuteSelectorCommand)
formattedCommand.selector = this._prepareSelector(this._command, 'selector');
else if (this._command instanceof ExecuteClientFunctionCommand)
formattedCommand.clientFn = this._prepareClientFunction(this._command);
else if (this._command instanceof UseRoleCommand)
formattedCommand.role = this._prepareRole(this._command);
else if (this._command instanceof NavigateToCommand)
formattedCommand.url = this._prepareUrl(this._command);
else if (this._command instanceof SetNativeDialogHandlerCommand)
formattedCommand.dialogHandler = this._prepareDialogHandler(this._command);
else
this._assignProperties(this._command, formattedCommand);
return formattedCommand;
}
private _getElementByPropertyName (propertyName: string): HTMLElement {
this._ensureSelectorElements();
switch (propertyName) {
case 'selector':
case 'startSelector':
return this._elements[0];
case 'endSelector':
case 'destinationSelector':
return this._elements[1];
}
return this._elements[0];
}
private _prepareSelector (command: Command, propertyName: string): SelectorInfo {
const selectorChain = command.apiFnChain as string[];
const expression = selectorChain.join('');
let element = null;
if (this._result)
element = this._getElementByPropertyName(propertyName);
if (element)
return { expression, element };
return { expression };
}
private _prepareClientFunction (command: Command): object {
return {
code: command.fnCode,
args: command.args[0]
};
}
private _prepareDialogHandler (command: Command): object {
return this._prepareClientFunction(command.dialogHandler);
}
private _prepareRole (command: Command): object {
const { loginPage, opts, phase } = command.role;
return { loginPage, options: opts, phase };
}
private _prepareUrl (command: Command): string {
return command.url;
}
private _assignProperties (command: Command, formattedCommand: FormattedCommand): void {
if (!this._command._getAssignableProperties)
return;
const sourceProperties = this._command._getAssignableProperties().map(prop => prop.name);
sourceProperties.forEach((key: string) => {
const prop = this._command[key];
if (prop instanceof ExecuteSelectorCommand)
formattedCommand[key] = this._prepareSelector(prop, key);
else if (prop instanceof ActionOptions) {
// @ts-ignore
const props = new prop.constructor();
formattedCommand[key] = diff(props, prop);
}
else
formattedCommand[key] = prop;
});
}
private _ensureSelectorElements (): void {
if (!this._result || this._elements.length)
return;
const decoded = createReplicator(new SelectorNodeTransform()).decode(this._result);
this._elements = Array.isArray(decoded) ? decoded : [decoded];
}
}