@umbraco/playwright-testhelpers 17.0.7 → 17.0.9
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/dist/lib/helpers/ApiHelpers.d.ts +16 -17
- package/dist/lib/helpers/ApiHelpers.js +106 -91
- package/dist/lib/helpers/ApiHelpers.js.map +1 -1
- package/dist/lib/helpers/DataTypeApiHelper.js +1 -1
- package/dist/lib/helpers/DataTypeApiHelper.js.map +1 -1
- package/dist/lib/helpers/LoginApiHelper.d.ts +4 -4
- package/dist/lib/helpers/LoginApiHelper.js +17 -16
- package/dist/lib/helpers/LoginApiHelper.js.map +1 -1
- package/dist/lib/helpers/UiBaseLocators.d.ts +1 -0
- package/dist/lib/helpers/UiBaseLocators.js +13 -2
- package/dist/lib/helpers/UiBaseLocators.js.map +1 -1
- package/dist/lib/helpers/UserApiHelper.d.ts +3 -3
- package/dist/lib/helpers/UserApiHelper.js +1 -2
- package/dist/lib/helpers/UserApiHelper.js.map +1 -1
- package/dist/lib/helpers/testExtension.js +1 -1
- package/dist/lib/helpers/testExtension.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -88,36 +88,35 @@ export declare class ApiHelpers {
|
|
|
88
88
|
delete(url: string, data?: object): Promise<import("playwright-core").APIResponse>;
|
|
89
89
|
put(url: string, data?: object): Promise<import("playwright-core").APIResponse>;
|
|
90
90
|
postMultiPartForm(url: string, id: any, name: string, mimeType: string, filePath: any): Promise<import("playwright-core").APIResponse>;
|
|
91
|
-
private getTokenIssuedTime;
|
|
92
|
-
private getTokenExpireTime;
|
|
93
91
|
getRefreshToken(): Promise<any>;
|
|
94
|
-
|
|
92
|
+
refreshLoginState(userEmail: string, userPassword: string): Promise<{
|
|
95
93
|
cookie: string;
|
|
96
|
-
accessToken:
|
|
97
|
-
refreshToken:
|
|
98
|
-
}>;
|
|
99
|
-
private
|
|
100
|
-
private dateToEpoch;
|
|
101
|
-
refreshAccessToken(userEmail: string, userPassword: string): Promise<void | {
|
|
102
|
-
cookie: string;
|
|
103
|
-
accessToken: any;
|
|
104
|
-
refreshToken: any;
|
|
105
|
-
}>;
|
|
94
|
+
accessToken: string;
|
|
95
|
+
refreshToken: string;
|
|
96
|
+
} | undefined>;
|
|
97
|
+
private splitCookies;
|
|
106
98
|
updateTokenAndCookie(userEmail: string, userPassword: string): Promise<{
|
|
107
99
|
cookie: string;
|
|
108
|
-
accessToken:
|
|
109
|
-
refreshToken:
|
|
100
|
+
accessToken: string;
|
|
101
|
+
refreshToken: string;
|
|
110
102
|
}>;
|
|
111
103
|
readFileContent(filePath: any): Promise<any>;
|
|
112
104
|
readLocalBearerToken(): Promise<string>;
|
|
113
105
|
readLocalCookie(): Promise<string>;
|
|
114
106
|
private getLocalStorageToken;
|
|
107
|
+
extractTokensFromSetCookie(setCookies: string): Promise<{
|
|
108
|
+
accessToken: string;
|
|
109
|
+
refreshToken: string;
|
|
110
|
+
}>;
|
|
115
111
|
private getLocalStorageAuthToken;
|
|
116
|
-
private updateLocalStorage;
|
|
117
112
|
private updateCookie;
|
|
118
113
|
revokeAccessToken(cookie: string, accessToken: string): Promise<import("playwright-core").APIResponse>;
|
|
119
114
|
revokeRefreshToken(cookie: string, refreshToken: string): Promise<import("playwright-core").APIResponse>;
|
|
120
|
-
loginToAdminUser(testUserCookie: string, testUserAccessToken: string, testUserRefreshToken: string): Promise<
|
|
115
|
+
loginToAdminUser(testUserCookie: string, testUserAccessToken: string, testUserRefreshToken: string): Promise<{
|
|
116
|
+
cookie: string;
|
|
117
|
+
accessToken: string;
|
|
118
|
+
refreshToken: string;
|
|
119
|
+
}>;
|
|
121
120
|
getCurrentTimePlusMinute(minute?: number): Promise<string>;
|
|
122
121
|
convertDateFormat(dateString: string): Promise<string>;
|
|
123
122
|
}
|
|
@@ -187,44 +187,48 @@ class ApiHelpers {
|
|
|
187
187
|
};
|
|
188
188
|
return await this.page.request.post(url, options);
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
190
|
+
// Currently not used
|
|
191
|
+
// private async getTokenIssuedTime() {
|
|
192
|
+
// const authToken = await this.getLocalStorageAuthToken();
|
|
193
|
+
// return Number(authToken.issued_at);
|
|
194
|
+
// }
|
|
195
|
+
// private async getTokenExpireTime() {
|
|
196
|
+
// const authToken = await this.getLocalStorageAuthToken();
|
|
197
|
+
// return Number(authToken.expires_in);
|
|
198
|
+
// }
|
|
199
|
+
//
|
|
200
|
+
// async isAccessTokenValid() {
|
|
201
|
+
// const tokenTimeIssued = await this.getTokenIssuedTime();
|
|
202
|
+
// const tokenExpireTime = await this.getTokenExpireTime();
|
|
203
|
+
// // Should use a global value
|
|
204
|
+
// const globalTestTimeout: number = 45;
|
|
205
|
+
// // We want to have the date minus the globalTimeout, the reason for this is that while a test is running, the token could expire.
|
|
206
|
+
// // The refresh token lasts for 300 seconds, while the access token lasts for 60 seconds (NOT TOTALLY SURE) this is why we add 240 seconds
|
|
207
|
+
// const tokenRefreshTime = tokenTimeIssued + tokenExpireTime - (globalTestTimeout);
|
|
208
|
+
// // We need the currentTimeInEpoch so we can check if the tokenRefreshTime is close to expiring.
|
|
209
|
+
// const currentTimeInEpoch = await this.currentDateToEpoch();
|
|
210
|
+
//
|
|
211
|
+
// if (tokenRefreshTime <= currentTimeInEpoch) {
|
|
212
|
+
// return await this.refreshAccessToken(umbracoConfig.user.login, umbracoConfig.user.password);
|
|
213
|
+
// }
|
|
214
|
+
// }
|
|
198
215
|
async getRefreshToken() {
|
|
199
216
|
const authToken = await this.getLocalStorageAuthToken();
|
|
200
217
|
return authToken.refresh_token;
|
|
201
218
|
}
|
|
202
|
-
async
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
async currentDateToEpoch() {
|
|
217
|
-
const currentTime = new Date(Date.now());
|
|
218
|
-
return await this.dateToEpoch(currentTime);
|
|
219
|
-
}
|
|
220
|
-
async dateToEpoch(date) {
|
|
221
|
-
const dateToEpoch = date.getTime();
|
|
222
|
-
// The epoch is in milliseconds, but we want it to be in seconds(Like it is in the token).
|
|
223
|
-
const millisecondsToSeconds = dateToEpoch / 1000;
|
|
224
|
-
// There is no need to have anything after .
|
|
225
|
-
return Number(millisecondsToSeconds.toString().split('.')[0]);
|
|
226
|
-
}
|
|
227
|
-
async refreshAccessToken(userEmail, userPassword) {
|
|
219
|
+
// private async currentDateToEpoch() {
|
|
220
|
+
// const currentTime = new Date(Date.now());
|
|
221
|
+
// return await this.dateToEpoch(currentTime);
|
|
222
|
+
// }
|
|
223
|
+
//
|
|
224
|
+
// private async dateToEpoch(date: Date) {
|
|
225
|
+
// const dateToEpoch = date.getTime();
|
|
226
|
+
// // The epoch is in milliseconds, but we want it to be in seconds(Like it is in the token).
|
|
227
|
+
// const millisecondsToSeconds = dateToEpoch / 1000;
|
|
228
|
+
// // There is no need to have anything after .
|
|
229
|
+
// return Number(millisecondsToSeconds.toString().split('.')[0]);
|
|
230
|
+
// }
|
|
231
|
+
async refreshLoginState(userEmail, userPassword) {
|
|
228
232
|
const response = await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/token', {
|
|
229
233
|
headers: {
|
|
230
234
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -240,20 +244,38 @@ class ApiHelpers {
|
|
|
240
244
|
ignoreHTTPSErrors: true
|
|
241
245
|
});
|
|
242
246
|
if (response.status() === 200) {
|
|
243
|
-
const
|
|
244
|
-
|
|
247
|
+
const jsonStorageCookie = response.headers()['set-cookie'];
|
|
248
|
+
// We get multiple cookies, so we have to split them and then update each of the cookies in our localstorage
|
|
249
|
+
let cookies = this.splitCookies(jsonStorageCookie);
|
|
250
|
+
for (const cookie of cookies) {
|
|
251
|
+
await this.updateCookie(cookie);
|
|
252
|
+
}
|
|
253
|
+
return;
|
|
245
254
|
}
|
|
246
255
|
console.log('Error refreshing access token.');
|
|
247
256
|
return await this.updateTokenAndCookie(userEmail, userPassword);
|
|
248
257
|
}
|
|
258
|
+
splitCookies(cookieString) {
|
|
259
|
+
return cookieString
|
|
260
|
+
.trim()
|
|
261
|
+
.split('\n')
|
|
262
|
+
.filter(line => line.trim())
|
|
263
|
+
.filter(line => !line.includes('expires=Thu, 01 Jan 1970'));
|
|
264
|
+
}
|
|
249
265
|
async updateTokenAndCookie(userEmail, userPassword) {
|
|
250
266
|
const storageStateValues = await this.login.login(userEmail, userPassword);
|
|
251
267
|
await this.updateCookie(storageStateValues.cookie);
|
|
252
|
-
|
|
268
|
+
// We get multiple set cookies, so we have to split them and then update each of the cookies in our localstorage
|
|
269
|
+
let cookies = this.splitCookies(storageStateValues.setCookies);
|
|
270
|
+
for (const cookie of cookies) {
|
|
271
|
+
await this.updateCookie(cookie);
|
|
272
|
+
}
|
|
273
|
+
let tokens = await this.extractTokensFromSetCookie(storageStateValues.setCookies);
|
|
274
|
+
console.log('Successfully retrieved new authentication tokens.');
|
|
253
275
|
return {
|
|
254
276
|
cookie: storageStateValues.cookie,
|
|
255
|
-
accessToken:
|
|
256
|
-
refreshToken:
|
|
277
|
+
accessToken: tokens.accessToken,
|
|
278
|
+
refreshToken: tokens.refreshToken,
|
|
257
279
|
};
|
|
258
280
|
}
|
|
259
281
|
async readFileContent(filePath) {
|
|
@@ -299,67 +321,58 @@ class ApiHelpers {
|
|
|
299
321
|
async getLocalStorageToken(localStorage, tokenName) {
|
|
300
322
|
return await localStorage.origins?.[0]?.localStorage?.find(item => item.name === tokenName);
|
|
301
323
|
}
|
|
324
|
+
async extractTokensFromSetCookie(setCookies) {
|
|
325
|
+
// Extract token values from cookies
|
|
326
|
+
const accessToken = setCookies.match(/__Host-umbAccessToken=([^;]+)/)?.[1] ?? "";
|
|
327
|
+
const refreshToken = setCookies.match(/__Host-umbRefreshToken=([^;]+)/)?.[1] ?? "";
|
|
328
|
+
return { accessToken, refreshToken };
|
|
329
|
+
}
|
|
302
330
|
async getLocalStorageAuthToken() {
|
|
303
331
|
const currentStorageState = await this.page.context().storageState();
|
|
304
332
|
const currentStorageToken = await this.getLocalStorageToken(currentStorageState, 'umb:userAuthTokenResponse');
|
|
305
333
|
return JSON.parse(currentStorageToken.value);
|
|
306
334
|
}
|
|
307
|
-
async updateLocalStorage(localStorageValue) {
|
|
308
|
-
// Parse the existing token value and update its fields
|
|
309
|
-
let currentLocalStorageValue = await this.getLocalStorageAuthToken();
|
|
310
|
-
const newIssuedTime = await this.currentDateToEpoch();
|
|
311
|
-
currentLocalStorageValue.access_token = localStorageValue.access_token;
|
|
312
|
-
currentLocalStorageValue.refresh_token = localStorageValue.refresh_token;
|
|
313
|
-
currentLocalStorageValue.issued_at = newIssuedTime;
|
|
314
|
-
currentLocalStorageValue.scope = localStorageValue.scope;
|
|
315
|
-
currentLocalStorageValue.token_type = localStorageValue.token_type;
|
|
316
|
-
currentLocalStorageValue.expires_in = localStorageValue.expires_in.toString();
|
|
317
|
-
const filePath = process.env.STORAGE_STAGE_PATH;
|
|
318
|
-
// Updates the user.json file in our CMS project
|
|
319
|
-
if (filePath) {
|
|
320
|
-
try {
|
|
321
|
-
const data = await this.readFileContent(filePath);
|
|
322
|
-
const fileLocalStorageToken = await this.getLocalStorageToken(data, 'umb:userAuthTokenResponse');
|
|
323
|
-
fileLocalStorageToken.value = JSON.stringify(currentLocalStorageValue);
|
|
324
|
-
// Converts the object to JSON string
|
|
325
|
-
const updatedJsonString = JSON.stringify(data, null, 2);
|
|
326
|
-
// Writes the updated JSON content to the file
|
|
327
|
-
fs.writeFileSync(filePath, updatedJsonString, 'utf-8');
|
|
328
|
-
}
|
|
329
|
-
catch (error) {
|
|
330
|
-
console.error('Error updating token:', error);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
335
|
async updateCookie(cookieString) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
// Updates the expires value and converts it to Epoch
|
|
348
|
-
currentCookie.expires = await this.dateToEpoch(new Date(val));
|
|
336
|
+
try {
|
|
337
|
+
// Parse cookie string
|
|
338
|
+
const parts = cookieString.split(';').map(p => p.trim());
|
|
339
|
+
const [nameValue, ...attributes] = parts;
|
|
340
|
+
const [name, value] = nameValue.split('=');
|
|
341
|
+
const cookieName = name.trim();
|
|
342
|
+
// Get current state
|
|
343
|
+
const storageState = await this.page.context().storageState();
|
|
344
|
+
const cookieIndex = storageState.cookies.findIndex(c => c.name === cookieName);
|
|
345
|
+
if (cookieIndex === -1) {
|
|
346
|
+
console.log(`Cookie "${cookieName}" not found`);
|
|
347
|
+
return;
|
|
349
348
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
349
|
+
// Update cookie value
|
|
350
|
+
storageState.cookies[cookieIndex].value = value;
|
|
351
|
+
// Update expires if present
|
|
352
|
+
for (const attr of attributes) {
|
|
353
|
+
if (attr.toLowerCase().startsWith('expires=')) {
|
|
354
|
+
const expiresDate = attr.split('=')[1];
|
|
355
|
+
storageState.cookies[cookieIndex].expires = Date.parse(expiresDate) / 1000;
|
|
356
|
+
}
|
|
358
357
|
}
|
|
359
|
-
|
|
360
|
-
|
|
358
|
+
// Write to file if path exists
|
|
359
|
+
const filePath = process.env.STORAGE_STAGE_PATH;
|
|
360
|
+
if (filePath) {
|
|
361
|
+
const fs = require('fs');
|
|
362
|
+
const fileData = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
363
|
+
const fileCookieIndex = fileData.cookies.findIndex(c => c.name === cookieName);
|
|
364
|
+
if (fileCookieIndex !== -1) {
|
|
365
|
+
fileData.cookies[fileCookieIndex] = storageState.cookies[cookieIndex];
|
|
366
|
+
fs.writeFileSync(filePath, JSON.stringify(fileData, null, 2));
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
console.log(`Cookie "${cookieName}" not found in file`);
|
|
370
|
+
}
|
|
361
371
|
}
|
|
362
372
|
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
console.error('Error updating cookie:', error);
|
|
375
|
+
}
|
|
363
376
|
}
|
|
364
377
|
async revokeAccessToken(cookie, accessToken) {
|
|
365
378
|
return await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/revoke', {
|
|
@@ -394,7 +407,9 @@ class ApiHelpers {
|
|
|
394
407
|
async loginToAdminUser(testUserCookie, testUserAccessToken, testUserRefreshToken) {
|
|
395
408
|
await this.revokeAccessToken(testUserCookie, testUserAccessToken);
|
|
396
409
|
await this.revokeRefreshToken(testUserCookie, testUserRefreshToken);
|
|
397
|
-
|
|
410
|
+
let userCookieAndTokens;
|
|
411
|
+
userCookieAndTokens = await this.updateTokenAndCookie(umbraco_config_1.umbracoConfig.user.login, umbraco_config_1.umbracoConfig.user.password);
|
|
412
|
+
return userCookieAndTokens;
|
|
398
413
|
}
|
|
399
414
|
async getCurrentTimePlusMinute(minute = 1) {
|
|
400
415
|
const now = new Date();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiHelpers.js","sourceRoot":"","sources":["../../../lib/helpers/ApiHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {Page} from \"@playwright/test\"\nimport {umbracoConfig} from \"../../umbraco.config\";\nimport {ReportHelper} from \"./ReportHelper\";\nimport {TelemetryDataApiHelper} from \"./TelemetryDataApiHelper\";\nimport {LanguageApiHelper} from \"./LanguageApiHelper\";\nimport {DictionaryApiHelper} from \"./DictionaryApiHelper\";\nimport {RelationTypeApiHelper} from \"./RelationTypeApiHelper\";\nimport {UserGroupApiHelper} from \"./UserGroupApiHelper\";\nimport {TemplateApiHelper} from \"./TemplateApiHelper\";\nimport {AliasHelper} from \"./AliasHelper\";\nimport {DataTypeApiHelper} from \"./DataTypeApiHelper\";\nimport {UserApiHelper} from \"./UserApiHelper\";\nimport {TemporaryFileApiHelper} from \"./TemporaryFileApiHelper\";\nimport {PackageApiHelper} from \"./PackageApiHelper\";\nimport {ScriptApiHelper} from \"./ScriptApiHelper\";\nimport {PartialViewApiHelper} from \"./PartialViewApiHelper\";\nimport {StylesheetApiHelper} from \"./StylesheetApiHelper\";\nimport * as fs from \"fs\";\nimport {LogViewerApiHelper} from \"./LogViewerApiHelper\";\nimport {DocumentTypeApiHelper} from \"./DocumentTypeApiHelper\";\nimport {DocumentApiHelper} from \"./DocumentApiHelper\";\nimport {MediaTypeApiHelper} from \"./MediaTypeApiHelper\";\nimport {MediaApiHelper} from \"./MediaApiHelper\";\nimport {ObjectTypesApiHelper} from \"./ObjectTypesApiHelper\";\nimport {ModelsBuilderApiHelper} from \"./ModelsBuilderApiHelper\";\nimport {HealthCheckApiHelper} from \"./HealthCheckApiHelper\";\nimport {IndexerApiHelper} from \"./IndexerApiHelper\";\nimport {PublishedCacheApiHelper} from \"./PublishedCacheApiHelper\";\nimport {RedirectManagementApiHelper} from './RedirectManagementApiHelper';\nimport {MemberGroupApiHelper} from './MemberGroupApiHelper';\nimport {MemberApiHelper} from './MemberApiHelper';\nimport {MemberTypeApiHelper} from \"./MemberTypeApiHelper\";\nimport {DocumentBlueprintApiHelper} from \"./DocumentBlueprintApiHelper\";\nimport {LoginApiHelper} from \"./LoginApiHelper\";\nimport {WebhookApiHelper} from \"./WebhookApiHelper\";\nimport {MediaDeliveryApiHelper} from './differentAppSettingsHelpers/MediaDeliveryApiHelper';\nimport {ContentDeliveryApiHelper} from \"./differentAppSettingsHelpers/ContentDeliveryApiHelper\";\n\nexport class ApiHelpers {\n baseUrl: string = umbracoConfig.environment.baseUrl;\n page: Page;\n alias: AliasHelper;\n report: ReportHelper;\n telemetry: TelemetryDataApiHelper;\n language: LanguageApiHelper;\n dictionary: DictionaryApiHelper;\n relationType: RelationTypeApiHelper;\n userGroup: UserGroupApiHelper;\n template: TemplateApiHelper;\n dataType: DataTypeApiHelper;\n user: UserApiHelper;\n temporaryFile: TemporaryFileApiHelper;\n documentType: DocumentTypeApiHelper;\n document: DocumentApiHelper;\n package: PackageApiHelper;\n script: ScriptApiHelper;\n partialView: PartialViewApiHelper;\n stylesheet: StylesheetApiHelper;\n logViewer: LogViewerApiHelper;\n mediaType: MediaTypeApiHelper;\n media: MediaApiHelper;\n objectTypes: ObjectTypesApiHelper;\n modelsBuilder: ModelsBuilderApiHelper;\n healthCheck: HealthCheckApiHelper;\n indexer: IndexerApiHelper;\n publishedCache: PublishedCacheApiHelper;\n redirectManagement: RedirectManagementApiHelper;\n memberGroup: MemberGroupApiHelper;\n member: MemberApiHelper;\n memberType: MemberTypeApiHelper;\n documentBlueprint: DocumentBlueprintApiHelper;\n login: LoginApiHelper;\n webhook: WebhookApiHelper;\n mediaDeliveryApi: MediaDeliveryApiHelper;\n contentDeliveryApi: ContentDeliveryApiHelper;\n\n constructor(page: Page) {\n this.page = page;\n this.alias = new AliasHelper();\n this.report = new ReportHelper(this);\n this.telemetry = new TelemetryDataApiHelper(this);\n this.language = new LanguageApiHelper(this);\n this.dictionary = new DictionaryApiHelper(this);\n this.relationType = new RelationTypeApiHelper(this);\n this.userGroup = new UserGroupApiHelper(this);\n this.template = new TemplateApiHelper(this);\n this.dataType = new DataTypeApiHelper(this);\n this.user = new UserApiHelper(this, page);\n this.temporaryFile = new TemporaryFileApiHelper(this);\n this.documentType = new DocumentTypeApiHelper(this);\n this.document = new DocumentApiHelper(this);\n this.package = new PackageApiHelper(this);\n this.script = new ScriptApiHelper(this);\n this.partialView = new PartialViewApiHelper(this);\n this.stylesheet = new StylesheetApiHelper(this);\n this.logViewer = new LogViewerApiHelper(this);\n this.mediaType = new MediaTypeApiHelper(this);\n this.media = new MediaApiHelper(this);\n this.objectTypes = new ObjectTypesApiHelper(this);\n this.modelsBuilder = new ModelsBuilderApiHelper(this);\n this.healthCheck = new HealthCheckApiHelper(this);\n this.indexer = new IndexerApiHelper(this);\n this.publishedCache = new PublishedCacheApiHelper(this);\n this.redirectManagement = new RedirectManagementApiHelper(this);\n this.memberGroup = new MemberGroupApiHelper(this);\n this.member = new MemberApiHelper(this);\n this.memberType = new MemberTypeApiHelper(this);\n this.documentBlueprint = new DocumentBlueprintApiHelper(this);\n this.login = new LoginApiHelper(this, this.page);\n this.webhook = new WebhookApiHelper(this, this.page);\n this.mediaDeliveryApi = new MediaDeliveryApiHelper(this);\n this.contentDeliveryApi = new ContentDeliveryApiHelper(this);\n }\n\n async getAccessToken() {\n const authToken = await this.getLocalStorageAuthToken();\n return authToken.access_token;\n }\n\n async getBearerToken() {\n return 'Bearer ' + await this.getAccessToken();\n }\n\n async getCookie() {\n let someStorage = await this.page.context().storageState();\n let cookieString = \"\";\n for (let cookie of someStorage.cookies) {\n cookieString += cookie.name + '=' + cookie.value + ';';\n }\n return cookieString;\n }\n\n async getHeaders() {\n return {\n 'Authorization': await this.readLocalBearerToken(),\n 'Cookie': await this.readLocalCookie(),\n }\n }\n\n async get(url: string, params?: { [key: string]: string | number | boolean; }, extraHeaders?: { [key: string]: string; }) {\n const headers = await this.getHeaders();\n const allHeaders = { ...headers, ...extraHeaders };\n const options = {\n headers: allHeaders,\n params: params,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.get(url, options);\n }\n\n async saveCodeFile(codeFile) {\n if (codeFile == null) {\n return;\n }\n return await this.post(umbracoConfig.environment.baseUrl + '/umbraco/backoffice/UmbracoApi/CodeFile/PostSave', codeFile);\n }\n\n async post(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.post(url, options);\n }\n\n async delete(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.delete(url, options);\n }\n\n async put(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.put(url, options);\n }\n\n async postMultiPartForm(url: string, id, name: string, mimeType: string, filePath) {\n const options = {\n headers: await this.getHeaders(),\n multipart: {\n Id: id,\n File: {\n name: name,\n mimeType: mimeType,\n buffer: fs.readFileSync(filePath)\n }\n },\n ignoreHTTPSErrors: true\n }\n return await this.page.request.post(url, options);\n }\n\n private async getTokenIssuedTime() {\n const authToken = await this.getLocalStorageAuthToken();\n return Number(authToken.issued_at);\n }\n\n private async getTokenExpireTime() {\n const authToken = await this.getLocalStorageAuthToken();\n return Number(authToken.expires_in);\n }\n\n async getRefreshToken() {\n const authToken = await this.getLocalStorageAuthToken();\n return authToken.refresh_token;\n }\n\n async isAccessTokenValid() {\n const tokenTimeIssued = await this.getTokenIssuedTime();\n const tokenExpireTime = await this.getTokenExpireTime();\n // Should use a global value\n const globalTestTimeout: number = 45;\n // We want to have the date minus the globalTimeout, the reason for this is that while a test is running, the token could expire.\n // The refresh token lasts for 300 seconds, while the access token lasts for 60 seconds (NOT TOTALLY SURE) this is why we add 240 seconds\n const tokenRefreshTime = tokenTimeIssued + tokenExpireTime - (globalTestTimeout);\n // We need the currentTimeInEpoch so we can check if the tokenRefreshTime is close to expiring.\n const currentTimeInEpoch = await this.currentDateToEpoch();\n\n if (tokenRefreshTime <= currentTimeInEpoch) {\n return await this.refreshAccessToken(umbracoConfig.user.login, umbracoConfig.user.password);\n }\n }\n\n private async currentDateToEpoch() {\n const currentTime = new Date(Date.now());\n return await this.dateToEpoch(currentTime);\n }\n\n private async dateToEpoch(date: Date) {\n const dateToEpoch = date.getTime();\n // The epoch is in milliseconds, but we want it to be in seconds(Like it is in the token).\n const millisecondsToSeconds = dateToEpoch / 1000;\n // There is no need to have anything after .\n return Number(millisecondsToSeconds.toString().split('.')[0]);\n }\n\n async refreshAccessToken(userEmail: string, userPassword: string) {\n const response = await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/token', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: await this.readLocalCookie(),\n Origin: this.baseUrl\n },\n form:\n {\n grant_type: 'refresh_token',\n client_id: 'umbraco-back-office',\n redirect_uri: this.baseUrl + '/umbraco/oauth_complete',\n refresh_token: await this.getRefreshToken()\n },\n ignoreHTTPSErrors: true\n });\n\n if (response.status() === 200) {\n const jsonStorageValue = await response.json();\n return await this.updateLocalStorage(jsonStorageValue);\n }\n console.log('Error refreshing access token.');\n return await this.updateTokenAndCookie(userEmail, userPassword);\n }\n\n async updateTokenAndCookie(userEmail: string, userPassword: string) {\n const storageStateValues = await this.login.login(userEmail, userPassword);\n await this.updateCookie(storageStateValues.cookie);\n await this.updateLocalStorage(storageStateValues.accessToken);\n return {\n cookie: storageStateValues.cookie,\n accessToken: storageStateValues.accessToken.access_token,\n refreshToken: storageStateValues.refreshToken.refresh_token\n };\n }\n\n async readFileContent(filePath) {\n try {\n const jsonString = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(jsonString);\n } catch (error) {\n console.log('Error reading file:', error);\n throw error;\n }\n }\n\n async readLocalBearerToken() {\n const filePath = process.env.STORAGE_STAGE_PATH;\n if (!filePath) {\n return await this.getBearerToken();\n }\n\n try {\n const data = await JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n const localStorageItem = await this.getLocalStorageToken(data, 'umb:userAuthTokenResponse');\n const parsedValue = await JSON.parse(localStorageItem.value);\n return `Bearer ${parsedValue.access_token}`;\n } catch {\n // If the file is not found, return the current access token from the page context\n return await this.getBearerToken();\n }\n }\n\n async readLocalCookie() {\n const filePath = process.env.STORAGE_STAGE_PATH;\n if (!filePath) {\n return await this.getCookie();\n }\n\n try {\n const data = await JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return await data.cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ') + ';';\n } catch {\n // If the file is not found, return the current cookie from the page context\n return await this.getCookie();\n }\n }\n\n private async getLocalStorageToken(localStorage: any, tokenName: string) {\n return await localStorage.origins?.[0]?.localStorage?.find(item => item.name === tokenName);\n }\n\n private async getLocalStorageAuthToken(){\n const currentStorageState = await this.page.context().storageState();\n const currentStorageToken = await this.getLocalStorageToken(currentStorageState, 'umb:userAuthTokenResponse');\n return JSON.parse(currentStorageToken.value);\n }\n\n private async updateLocalStorage(localStorageValue) {\n // Parse the existing token value and update its fields\n let currentLocalStorageValue = await this.getLocalStorageAuthToken();\n const newIssuedTime = await this.currentDateToEpoch();\n\n currentLocalStorageValue.access_token = localStorageValue.access_token;\n currentLocalStorageValue.refresh_token = localStorageValue.refresh_token;\n currentLocalStorageValue.issued_at = newIssuedTime;\n currentLocalStorageValue.scope = localStorageValue.scope;\n currentLocalStorageValue.token_type = localStorageValue.token_type;\n currentLocalStorageValue.expires_in = localStorageValue.expires_in.toString();\n\n const filePath = process.env.STORAGE_STAGE_PATH;\n // Updates the user.json file in our CMS project\n if (filePath) {\n try {\n const data = await this.readFileContent(filePath);\n const fileLocalStorageToken = await this.getLocalStorageToken(data, 'umb:userAuthTokenResponse');\n fileLocalStorageToken.value = JSON.stringify(currentLocalStorageValue);\n // Converts the object to JSON string\n const updatedJsonString = JSON.stringify(data, null, 2);\n // Writes the updated JSON content to the file\n fs.writeFileSync(filePath, updatedJsonString, 'utf-8');\n } catch (error) {\n console.error('Error updating token:', error);\n }\n }\n }\n\n private async updateCookie(cookieString: string) {\n const currentStorageState = await this.page.context().storageState();\n let currentCookie = currentStorageState.cookies[0];\n\n const parts = cookieString.split(';').map(part => part.trim());\n // Extract the main key-value pair\n const [nameValue, ...attributes] = parts;\n const [, value] = nameValue.split('=');\n // Updates the cookie value\n currentCookie.value = value;\n // Process each attribute\n for (const attr of attributes) {\n const [key, val] = attr.split('=');\n if (key.trim().toLowerCase() === 'expires') {\n // Updates the expires value and converts it to Epoch\n currentCookie.expires = await this.dateToEpoch(new Date(val));\n }\n }\n\n const filePath = process.env.STORAGE_STAGE_PATH;\n\n if (filePath) {\n try {\n const data = await this.readFileContent(filePath);\n data.cookies[0] = currentCookie;\n const updatedJsonString = JSON.stringify(data, null, 2);\n fs.writeFileSync(filePath, updatedJsonString, 'utf-8');\n } catch (error) {\n console.error('Error updating cookie:', error);\n }\n }\n }\n\n async revokeAccessToken(cookie: string, accessToken: string) {\n return await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/revoke', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: cookie,\n Origin: this.baseUrl\n },\n form:\n {\n token: accessToken,\n token_type_hint: 'access_token',\n client_id: 'umbraco-back-office'\n },\n ignoreHTTPSErrors: true\n });\n }\n\n async revokeRefreshToken(cookie: string, refreshToken: string) {\n return await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/revoke', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: cookie,\n Origin: this.baseUrl\n },\n form:\n {\n token: refreshToken,\n token_type_hint: 'refresh_token',\n client_id: 'umbraco-back-office'\n },\n ignoreHTTPSErrors: true\n });\n }\n\n async loginToAdminUser(testUserCookie: string, testUserAccessToken: string, testUserRefreshToken: string) {\n await this.revokeAccessToken(testUserCookie, testUserAccessToken);\n await this.revokeRefreshToken(testUserCookie, testUserRefreshToken);\n await this.updateTokenAndCookie(umbracoConfig.user.login, umbracoConfig.user.password);\n }\n\n async getCurrentTimePlusMinute(minute: number = 1) {\n const now = new Date();\n now.setMinutes(now.getMinutes() + minute); // Add one minute\n\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n \n return `${year}-${month}-${day}T${hours}:${minutes}`;\n }\n\n async convertDateFormat(dateString: string) {\n return new Date(dateString).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n hour12: true,\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"ApiHelpers.js","sourceRoot":"","sources":["../../../lib/helpers/ApiHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["import {Page} from \"@playwright/test\"\nimport {umbracoConfig} from \"../../umbraco.config\";\nimport {ReportHelper} from \"./ReportHelper\";\nimport {TelemetryDataApiHelper} from \"./TelemetryDataApiHelper\";\nimport {LanguageApiHelper} from \"./LanguageApiHelper\";\nimport {DictionaryApiHelper} from \"./DictionaryApiHelper\";\nimport {RelationTypeApiHelper} from \"./RelationTypeApiHelper\";\nimport {UserGroupApiHelper} from \"./UserGroupApiHelper\";\nimport {TemplateApiHelper} from \"./TemplateApiHelper\";\nimport {AliasHelper} from \"./AliasHelper\";\nimport {DataTypeApiHelper} from \"./DataTypeApiHelper\";\nimport {UserApiHelper} from \"./UserApiHelper\";\nimport {TemporaryFileApiHelper} from \"./TemporaryFileApiHelper\";\nimport {PackageApiHelper} from \"./PackageApiHelper\";\nimport {ScriptApiHelper} from \"./ScriptApiHelper\";\nimport {PartialViewApiHelper} from \"./PartialViewApiHelper\";\nimport {StylesheetApiHelper} from \"./StylesheetApiHelper\";\nimport * as fs from \"fs\";\nimport {LogViewerApiHelper} from \"./LogViewerApiHelper\";\nimport {DocumentTypeApiHelper} from \"./DocumentTypeApiHelper\";\nimport {DocumentApiHelper} from \"./DocumentApiHelper\";\nimport {MediaTypeApiHelper} from \"./MediaTypeApiHelper\";\nimport {MediaApiHelper} from \"./MediaApiHelper\";\nimport {ObjectTypesApiHelper} from \"./ObjectTypesApiHelper\";\nimport {ModelsBuilderApiHelper} from \"./ModelsBuilderApiHelper\";\nimport {HealthCheckApiHelper} from \"./HealthCheckApiHelper\";\nimport {IndexerApiHelper} from \"./IndexerApiHelper\";\nimport {PublishedCacheApiHelper} from \"./PublishedCacheApiHelper\";\nimport {RedirectManagementApiHelper} from './RedirectManagementApiHelper';\nimport {MemberGroupApiHelper} from './MemberGroupApiHelper';\nimport {MemberApiHelper} from './MemberApiHelper';\nimport {MemberTypeApiHelper} from \"./MemberTypeApiHelper\";\nimport {DocumentBlueprintApiHelper} from \"./DocumentBlueprintApiHelper\";\nimport {LoginApiHelper} from \"./LoginApiHelper\";\nimport {WebhookApiHelper} from \"./WebhookApiHelper\";\nimport {MediaDeliveryApiHelper} from './differentAppSettingsHelpers/MediaDeliveryApiHelper';\nimport {ContentDeliveryApiHelper} from \"./differentAppSettingsHelpers/ContentDeliveryApiHelper\";\n\nexport class ApiHelpers {\n baseUrl: string = umbracoConfig.environment.baseUrl;\n page: Page;\n alias: AliasHelper;\n report: ReportHelper;\n telemetry: TelemetryDataApiHelper;\n language: LanguageApiHelper;\n dictionary: DictionaryApiHelper;\n relationType: RelationTypeApiHelper;\n userGroup: UserGroupApiHelper;\n template: TemplateApiHelper;\n dataType: DataTypeApiHelper;\n user: UserApiHelper;\n temporaryFile: TemporaryFileApiHelper;\n documentType: DocumentTypeApiHelper;\n document: DocumentApiHelper;\n package: PackageApiHelper;\n script: ScriptApiHelper;\n partialView: PartialViewApiHelper;\n stylesheet: StylesheetApiHelper;\n logViewer: LogViewerApiHelper;\n mediaType: MediaTypeApiHelper;\n media: MediaApiHelper;\n objectTypes: ObjectTypesApiHelper;\n modelsBuilder: ModelsBuilderApiHelper;\n healthCheck: HealthCheckApiHelper;\n indexer: IndexerApiHelper;\n publishedCache: PublishedCacheApiHelper;\n redirectManagement: RedirectManagementApiHelper;\n memberGroup: MemberGroupApiHelper;\n member: MemberApiHelper;\n memberType: MemberTypeApiHelper;\n documentBlueprint: DocumentBlueprintApiHelper;\n login: LoginApiHelper;\n webhook: WebhookApiHelper;\n mediaDeliveryApi: MediaDeliveryApiHelper;\n contentDeliveryApi: ContentDeliveryApiHelper;\n\n constructor(page: Page) {\n this.page = page;\n this.alias = new AliasHelper();\n this.report = new ReportHelper(this);\n this.telemetry = new TelemetryDataApiHelper(this);\n this.language = new LanguageApiHelper(this);\n this.dictionary = new DictionaryApiHelper(this);\n this.relationType = new RelationTypeApiHelper(this);\n this.userGroup = new UserGroupApiHelper(this);\n this.template = new TemplateApiHelper(this);\n this.dataType = new DataTypeApiHelper(this);\n this.user = new UserApiHelper(this, page);\n this.temporaryFile = new TemporaryFileApiHelper(this);\n this.documentType = new DocumentTypeApiHelper(this);\n this.document = new DocumentApiHelper(this);\n this.package = new PackageApiHelper(this);\n this.script = new ScriptApiHelper(this);\n this.partialView = new PartialViewApiHelper(this);\n this.stylesheet = new StylesheetApiHelper(this);\n this.logViewer = new LogViewerApiHelper(this);\n this.mediaType = new MediaTypeApiHelper(this);\n this.media = new MediaApiHelper(this);\n this.objectTypes = new ObjectTypesApiHelper(this);\n this.modelsBuilder = new ModelsBuilderApiHelper(this);\n this.healthCheck = new HealthCheckApiHelper(this);\n this.indexer = new IndexerApiHelper(this);\n this.publishedCache = new PublishedCacheApiHelper(this);\n this.redirectManagement = new RedirectManagementApiHelper(this);\n this.memberGroup = new MemberGroupApiHelper(this);\n this.member = new MemberApiHelper(this);\n this.memberType = new MemberTypeApiHelper(this);\n this.documentBlueprint = new DocumentBlueprintApiHelper(this);\n this.login = new LoginApiHelper(this, this.page);\n this.webhook = new WebhookApiHelper(this, this.page);\n this.mediaDeliveryApi = new MediaDeliveryApiHelper(this);\n this.contentDeliveryApi = new ContentDeliveryApiHelper(this);\n }\n\n async getAccessToken() {\n const authToken = await this.getLocalStorageAuthToken();\n return authToken.access_token;\n }\n\n async getBearerToken() {\n return 'Bearer ' + await this.getAccessToken();\n }\n\n async getCookie() {\n let someStorage = await this.page.context().storageState();\n let cookieString = \"\";\n for (let cookie of someStorage.cookies) {\n cookieString += cookie.name + '=' + cookie.value + ';';\n }\n return cookieString;\n }\n\n async getHeaders() {\n return {\n 'Authorization': await this.readLocalBearerToken(),\n 'Cookie': await this.readLocalCookie(),\n }\n }\n\n async get(url: string, params?: { [key: string]: string | number | boolean; }, extraHeaders?: { [key: string]: string; }) {\n const headers = await this.getHeaders();\n const allHeaders = {...headers, ...extraHeaders};\n const options = {\n headers: allHeaders,\n params: params,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.get(url, options);\n }\n\n async saveCodeFile(codeFile) {\n if (codeFile == null) {\n return;\n }\n return await this.post(umbracoConfig.environment.baseUrl + '/umbraco/backoffice/UmbracoApi/CodeFile/PostSave', codeFile);\n }\n\n async post(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.post(url, options);\n }\n\n async delete(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.delete(url, options);\n }\n\n async put(url: string, data?: object) {\n const options = {\n headers: await this.getHeaders(),\n data: data,\n ignoreHTTPSErrors: true\n }\n return await this.page.request.put(url, options);\n }\n\n async postMultiPartForm(url: string, id, name: string, mimeType: string, filePath) {\n const options = {\n headers: await this.getHeaders(),\n multipart: {\n Id: id,\n File: {\n name: name,\n mimeType: mimeType,\n buffer: fs.readFileSync(filePath)\n }\n },\n ignoreHTTPSErrors: true\n }\n return await this.page.request.post(url, options);\n }\n\n // Currently not used\n // private async getTokenIssuedTime() {\n // const authToken = await this.getLocalStorageAuthToken();\n // return Number(authToken.issued_at);\n // }\n // private async getTokenExpireTime() {\n // const authToken = await this.getLocalStorageAuthToken();\n // return Number(authToken.expires_in);\n // }\n //\n // async isAccessTokenValid() {\n // const tokenTimeIssued = await this.getTokenIssuedTime();\n // const tokenExpireTime = await this.getTokenExpireTime();\n // // Should use a global value\n // const globalTestTimeout: number = 45;\n // // We want to have the date minus the globalTimeout, the reason for this is that while a test is running, the token could expire.\n // // The refresh token lasts for 300 seconds, while the access token lasts for 60 seconds (NOT TOTALLY SURE) this is why we add 240 seconds\n // const tokenRefreshTime = tokenTimeIssued + tokenExpireTime - (globalTestTimeout);\n // // We need the currentTimeInEpoch so we can check if the tokenRefreshTime is close to expiring.\n // const currentTimeInEpoch = await this.currentDateToEpoch();\n //\n // if (tokenRefreshTime <= currentTimeInEpoch) {\n // return await this.refreshAccessToken(umbracoConfig.user.login, umbracoConfig.user.password);\n // }\n // }\n async getRefreshToken() {\n const authToken = await this.getLocalStorageAuthToken();\n return authToken.refresh_token;\n }\n\n // private async currentDateToEpoch() {\n // const currentTime = new Date(Date.now());\n // return await this.dateToEpoch(currentTime);\n // }\n //\n // private async dateToEpoch(date: Date) {\n // const dateToEpoch = date.getTime();\n // // The epoch is in milliseconds, but we want it to be in seconds(Like it is in the token).\n // const millisecondsToSeconds = dateToEpoch / 1000;\n // // There is no need to have anything after .\n // return Number(millisecondsToSeconds.toString().split('.')[0]);\n // }\n\n async refreshLoginState(userEmail: string, userPassword: string) {\n const response = await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/token', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: await this.readLocalCookie(),\n Origin: this.baseUrl\n },\n form:\n {\n grant_type: 'refresh_token',\n client_id: 'umbraco-back-office',\n redirect_uri: this.baseUrl + '/umbraco/oauth_complete',\n refresh_token: await this.getRefreshToken()\n },\n ignoreHTTPSErrors: true\n });\n\n if (response.status() === 200) {\n const jsonStorageCookie = response.headers()['set-cookie'];\n // We get multiple cookies, so we have to split them and then update each of the cookies in our localstorage \n let cookies = this.splitCookies(jsonStorageCookie);\n for (const cookie of cookies) {\n await this.updateCookie(cookie);\n }\n return;\n }\n console.log('Error refreshing access token.');\n return await this.updateTokenAndCookie(userEmail, userPassword);\n }\n\n private splitCookies(cookieString: string): string[] {\n return cookieString\n .trim()\n .split('\\n')\n .filter(line => line.trim())\n .filter(line => !line.includes('expires=Thu, 01 Jan 1970'));\n }\n\n async updateTokenAndCookie(userEmail: string, userPassword: string) {\n const storageStateValues = await this.login.login(userEmail, userPassword);\n await this.updateCookie(storageStateValues.cookie)\n\n // We get multiple set cookies, so we have to split them and then update each of the cookies in our localstorage \n let cookies = this.splitCookies(storageStateValues.setCookies);\n for (const cookie of cookies) {\n await this.updateCookie(cookie);\n }\n let tokens = await this.extractTokensFromSetCookie(storageStateValues.setCookies);\n\n console.log('Successfully retrieved new authentication tokens.');\n \n return {\n cookie: storageStateValues.cookie,\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n };\n }\n\n async readFileContent(filePath) {\n try {\n const jsonString = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(jsonString);\n } catch (error) {\n console.log('Error reading file:', error);\n throw error;\n }\n }\n\n async readLocalBearerToken() {\n const filePath = process.env.STORAGE_STAGE_PATH;\n if (!filePath) {\n return await this.getBearerToken();\n }\n\n try {\n const data = await JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n const localStorageItem = await this.getLocalStorageToken(data, 'umb:userAuthTokenResponse');\n const parsedValue = await JSON.parse(localStorageItem.value);\n return `Bearer ${parsedValue.access_token}`;\n } catch {\n // If the file is not found, return the current access token from the page context\n return await this.getBearerToken();\n }\n }\n\n async readLocalCookie() {\n const filePath = process.env.STORAGE_STAGE_PATH;\n if (!filePath) {\n return await this.getCookie();\n }\n\n try {\n const data = await JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return await data.cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ') + ';';\n } catch {\n // If the file is not found, return the current cookie from the page context\n return await this.getCookie();\n }\n }\n\n private async getLocalStorageToken(localStorage: any, tokenName: string) {\n return await localStorage.origins?.[0]?.localStorage?.find(item => item.name === tokenName);\n }\n\n async extractTokensFromSetCookie(setCookies: string) {\n // Extract token values from cookies\n const accessToken = setCookies.match(/__Host-umbAccessToken=([^;]+)/)?.[1] ?? \"\";\n const refreshToken = setCookies.match(/__Host-umbRefreshToken=([^;]+)/)?.[1] ?? \"\";\n return {accessToken, refreshToken};\n }\n\n private async getLocalStorageAuthToken() {\n const currentStorageState = await this.page.context().storageState();\n const currentStorageToken = await this.getLocalStorageToken(currentStorageState, 'umb:userAuthTokenResponse');\n return JSON.parse(currentStorageToken.value);\n }\n\n private async updateCookie(cookieString: string) {\n try {\n // Parse cookie string\n const parts = cookieString.split(';').map(p => p.trim());\n const [nameValue, ...attributes] = parts;\n const [name, value] = nameValue.split('=');\n const cookieName = name.trim();\n\n // Get current state\n const storageState = await this.page.context().storageState();\n const cookieIndex = storageState.cookies.findIndex(c => c.name === cookieName);\n\n if (cookieIndex === -1) {\n console.log(`Cookie \"${cookieName}\" not found`);\n return;\n }\n\n // Update cookie value\n storageState.cookies[cookieIndex].value = value;\n\n // Update expires if present\n for (const attr of attributes) {\n if (attr.toLowerCase().startsWith('expires=')) {\n const expiresDate = attr.split('=')[1];\n storageState.cookies[cookieIndex].expires = Date.parse(expiresDate) / 1000;\n }\n }\n\n // Write to file if path exists\n const filePath = process.env.STORAGE_STAGE_PATH;\n if (filePath) {\n const fs = require('fs');\n const fileData = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n\n const fileCookieIndex = fileData.cookies.findIndex(c => c.name === cookieName);\n\n if (fileCookieIndex !== -1) {\n fileData.cookies[fileCookieIndex] = storageState.cookies[cookieIndex];\n fs.writeFileSync(filePath, JSON.stringify(fileData, null, 2));\n } else {\n console.log(`Cookie \"${cookieName}\" not found in file`);\n }\n }\n } catch (error) {\n console.error('Error updating cookie:', error);\n }\n }\n\n async revokeAccessToken(cookie: string, accessToken: string) {\n return await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/revoke', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: cookie,\n Origin: this.baseUrl\n },\n form:\n {\n token: accessToken,\n token_type_hint: 'access_token',\n client_id: 'umbraco-back-office'\n },\n ignoreHTTPSErrors: true\n });\n }\n\n async revokeRefreshToken(cookie: string, refreshToken: string) {\n return await this.page.request.post(this.baseUrl + '/umbraco/management/api/v1/security/back-office/revoke', {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Cookie: cookie,\n Origin: this.baseUrl\n },\n form:\n {\n token: refreshToken,\n token_type_hint: 'refresh_token',\n client_id: 'umbraco-back-office'\n },\n ignoreHTTPSErrors: true\n });\n }\n\n async loginToAdminUser(testUserCookie: string, testUserAccessToken: string, testUserRefreshToken: string) {\n await this.revokeAccessToken(testUserCookie, testUserAccessToken);\n await this.revokeRefreshToken(testUserCookie, testUserRefreshToken);\n \n let userCookieAndTokens: { cookie: string; accessToken: string; refreshToken: string } | undefined;\n userCookieAndTokens = await this.updateTokenAndCookie(umbracoConfig.user.login, umbracoConfig.user.password);\n\n return userCookieAndTokens;\n }\n\n async getCurrentTimePlusMinute(minute: number = 1) {\n const now = new Date();\n now.setMinutes(now.getMinutes() + minute); // Add one minute\n\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const day = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n\n return `${year}-${month}-${day}T${hours}:${minutes}`;\n }\n\n async convertDateFormat(dateString: string) {\n return new Date(dateString).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n hour12: true,\n });\n }\n}"]}
|
|
@@ -853,7 +853,7 @@ class DataTypeApiHelper {
|
|
|
853
853
|
.build();
|
|
854
854
|
return await this.save(dataType);
|
|
855
855
|
}
|
|
856
|
-
async createTextstringDataType(name, maxChars =
|
|
856
|
+
async createTextstringDataType(name, maxChars = 50) {
|
|
857
857
|
await this.ensureNameNotExists(name);
|
|
858
858
|
const dataType = new json_models_builders_1.TextStringDataTypeBuilder()
|
|
859
859
|
.withName(name)
|