/
role.ts
153 lines (123 loc) · 4.6 KB
/
role.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { EventEmitter } from 'events';
import RolePhase from './phase';
import { StateSnapshot } from 'testcafe-hammerhead';
import roleMarker from './marker-symbol';
import { nanoid } from 'nanoid';
import TestRun from '../test-run';
import TestCafeErrorList from '../errors/error-list';
export interface RedirectUrl {
[testId: string]: string;
}
export default class Role extends EventEmitter {
public id: string;
public phase: RolePhase;
public loginUrl: string | null;
public redirectUrl: RedirectUrl | string | null;
public _initFn: Function | null;
public opts: RoleOptions;
public initErr: null | Error | TestCafeErrorList;
public stateSnapshot: StateSnapshot;
private [roleMarker]: boolean;
public constructor (loginUrl: string | null, initFn: Function | null, options = {}) {
super();
this[roleMarker] = true;
this.id = nanoid(7);
this.phase = loginUrl ? RolePhase.uninitialized : RolePhase.initialized;
this.loginUrl = loginUrl;
this._initFn = initFn;
this.opts = options;
this.redirectUrl = null;
this.stateSnapshot = StateSnapshot.empty();
this.initErr = null;
}
private async _storeStateSnapshot (testRun: TestRun): Promise<void> {
if (this.initErr)
return;
this.stateSnapshot = await testRun.getStateSnapshot();
await testRun?.compilerService?.updateRoleProperty({
roleId: this.id,
name: 'stateSnapshot',
value: this.stateSnapshot,
});
}
private _wrapTestFn (testRun: TestRun): void {
this._initFn = () => {
return testRun.compilerService?.executeRoleInitFn({
testRunId: testRun.id,
roleId: this.id,
});
};
}
private async _setInitError (err: Error, testRun: TestRun): Promise<void> {
this.initErr = err;
await testRun?.compilerService?.updateRoleProperty({
roleId: this.id,
name: 'initErr',
value: this.initErr,
});
}
private async _executeInitFn (testRun: TestRun): Promise<void> {
if (this.initErr)
return;
try {
if (testRun.compilerService)
this._wrapTestFn(testRun);
let fn = (): Promise<void> => (this._initFn as Function)(testRun);
fn = testRun.decoratePreventEmitActionEvents(fn, { prevent: false });
fn = testRun.decorateDisableDebugBreakpoints(fn, { disable: false });
await fn();
}
catch (err) {
await this._setInitError(err, testRun);
}
}
private async _switchToCleanRun (testRun: TestRun): Promise<void> {
try {
await testRun.switchToCleanRun(this.loginUrl as string);
}
catch (err) {
await this._setInitError(err, testRun);
}
}
public async initialize (testRun: TestRun): Promise<void> {
this.phase = RolePhase.pendingInitialization;
await this._switchToCleanRun(testRun);
await this._executeInitFn(testRun);
await this._storeStateSnapshot(testRun);
if (this.opts.preserveUrl)
await this.setCurrentUrlAsRedirectUrl(testRun);
this.phase = RolePhase.initialized;
await testRun.compilerService?.updateRoleProperty({
roleId: this.id,
name: 'phase',
value: this.phase,
});
this.emit('initialized');
}
public async setCurrentUrlAsRedirectUrl (testRun: TestRun): Promise<void> {
const currentUrl = await testRun.getCurrentUrl();
if (this.opts.preserveUrl)
this.redirectUrl = currentUrl;
else {
this.redirectUrl = this.redirectUrl || {};
(this.redirectUrl as RedirectUrl)[testRun.test.id] = currentUrl;
}
await testRun.compilerService?.updateRoleProperty({
roleId: this.id,
name: 'redirectUrl',
value: this.redirectUrl,
});
}
public static from (init: unknown): Role | null {
if (!init)
return null;
const serializedRole = init as Role;
const role = new Role(serializedRole.loginUrl, serializedRole._initFn, serializedRole.opts);
role.id = serializedRole.id;
role.phase = serializedRole.phase;
role.redirectUrl = serializedRole.redirectUrl;
role.stateSnapshot = serializedRole.stateSnapshot;
role.initErr = serializedRole.initErr;
return role;
}
}