@zohodesk/testinglibrary 0.0.65-n20-experimental → 0.0.66-n20-experimental
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/common/data-generator/steps/DataGenerator.spec.js +8 -4
- package/build/common/data-generator/steps/DataGeneratorStepsHelper.js +2 -2
- package/build/core/dataGenerator/DataGenerator.js +9 -4
- package/build/core/dataGenerator/authenticator/Authenticator.js +35 -0
- package/build/core/dataGenerator/authenticator/CookieAuthenticator.js +41 -0
- package/build/core/dataGenerator/authenticator/JWTauthenticator.js +71 -0
- package/build/core/dataGenerator/authenticator/OAuthAuthenticator.js +31 -0
- package/build/core/dataGenerator/authenticator/OrgOAuthAuthenticator.js +29 -0
- package/build/core/playwright/builtInFixtures/context.js +3 -36
- package/build/core/playwright/readConfigFile.js +1 -7
- package/build/core/playwright/setup/custom-reporter.js +1 -87
- package/build/test/core/dataGenerator/authenticator/__test__/Authenticator.test.js +89 -0
- package/build/test/core/dataGenerator/authenticator/__test__/JWTauthenticator.test.js +134 -0
- package/build/test/core/dataGenerator/authenticator/__test__/OAuthAuthenticator.test.js +46 -0
- package/build/test/core/dataGenerator/authenticator/__test__/OrgOAuthAuthenticator.test.js +46 -0
- package/build/test/core/dataGenerator/authenticator/__tests__/JWTauthenticator.test.js +165 -0
- package/jest.config.js +1 -1
- package/npm-shrinkwrap.json +4 -3
- package/package.json +2 -2
- package/unit_reports/unit-report.html +1 -1
- package/build/core/playwright/helpers/logCollector.js +0 -153
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _JWTauthenticator = _interopRequireDefault(require("../../../../../../src/core/dataGenerator/authenticator/JWTauthenticator"));
|
|
5
|
+
describe('JWTauthenticator', () => {
|
|
6
|
+
let fetchMock;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
fetchMock = jest.fn();
|
|
9
|
+
global.fetch = fetchMock;
|
|
10
|
+
process.env.DG_JWT_AUTH_URL = 'https://jwt-auth.example.com';
|
|
11
|
+
process.env.DG_JWT_TOKEN_URL = 'https://token.example.com/{ZSOID}/oauth';
|
|
12
|
+
process.env.DG_DOMAIN_URL = 'https://domain.example.com';
|
|
13
|
+
process.env.DG_JWT_AUTHENTICATOR_API = 'https://authenticator.example.com/jwtToken';
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
delete global.fetch;
|
|
17
|
+
delete process.env.DG_JWT_AUTH_URL;
|
|
18
|
+
delete process.env.DG_JWT_TOKEN_URL;
|
|
19
|
+
delete process.env.DG_DOMAIN_URL;
|
|
20
|
+
delete process.env.DG_JWT_AUTHENTICATOR_API;
|
|
21
|
+
});
|
|
22
|
+
it('should return unchanged payload when jwt config is missing', async () => {
|
|
23
|
+
const jwtAuthenticator = new _JWTauthenticator.default();
|
|
24
|
+
const apiPayload = {
|
|
25
|
+
account: {}
|
|
26
|
+
};
|
|
27
|
+
const actorInfo = {
|
|
28
|
+
email: 'user@example.com',
|
|
29
|
+
'data-generator': {
|
|
30
|
+
account: {}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const result = await jwtAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
34
|
+
expect(result).toEqual(apiPayload);
|
|
35
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
it('should fetch jwt access token and attach it to payload', async () => {
|
|
38
|
+
fetchMock.mockResolvedValue({
|
|
39
|
+
ok: true,
|
|
40
|
+
json: async () => ({
|
|
41
|
+
access_token: 'access-token-123'
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
const jwtAuthenticator = new _JWTauthenticator.default();
|
|
45
|
+
const apiPayload = {
|
|
46
|
+
account: {}
|
|
47
|
+
};
|
|
48
|
+
const actorInfo = {
|
|
49
|
+
email: 'user.one@example.com',
|
|
50
|
+
'data-generator': {
|
|
51
|
+
account: {
|
|
52
|
+
jwt: {
|
|
53
|
+
jwt_secret: 'jwt-secret',
|
|
54
|
+
response_type: 'token',
|
|
55
|
+
client_id: '12345.client-id'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const result = await jwtAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
61
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
62
|
+
expect(fetchMock).toHaveBeenCalledWith('https://authenticator.example.com/jwtToken', expect.objectContaining({
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/json'
|
|
66
|
+
}
|
|
67
|
+
}));
|
|
68
|
+
const requestBody = JSON.parse(fetchMock.mock.calls[0][1].body);
|
|
69
|
+
expect(requestBody).toEqual(expect.objectContaining({
|
|
70
|
+
user_token: encodeURIComponent('user.one@example.com'),
|
|
71
|
+
jwt_secret: 'jwt-secret',
|
|
72
|
+
jwt_auth_url: 'https://jwt-auth.example.com',
|
|
73
|
+
response_type: 'token',
|
|
74
|
+
client_id: '12345.client-id',
|
|
75
|
+
token_url: 'https://token.example.com/12345/oauth',
|
|
76
|
+
domain_url: 'https://domain.example.com'
|
|
77
|
+
}));
|
|
78
|
+
expect(result.account.jwt).toEqual(expect.objectContaining({
|
|
79
|
+
jwt_secret: 'jwt-secret',
|
|
80
|
+
response_type: 'token',
|
|
81
|
+
client_id: '12345.client-id',
|
|
82
|
+
access_token: 'access-token-123'
|
|
83
|
+
}));
|
|
84
|
+
});
|
|
85
|
+
it('should throw a descriptive error when authenticator API returns non-ok response', async () => {
|
|
86
|
+
fetchMock.mockResolvedValue({
|
|
87
|
+
ok: false,
|
|
88
|
+
status: 500,
|
|
89
|
+
text: async () => 'internal error'
|
|
90
|
+
});
|
|
91
|
+
const jwtAuthenticator = new _JWTauthenticator.default();
|
|
92
|
+
const apiPayload = {
|
|
93
|
+
account: {}
|
|
94
|
+
};
|
|
95
|
+
const actorInfo = {
|
|
96
|
+
email: 'user@example.com',
|
|
97
|
+
'data-generator': {
|
|
98
|
+
account: {
|
|
99
|
+
jwt: {
|
|
100
|
+
jwt_secret: 'jwt-secret',
|
|
101
|
+
response_type: 'token',
|
|
102
|
+
client_id: '12345.client-id'
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
await expect(jwtAuthenticator.constructPayload(apiPayload, actorInfo)).rejects.toThrow('JWT authenticator error! status: 500, body: internal error');
|
|
108
|
+
});
|
|
109
|
+
it('should throw when authenticator response has no access_token', async () => {
|
|
110
|
+
fetchMock.mockResolvedValue({
|
|
111
|
+
ok: true,
|
|
112
|
+
json: async () => ({
|
|
113
|
+
token_type: 'Bearer'
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
const jwtAuthenticator = new _JWTauthenticator.default();
|
|
117
|
+
const apiPayload = {
|
|
118
|
+
account: {}
|
|
119
|
+
};
|
|
120
|
+
const actorInfo = {
|
|
121
|
+
email: 'user@example.com',
|
|
122
|
+
'data-generator': {
|
|
123
|
+
account: {
|
|
124
|
+
jwt: {
|
|
125
|
+
jwt_secret: 'jwt-secret',
|
|
126
|
+
response_type: 'token',
|
|
127
|
+
client_id: '12345.client-id'
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
await expect(jwtAuthenticator.constructPayload(apiPayload, actorInfo)).rejects.toThrow('JWT authenticator did not return access_token');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _OAuthAuthenticator = _interopRequireDefault(require("../../../../../../src/core/dataGenerator/authenticator/OAuthAuthenticator"));
|
|
5
|
+
describe('OAuthAuthenticator', () => {
|
|
6
|
+
it('should merge oauth2 from actor info into payload account', async () => {
|
|
7
|
+
const oauthAuthenticator = new _OAuthAuthenticator.default();
|
|
8
|
+
const apiPayload = {
|
|
9
|
+
account: {
|
|
10
|
+
oauth2: {
|
|
11
|
+
existing_key: 'existing-value'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const actorInfo = {
|
|
16
|
+
'data-generator': {
|
|
17
|
+
account: {
|
|
18
|
+
oauth2: {
|
|
19
|
+
client_id: 'new-client',
|
|
20
|
+
scope: 'tickets.read'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const result = await oauthAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
26
|
+
expect(result.account.oauth2).toEqual({
|
|
27
|
+
existing_key: 'existing-value',
|
|
28
|
+
client_id: 'new-client',
|
|
29
|
+
scope: 'tickets.read'
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it('should initialize account when missing and keep payload unchanged if oauth2 is absent', async () => {
|
|
33
|
+
const oauthAuthenticator = new _OAuthAuthenticator.default();
|
|
34
|
+
const apiPayload = {};
|
|
35
|
+
const actorInfo = {
|
|
36
|
+
'data-generator': {
|
|
37
|
+
account: {}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const result = await oauthAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
account: {}
|
|
43
|
+
});
|
|
44
|
+
expect(result.account.oauth2).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _OrgOAuthAuthenticator = _interopRequireDefault(require("../../../../../../src/core/dataGenerator/authenticator/OrgOAuthAuthenticator"));
|
|
5
|
+
describe('OrgOAuthAuthenticator', () => {
|
|
6
|
+
it('should merge org_oauth from actor info into payload account', async () => {
|
|
7
|
+
const orgOAuthAuthenticator = new _OrgOAuthAuthenticator.default();
|
|
8
|
+
const apiPayload = {
|
|
9
|
+
account: {
|
|
10
|
+
org_oauth: {
|
|
11
|
+
existing_key: 'existing-value'
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const actorInfo = {
|
|
16
|
+
'data-generator': {
|
|
17
|
+
account: {
|
|
18
|
+
org_oauth: {
|
|
19
|
+
org_id: 'org-1001',
|
|
20
|
+
region: 'us'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const result = await orgOAuthAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
26
|
+
expect(result.account.org_oauth).toEqual({
|
|
27
|
+
existing_key: 'existing-value',
|
|
28
|
+
org_id: 'org-1001',
|
|
29
|
+
region: 'us'
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it('should initialize account when missing and keep payload unchanged if org_oauth is absent', async () => {
|
|
33
|
+
const orgOAuthAuthenticator = new _OrgOAuthAuthenticator.default();
|
|
34
|
+
const apiPayload = {};
|
|
35
|
+
const actorInfo = {
|
|
36
|
+
'data-generator': {
|
|
37
|
+
account: {}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const result = await orgOAuthAuthenticator.constructPayload(apiPayload, actorInfo);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
account: {}
|
|
43
|
+
});
|
|
44
|
+
expect(result.account.org_oauth).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _JWTauthenticator = _interopRequireDefault(require("../../../../../core/dataGenerator/authenticator/JWTauthenticator.js"));
|
|
5
|
+
const MOCK_ACCESS_TOKEN = '1026812030.abc123.def456';
|
|
6
|
+
const makeActorInfo = (overrides = {}) => ({
|
|
7
|
+
email: 'anitha.m+uatagent@zohotest.com',
|
|
8
|
+
'data-generator': {
|
|
9
|
+
account: {
|
|
10
|
+
authentications: ['jwt-auth'],
|
|
11
|
+
'jwt-oauth': {
|
|
12
|
+
jwt_secret: 'PZkhUzx0ruJQNU4QRagh0u13uuKk9s0m5EU1pUbD',
|
|
13
|
+
response_type: 'remote_token',
|
|
14
|
+
client_id: '1026812030.WKK443JMM12S4ZVR23C3HUK66PFUSG',
|
|
15
|
+
token_url: 'https://accounts-portal.csez.zohocorpin.com/clientoauth/v2/1026812030/remote/auth',
|
|
16
|
+
domain_url: 'https://zdesk-devops08.csez.zohocorpin.com:31000'
|
|
17
|
+
},
|
|
18
|
+
...overrides
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const makeApiPayload = (overrides = {}) => ({
|
|
23
|
+
scenario_name: 'verify the Department page is loaded',
|
|
24
|
+
account: {
|
|
25
|
+
storeVariables: {
|
|
26
|
+
orgId: '20408511'
|
|
27
|
+
},
|
|
28
|
+
authentications: ['jwt-auth']
|
|
29
|
+
},
|
|
30
|
+
...overrides
|
|
31
|
+
});
|
|
32
|
+
const mockFetchSuccess = () => {
|
|
33
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
34
|
+
ok: true,
|
|
35
|
+
json: jest.fn().mockResolvedValue({
|
|
36
|
+
access_token: MOCK_ACCESS_TOKEN
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
describe('JWTauthenticator.constructPayload', () => {
|
|
41
|
+
let authenticator;
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
authenticator = new _JWTauthenticator.default();
|
|
44
|
+
process.env.DG_JWT_AUTHENTICATOR_API = 'https://authenticator.zdesk.csez.zohocorpin.com/jwtToken';
|
|
45
|
+
process.env.DG_JWT_AUTH_URL = 'https://jwt.zdesk.csez.zohocorpin.com/JWTAuth';
|
|
46
|
+
delete process.env.DG_JWT_TOKEN_URL;
|
|
47
|
+
delete process.env.DG_DOMAIN_URL;
|
|
48
|
+
jest.clearAllMocks();
|
|
49
|
+
});
|
|
50
|
+
describe('no-op cases', () => {
|
|
51
|
+
it('returns apiPayload unchanged when jwt-oauth config is absent in actorInfo', async () => {
|
|
52
|
+
const actorInfo = {
|
|
53
|
+
email: 'anitha.m+uatagent@zohotest.com',
|
|
54
|
+
'data-generator': {
|
|
55
|
+
account: {
|
|
56
|
+
authentications: ['jwt-auth']
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const apiPayload = makeApiPayload();
|
|
61
|
+
const result = await authenticator.constructPayload(apiPayload, actorInfo);
|
|
62
|
+
expect(result).toBe(apiPayload);
|
|
63
|
+
expect(result.account.authHeaders).toBeUndefined();
|
|
64
|
+
});
|
|
65
|
+
it('returns apiPayload unchanged when actorInfo has no data-generator', async () => {
|
|
66
|
+
const apiPayload = makeApiPayload();
|
|
67
|
+
const result = await authenticator.constructPayload(apiPayload, {});
|
|
68
|
+
expect(result).toBe(apiPayload);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('successful token fetch', () => {
|
|
72
|
+
it('sets authHeaders.Authorization with Zoho-oauthtoken prefix', async () => {
|
|
73
|
+
mockFetchSuccess();
|
|
74
|
+
const result = await authenticator.constructPayload(makeApiPayload(), makeActorInfo());
|
|
75
|
+
expect(result.account.authHeaders.Authorization).toBe(`Zoho-oauthtoken ${MOCK_ACCESS_TOKEN}`);
|
|
76
|
+
});
|
|
77
|
+
it('URL-encodes email with + and @ characters as user_token', async () => {
|
|
78
|
+
mockFetchSuccess();
|
|
79
|
+
await authenticator.constructPayload(makeApiPayload(), makeActorInfo());
|
|
80
|
+
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
81
|
+
expect(body.user_token).toBe('anitha.m%2Buatagent%40zohotest.com');
|
|
82
|
+
});
|
|
83
|
+
it('posts to DG_JWT_AUTHENTICATOR_API with correct payload fields', async () => {
|
|
84
|
+
mockFetchSuccess();
|
|
85
|
+
await authenticator.constructPayload(makeApiPayload(), makeActorInfo());
|
|
86
|
+
const [url, options] = global.fetch.mock.calls[0];
|
|
87
|
+
const body = JSON.parse(options.body);
|
|
88
|
+
expect(url).toBe(process.env.DG_JWT_AUTHENTICATOR_API);
|
|
89
|
+
expect(options.method).toBe('POST');
|
|
90
|
+
expect(options.headers['Content-Type']).toBe('application/json');
|
|
91
|
+
expect(body.jwt_secret).toBe('PZkhUzx0ruJQNU4QRagh0u13uuKk9s0m5EU1pUbD');
|
|
92
|
+
expect(body.response_type).toBe('remote_token');
|
|
93
|
+
expect(body.client_id).toBe('1026812030.WKK443JMM12S4ZVR23C3HUK66PFUSG');
|
|
94
|
+
expect(body.jwt_auth_url).toBe(process.env.DG_JWT_AUTH_URL);
|
|
95
|
+
expect(body.token_url).toBe('https://accounts-portal.csez.zohocorpin.com/clientoauth/v2/1026812030/remote/auth');
|
|
96
|
+
expect(body.domain_url).toBe('https://zdesk-devops08.csez.zohocorpin.com:31000');
|
|
97
|
+
});
|
|
98
|
+
it('does not overwrite existing authHeaders fields other than Authorization', async () => {
|
|
99
|
+
mockFetchSuccess();
|
|
100
|
+
const apiPayload = makeApiPayload();
|
|
101
|
+
apiPayload.account.authHeaders = {
|
|
102
|
+
'X-Custom-Header': 'custom-value'
|
|
103
|
+
};
|
|
104
|
+
const result = await authenticator.constructPayload(apiPayload, makeActorInfo());
|
|
105
|
+
expect(result.account.authHeaders['X-Custom-Header']).toBe('custom-value');
|
|
106
|
+
expect(result.account.authHeaders.Authorization).toBe(`Zoho-oauthtoken ${MOCK_ACCESS_TOKEN}`);
|
|
107
|
+
});
|
|
108
|
+
it('resolves token_url from DG_JWT_TOKEN_URL env when not in config', async () => {
|
|
109
|
+
mockFetchSuccess();
|
|
110
|
+
process.env.DG_JWT_TOKEN_URL = 'https://accounts-portal.csez.zohocorpin.com/clientoauth/v2/{ZSOID}/remote/auth';
|
|
111
|
+
const actorInfo = makeActorInfo({
|
|
112
|
+
'jwt-oauth': {
|
|
113
|
+
...makeActorInfo()['data-generator'].account['jwt-oauth'],
|
|
114
|
+
token_url: undefined
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
await authenticator.constructPayload(makeApiPayload(), actorInfo);
|
|
118
|
+
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
119
|
+
expect(body.token_url).toBe('https://accounts-portal.csez.zohocorpin.com/clientoauth/v2/1026812030/remote/auth');
|
|
120
|
+
});
|
|
121
|
+
it('resolves domain_url from DG_DOMAIN_URL env when not in config', async () => {
|
|
122
|
+
mockFetchSuccess();
|
|
123
|
+
process.env.DG_DOMAIN_URL = 'https://zdesk-env-domain.csez.zohocorpin.com:31000';
|
|
124
|
+
const jwtOauth = {
|
|
125
|
+
...makeActorInfo()['data-generator'].account['jwt-oauth'],
|
|
126
|
+
domain_url: undefined
|
|
127
|
+
};
|
|
128
|
+
const actorInfo = {
|
|
129
|
+
...makeActorInfo(),
|
|
130
|
+
'data-generator': {
|
|
131
|
+
account: {
|
|
132
|
+
authentications: ['jwt-auth'],
|
|
133
|
+
'jwt-oauth': jwtOauth
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
await authenticator.constructPayload(makeApiPayload(), actorInfo);
|
|
138
|
+
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
139
|
+
expect(body.domain_url).toBe('https://zdesk-env-domain.csez.zohocorpin.com:31000');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('authenticator service errors', () => {
|
|
143
|
+
it('throws when authenticator responds with non-ok status', async () => {
|
|
144
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
145
|
+
ok: false,
|
|
146
|
+
status: 401,
|
|
147
|
+
text: jest.fn().mockResolvedValue('Unauthorized')
|
|
148
|
+
});
|
|
149
|
+
await expect(authenticator.constructPayload(makeApiPayload(), makeActorInfo())).rejects.toThrow('status: 401');
|
|
150
|
+
});
|
|
151
|
+
it('throws when authenticator response has no access_token', async () => {
|
|
152
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
153
|
+
ok: true,
|
|
154
|
+
json: jest.fn().mockResolvedValue({
|
|
155
|
+
error: 'invalid_grant'
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
await expect(authenticator.constructPayload(makeApiPayload(), makeActorInfo())).rejects.toThrow('access_token');
|
|
159
|
+
});
|
|
160
|
+
it('throws when fetch fails due to network error', async () => {
|
|
161
|
+
global.fetch = jest.fn().mockRejectedValue(new Error('ECONNREFUSED'));
|
|
162
|
+
await expect(authenticator.constructPayload(makeApiPayload(), makeActorInfo())).rejects.toThrow('ECONNREFUSED');
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
package/jest.config.js
CHANGED
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/testinglibrary",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.66-n20-experimental",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@zohodesk/testinglibrary",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.66-n20-experimental",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@babel/code-frame": "7.27.1",
|
|
14
14
|
"@babel/preset-react": "7.28.5",
|
|
15
|
-
"@babel/runtime": "7.28.4",
|
|
16
15
|
"@playwright/test": "1.56.1",
|
|
17
16
|
"@reportportal/agent-js-playwright": "5.2.2",
|
|
18
17
|
"@testing-library/jest-dom": "6.9.1",
|
|
@@ -37,6 +36,7 @@
|
|
|
37
36
|
"@babel/node": "7.28.0",
|
|
38
37
|
"@babel/plugin-transform-runtime": "7.28.3",
|
|
39
38
|
"@babel/preset-env": "7.28.3",
|
|
39
|
+
"@babel/runtime": "7.28.4",
|
|
40
40
|
"commander": "14.0.2",
|
|
41
41
|
"jest-html-reporter": "4.3.0"
|
|
42
42
|
},
|
|
@@ -1958,6 +1958,7 @@
|
|
|
1958
1958
|
"version": "7.28.4",
|
|
1959
1959
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
|
1960
1960
|
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
|
1961
|
+
"dev": true,
|
|
1961
1962
|
"license": "MIT",
|
|
1962
1963
|
"engines": {
|
|
1963
1964
|
"node": ">=6.9.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/testinglibrary",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.66-n20-experimental",
|
|
4
4
|
"main": "./build/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"postinstall": "node bin/postinstall.js",
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@babel/code-frame": "7.27.1",
|
|
25
25
|
"@babel/preset-react": "7.28.5",
|
|
26
|
-
"@babel/runtime": "7.28.4",
|
|
27
26
|
"@playwright/test": "1.56.1",
|
|
28
27
|
"@reportportal/agent-js-playwright": "5.2.2",
|
|
29
28
|
"@testing-library/jest-dom": "6.9.1",
|
|
@@ -53,6 +52,7 @@
|
|
|
53
52
|
"@babel/node": "7.28.0",
|
|
54
53
|
"@babel/plugin-transform-runtime": "7.28.3",
|
|
55
54
|
"@babel/preset-env": "7.28.3",
|
|
55
|
+
"@babel/runtime": "7.28.4",
|
|
56
56
|
"commander": "14.0.2",
|
|
57
57
|
"jest-html-reporter": "4.3.0"
|
|
58
58
|
}
|
|
@@ -274,4 +274,4 @@ header {
|
|
|
274
274
|
font-size: 1rem;
|
|
275
275
|
padding: 0 0.5rem;
|
|
276
276
|
}
|
|
277
|
-
</style></head><body><main class="jesthtml-content"><header><h1 id="title">Unit Report</h1></header><section id="metadata-container"><div id="timestamp">Started: 2026-05-28 21:12:55</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (14)</div><div class="summary-passed ">14 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (61)</div><div class="summary-passed ">61 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></section><details id="suite-1" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/configPathResolver.test.js</div><div class="suite-time">0.626s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">getConfigPath</div><div class="test-title">should return config path when properties file exists and has mapping</div><div class="test-status">passed</div><div class="test-duration">0.004s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getConfigPath</div><div class="test-title">should log info and use default mapping if file does not exist</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getConfigPath</div><div class="test-title">should log failure if config mapping not found for stage</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div></div></details><details id="suite-2" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/buildInFixtures/__tests__/executionContext.test.js</div><div class="suite-time">0.602s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">executionContext</div><div class="test-title">should pass actorInfo with details from getCustomAccountDetails to use</div><div class="test-status">passed</div><div class="test-duration">0.004s</div></div></div></div></details><details id="suite-3" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/getUsers_ListOfActors.test.js</div><div class="suite-time">0.584s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">getListOfActors</div><div class="test-title">throws an error when config file cannot be loaded</div><div class="test-status">passed</div><div class="test-duration">0.018s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getListOfActors</div><div class="test-title">throws an error when beta feature config does not exist</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getListOfActors</div><div class="test-title">loads main configuration when betaFeature is not provided and main config exists</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getListOfActors</div><div class="test-title">falls back to default configuration if main config file does not exist</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getListOfActors</div><div class="test-title">loads beta feature configuration when betaFeature is provided</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-4" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/configFileNameProvider.test.js</div><div class="suite-time">0.568s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">getUATFileName</div><div class="test-title">should return pipeline-matched config path when file exists</div><div class="test-status">passed</div><div class="test-duration">0.003s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getUATFileName</div><div class="test-title">should use default stage and mode when not provided</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getUATFileName</div><div class="test-title">should return the default config files for pipeline matched files not exists</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getEnvConfigFilePath</div><div class="test-title">should return conf file path when file exists</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getEnvConfigFilePath</div><div class="test-title">should return default path when file does not exist</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-5" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/examples/src/__tests__/App.test.js</div><div class="suite-time">0.087s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">example functions</div><div class="test-title">add function adds two numbers correctly</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">example functions</div><div class="test-title">greet function greets a person with their name</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-6" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/__tests__/tagProcessor.test.js</div><div class="suite-time">0.092s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should return tagArgs if no edition is provided</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle a single edition with <= operator</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle a single edition with >= operator</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle a single edition with < operator</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle a single edition with > operator</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle a single edition with no operator</div><div class="test-status">passed</div><div class="test-duration">0.002s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should log a message if edition is not found</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should handle multiple editions</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">TagProcessor</div><div class="test-title">should build tags correctly when tags are empty</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-7" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/additionalProfiles.test.js</div><div class="suite-time">0.564s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">additionalProfiles</div><div class="test-title">should return empty object when no additional profile tags are present</div><div class="test-status">passed</div><div class="test-duration">0.002s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">additionalProfiles</div><div class="test-title">should return additional profile actors when additional profile tags and editionInfo are present</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">additionalProfiles</div><div class="test-title">should return additional profile actors when all actor details are present</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-8" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/configuration/__tests__/Configuration.test.js</div><div class="suite-time">0.492s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">Configuration Class</div><div class="test-title">should add new key-value pair to the configuration</div><div class="test-status">passed</div><div class="test-duration">0.006s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">Configuration Class</div><div class="test-title">should combine configurations correctly using addAll</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">Configuration Class</div><div class="test-title">should return correct value for a given key</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-9" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/customFixturesHelper.test.js</div><div class="suite-time">0.56s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">getCustomAccountDetails</div><div class="test-title">returns selected user when any tag info is present</div><div class="test-status">passed</div><div class="test-duration">0.003s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getCustomAccountDetails</div><div class="test-title">logs and returns undefined if getCustomAccountDetails function throws</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">getCustomAccountDetails</div><div class="test-title">returns default actor when no tag info is not provided</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div></div></details><details id="suite-10" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/buildInFixtures/__tests__/caseTimeout.test.js</div><div class="suite-time">0.22s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns null when no timeout tag is present</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns null when tags is not an array</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">parses @timeout_<n> as seconds for Chrome (factor 1)</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies Firefox 2x multiplier</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies Safari 4x multiplier</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies factor 1 for Edge</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns 0 (no timeout) when tag is @timeout_0, regardless of browser</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">uses the first matching tag and logs a warning when multiple are present</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">ignores malformed timeout-like tags</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">ignores non-string entries in tags</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">is registered as an auto fixture</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">calls testInfo.setTimeout with scaled value when tag matches</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">does not call testInfo.setTimeout when no tag is present</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">passes 0 through to testInfo.setTimeout for @timeout_0</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div></div></details><details id="suite-11" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/runner/__tests__/SpawnRunner.test.js</div><div class="suite-time">0.914s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">SpawnRunner > run</div><div class="test-title">should call runPreprocessing when bddMode is true</div><div class="test-status">passed</div><div class="test-duration">0.002s</div></div></div></div></details><details id="suite-12" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/runner/__tests__/RunnerHelper.test.js</div><div class="suite-time">0.857s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">RunnerHelper > createRunner</div><div class="test-title">should throw error on invalid runner type</div><div class="test-status">passed</div><div class="test-duration">0.002s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">RunnerHelper > createRunner</div><div class="test-title">should create a valid runner class</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-13" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/__tests__/validateFeature.test.js</div><div class="suite-time">1.071s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">validateFeatureFiles</div><div class="test-title">runPreprocessing with correct arguments and log success</div><div class="test-status">passed</div><div class="test-duration">0.003s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">validateFeatureFiles</div><div class="test-title">runPreprocessing with playwright conf</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">validateFeatureFiles</div><div class="test-title">error when runPreprocessing fails</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div></div></details><details id="suite-14" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/helpers/__tests__/fileMutex.test.js</div><div class="suite-time">1.638s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > acquire</div><div class="test-title">should create the lock file if it does not exist</div><div class="test-status">passed</div><div class="test-duration">0.013s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > acquire</div><div class="test-title">should wait for lock file deletion if it exists</div><div class="test-status">passed</div><div class="test-duration">0.002s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > acquire</div><div class="test-title">should reject if watch timeout exceeds</div><div class="test-status">passed</div><div class="test-duration">1.013s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > release</div><div class="test-title">should delete the lock file if it exists</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > release</div><div class="test-title">should release lock by deleting lock file</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > release</div><div class="test-title">should not attempt to delete the lock file if it does not exist</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">FileMutex > release</div><div class="test-title">should log an error if deleting the lock file fails</div><div class="test-status">passed</div><div class="test-duration">0.004s</div></div></div></div></details></main></body></html>
|
|
277
|
+
</style></head><body><main class="jesthtml-content"><header><h1 id="title">Unit Report</h1></header><section id="metadata-container"><div id="timestamp">Started: 2026-06-01 10:50:58</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed ">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (14)</div><div class="summary-passed ">14 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></section><details id="suite-1" class="suite-container" open=""><summary class="suite-info"><div class="suite-path">/Users/muthu-19817/git/testing-framework/src/test/core/playwright/buildInFixtures/__tests__/caseTimeout.test.js</div><div class="suite-time">0.437s</div></summary><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns null when no timeout tag is present</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns null when tags is not an array</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">parses @timeout_<n> as seconds for Chrome (factor 1)</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies Firefox 2x multiplier</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies Safari 4x multiplier</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">applies factor 1 for Edge</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">returns 0 (no timeout) when tag is @timeout_0, regardless of browser</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">uses the first matching tag and logs a warning when multiple are present</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">ignores malformed timeout-like tags</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">resolveCaseTimeoutMs</div><div class="test-title">ignores non-string entries in tags</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">is registered as an auto fixture</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">calls testInfo.setTimeout with scaled value when tag matches</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">does not call testInfo.setTimeout when no tag is present</div><div class="test-status">passed</div><div class="test-duration"> </div></div></div><div class="test-result passed"><div class="test-info"><div class="test-suitename">caseTimeout fixture</div><div class="test-title">passes 0 through to testInfo.setTimeout for @timeout_0</div><div class="test-status">passed</div><div class="test-duration">0.001s</div></div></div></div></details></main></body></html>
|