@alfresco/aca-playwright-shared 8.0.0-28849044572 → 8.0.0-28932229495
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.
|
@@ -2298,6 +2298,7 @@ class ActionsDropdownComponent extends BaseComponent {
|
|
|
2298
2298
|
this.ruleActionLocator = this.getChild('aca-rule-action');
|
|
2299
2299
|
this.addActionButtonLocator = this.getChild('[data-automation-id="rule-action-list-add-action-button"]');
|
|
2300
2300
|
this.actionDropdownLocator = this.getChild('[data-automation-id="rule-action-select"]');
|
|
2301
|
+
this.selectActionLocator = this.actionDropdownLocator.locator('span', { hasText: 'Select an action' });
|
|
2301
2302
|
this.actionAspectNameLocator = '[data-automation-id="header-aspect-name"] .adf-property-field';
|
|
2302
2303
|
this.actionCheckInInputLocator = '[data-automation-id="header-description"] input';
|
|
2303
2304
|
this.actionSimpleWorkflowStepInputLocator = '[data-automation-id="header-approve-step"] input';
|
|
@@ -2311,14 +2312,52 @@ class ActionsDropdownComponent extends BaseComponent {
|
|
|
2311
2312
|
this.actionTransformAndCopyContentDestinationFolderLocator = '[data-automation-id="card-textitem-value-destination-folder"]';
|
|
2312
2313
|
this.contentNodeSelectorSearchInput = '[data-automation-id="content-node-selector-search-input"]';
|
|
2313
2314
|
}
|
|
2314
|
-
async
|
|
2315
|
-
|
|
2315
|
+
async selectActions(actions) {
|
|
2316
|
+
for (const action of actions) {
|
|
2317
|
+
await this.selectSingleAction(action);
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
normalizeAction(action) {
|
|
2321
|
+
if (typeof action === 'string') {
|
|
2322
|
+
return { type: action };
|
|
2323
|
+
}
|
|
2324
|
+
return action;
|
|
2325
|
+
}
|
|
2326
|
+
async selectSingleAction(action) {
|
|
2327
|
+
const { type, value, mimeType, destinationFolder } = this.normalizeAction(action);
|
|
2328
|
+
if (await this.selectActionLocator.isHidden()) {
|
|
2316
2329
|
await this.addActionButtonLocator.click();
|
|
2317
2330
|
}
|
|
2318
|
-
await this.
|
|
2319
|
-
await this.
|
|
2320
|
-
|
|
2321
|
-
await
|
|
2331
|
+
await this.selectActionLocator.scrollIntoViewIfNeeded();
|
|
2332
|
+
await this.selectActionLocator.hover({ timeout: 1000 });
|
|
2333
|
+
await this.selectActionLocator.click();
|
|
2334
|
+
await this.getOptionLocator(type).click();
|
|
2335
|
+
const actionIndex = (await this.ruleActionLocator.count()) - 1;
|
|
2336
|
+
if (value) {
|
|
2337
|
+
await this.insertActionValues(type, value, actionIndex);
|
|
2338
|
+
}
|
|
2339
|
+
if (mimeType) {
|
|
2340
|
+
await this.selectMimeType(mimeType, actionIndex);
|
|
2341
|
+
}
|
|
2342
|
+
if (destinationFolder) {
|
|
2343
|
+
await this.selectDestinationFolderTransformAndCopyContent(actionIndex, destinationFolder);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
async insertActionValues(type, value, actionIndex) {
|
|
2347
|
+
switch (type) {
|
|
2348
|
+
case ActionType.AddAspect:
|
|
2349
|
+
await this.insertAddAspectActionValues(value, actionIndex);
|
|
2350
|
+
break;
|
|
2351
|
+
case ActionType.CheckIn:
|
|
2352
|
+
await this.insertCheckInActionValues(value, actionIndex);
|
|
2353
|
+
break;
|
|
2354
|
+
case ActionType.SpecialiseType:
|
|
2355
|
+
await this.insertSpecialiseTypeActionValues(value, actionIndex);
|
|
2356
|
+
break;
|
|
2357
|
+
case ActionType.SimpleWorkflow:
|
|
2358
|
+
await this.insertSimpleWorkflowActionValues(value, actionIndex);
|
|
2359
|
+
break;
|
|
2360
|
+
}
|
|
2322
2361
|
}
|
|
2323
2362
|
async dropdownSelection(selectValue, locator, index) {
|
|
2324
2363
|
await this.ruleActionLocator.nth(index).locator(locator).click();
|
|
@@ -2454,6 +2493,7 @@ class ConditionComponent extends ManageRulesDialogComponent {
|
|
|
2454
2493
|
await option.click();
|
|
2455
2494
|
}
|
|
2456
2495
|
async addCondition(fields, value, index, comparators) {
|
|
2496
|
+
await this.addConditionButton.first().scrollIntoViewIfNeeded();
|
|
2457
2497
|
await this.addConditionButton.first().click();
|
|
2458
2498
|
await this.selectField(fields, index);
|
|
2459
2499
|
if (comparators) {
|
|
@@ -2467,7 +2507,9 @@ class ConditionComponent extends ManageRulesDialogComponent {
|
|
|
2467
2507
|
}
|
|
2468
2508
|
}
|
|
2469
2509
|
async addConditionGroup(fields, value, index, comparators) {
|
|
2510
|
+
await this.addConditionGroupButton.last().scrollIntoViewIfNeeded();
|
|
2470
2511
|
await this.addConditionGroupButton.last().click();
|
|
2512
|
+
await this.addConditionButton.nth(index).scrollIntoViewIfNeeded();
|
|
2471
2513
|
await this.addConditionButton.nth(index).click();
|
|
2472
2514
|
await this.selectField(fields, index);
|
|
2473
2515
|
if (comparators) {
|
|
@@ -2475,6 +2517,18 @@ class ConditionComponent extends ManageRulesDialogComponent {
|
|
|
2475
2517
|
}
|
|
2476
2518
|
await this.valueField.nth(index).fill(value);
|
|
2477
2519
|
}
|
|
2520
|
+
async addConditions(conditions) {
|
|
2521
|
+
for (let i = 0; i < conditions.length; i++) {
|
|
2522
|
+
const { field, value, comparator } = conditions[i];
|
|
2523
|
+
await this.addCondition(field, value, i, comparator);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
async addConditionGroups(conditions) {
|
|
2527
|
+
for (let i = 0; i < conditions.length; i++) {
|
|
2528
|
+
const { field, value, comparator } = conditions[i];
|
|
2529
|
+
await this.addConditionGroup(field, value, i, comparator);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2478
2532
|
}
|
|
2479
2533
|
|
|
2480
2534
|
/*!
|
|
@@ -3380,7 +3434,7 @@ class Breadcrumb extends BaseComponent {
|
|
|
3380
3434
|
const itemElements = await this.page.$$('adf-breadcrumb .adf-breadcrumb-item');
|
|
3381
3435
|
const itemTexts = await Promise.all(itemElements.map(async (elem) => {
|
|
3382
3436
|
const text = await elem.innerText();
|
|
3383
|
-
return text.split('\nchevron_right')[0];
|
|
3437
|
+
return text.split('\nchevron_right')[0].trim();
|
|
3384
3438
|
}));
|
|
3385
3439
|
return itemTexts;
|
|
3386
3440
|
}
|
|
@@ -4578,7 +4632,7 @@ const getGlobalConfig = {
|
|
|
4578
4632
|
/* Retry on CI only */
|
|
4579
4633
|
retries: env.CI ? 2 : 0,
|
|
4580
4634
|
/* Opt out of parallel tests on CI. */
|
|
4581
|
-
workers: 3,
|
|
4635
|
+
workers: Number(env.PLAYWRIGHT_WORKERS) || 3,
|
|
4582
4636
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
4583
4637
|
reporter: [['list'], ...getReporter()],
|
|
4584
4638
|
globalSetup: require.resolve('./global.setup'),
|
|
@@ -4744,7 +4798,7 @@ class ApiClientFactory {
|
|
|
4744
4798
|
await this.alfrescoApi.login(user.username, user.password);
|
|
4745
4799
|
}
|
|
4746
4800
|
catch (error) {
|
|
4747
|
-
logger.error(`[API Client Factory] Log in user ${user.username} failed ${error}`);
|
|
4801
|
+
logger.error(`[API Client Factory] Log in user ${user.username} failed ${JSON.stringify(error)}`);
|
|
4748
4802
|
throw error;
|
|
4749
4803
|
}
|
|
4750
4804
|
}
|
|
@@ -4755,7 +4809,7 @@ class ApiClientFactory {
|
|
|
4755
4809
|
return await peopleApi.createPerson(person);
|
|
4756
4810
|
}
|
|
4757
4811
|
catch (error) {
|
|
4758
|
-
if (
|
|
4812
|
+
if (JSON.stringify(error).includes('409')) {
|
|
4759
4813
|
logger.warn(`[API Client Factory] createUser: user "${user.username}" already exists, skipping creation`);
|
|
4760
4814
|
return null;
|
|
4761
4815
|
}
|
|
@@ -5072,7 +5126,7 @@ class FileActionsApi {
|
|
|
5072
5126
|
return result;
|
|
5073
5127
|
}
|
|
5074
5128
|
catch (error) {
|
|
5075
|
-
logger.error(`Failed to upload file: ${fileName}: ${error}`);
|
|
5129
|
+
logger.error(`Failed to upload file: ${fileName}: ${JSON.stringify(error)}`);
|
|
5076
5130
|
return Promise.reject(error);
|
|
5077
5131
|
}
|
|
5078
5132
|
}
|
|
@@ -5169,16 +5223,10 @@ class FileActionsApi {
|
|
|
5169
5223
|
}
|
|
5170
5224
|
}
|
|
5171
5225
|
async waitForNodes(searchTerm, data) {
|
|
5172
|
-
logger.info(`waitForNodes: Waiting for ${data.expect} node(s) matching "${searchTerm}"`);
|
|
5173
5226
|
const predicate = (totalItems) => totalItems === data.expect;
|
|
5174
|
-
let pollCount = 0;
|
|
5175
5227
|
const apiCall = async () => {
|
|
5176
5228
|
try {
|
|
5177
|
-
|
|
5178
|
-
if (pollCount++ % 4 === 0) {
|
|
5179
|
-
logger.info(`waitForNodes: "${searchTerm}" — found ${totalItems}, expecting ${data.expect}`);
|
|
5180
|
-
}
|
|
5181
|
-
return totalItems;
|
|
5229
|
+
return (await this.queryNodesNames(searchTerm)).list?.pagination?.totalItems || 0;
|
|
5182
5230
|
}
|
|
5183
5231
|
catch {
|
|
5184
5232
|
return 0;
|
|
@@ -5186,6 +5234,7 @@ class FileActionsApi {
|
|
|
5186
5234
|
};
|
|
5187
5235
|
try {
|
|
5188
5236
|
await waitForApi(apiCall, predicate, 30, 2500);
|
|
5237
|
+
logger.info(`waitForNodes: Found ${data.expect} node(s) matching "${searchTerm}"`);
|
|
5189
5238
|
}
|
|
5190
5239
|
catch {
|
|
5191
5240
|
const actual = await apiCall();
|
|
@@ -5349,9 +5398,7 @@ class SharedLinksApi {
|
|
|
5349
5398
|
const sharedFiles = (await this.getSharedLinks()).list?.entries?.map((link) => link.entry.nodeId) ?? [];
|
|
5350
5399
|
const foundItems = fileIds.every((id) => sharedFiles.includes(id));
|
|
5351
5400
|
if (!foundItems) {
|
|
5352
|
-
|
|
5353
|
-
logger.error(message);
|
|
5354
|
-
throw new Error(message);
|
|
5401
|
+
throw new Error('Not all files are shared yet');
|
|
5355
5402
|
}
|
|
5356
5403
|
};
|
|
5357
5404
|
await Utils.retryCall(sharedFile);
|
|
@@ -5645,7 +5692,7 @@ class NodesApi {
|
|
|
5645
5692
|
return await this.createNode('cm:content', name, parentId, title, description, null, author, majorVersion, aspectNames);
|
|
5646
5693
|
}
|
|
5647
5694
|
catch (error) {
|
|
5648
|
-
const message = `${this.constructor.name} ${this.createFile.name}: ${error}`;
|
|
5695
|
+
const message = `${this.constructor.name} ${this.createFile.name}: ${error instanceof Error ? error.message : JSON.stringify(error)}`;
|
|
5649
5696
|
logger.error(message);
|
|
5650
5697
|
throw new Error(message);
|
|
5651
5698
|
}
|
|
@@ -5710,7 +5757,14 @@ class NodesApi {
|
|
|
5710
5757
|
});
|
|
5711
5758
|
}
|
|
5712
5759
|
catch (error) {
|
|
5713
|
-
|
|
5760
|
+
if (JSON.stringify(error).includes('409')) {
|
|
5761
|
+
logger.warn(`${this.constructor.name} ${this.createNode.name}: node "${name}" already exists in parent "${parentId}", retrieving existing node`);
|
|
5762
|
+
const existingNodeId = await this.getNodeIdFromParent(name, parentId);
|
|
5763
|
+
if (existingNodeId) {
|
|
5764
|
+
return this.getNodeById(existingNodeId);
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
const message = `${this.constructor.name} ${this.createNode.name}: ${error instanceof Error ? error.message : JSON.stringify(error)}`;
|
|
5714
5768
|
logger.error(message);
|
|
5715
5769
|
throw new Error(message);
|
|
5716
5770
|
}
|
|
@@ -6096,9 +6150,15 @@ class SitesApi {
|
|
|
6096
6150
|
return await this.apiService.sites.createSite(site);
|
|
6097
6151
|
}
|
|
6098
6152
|
catch (error) {
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6153
|
+
if (JSON.stringify(error).includes('409')) {
|
|
6154
|
+
logger.warn(`[SitesApi] createSite: site "${siteId || title}" already exists, skipping creation`);
|
|
6155
|
+
return this.getSite(siteId || title);
|
|
6156
|
+
}
|
|
6157
|
+
else {
|
|
6158
|
+
const message = `SitesApi ${this.createSite.name}: ${JSON.stringify(error)}`;
|
|
6159
|
+
logger.error(message);
|
|
6160
|
+
throw new Error(message);
|
|
6161
|
+
}
|
|
6102
6162
|
}
|
|
6103
6163
|
}
|
|
6104
6164
|
async getDocLibId(siteId) {
|
|
@@ -6267,6 +6327,116 @@ class SearchApi {
|
|
|
6267
6327
|
return new ResultSetPaging();
|
|
6268
6328
|
}
|
|
6269
6329
|
}
|
|
6330
|
+
async searchForNode(fileName, options) {
|
|
6331
|
+
const query = {
|
|
6332
|
+
query: {
|
|
6333
|
+
query: `cm:name:"${fileName}"`,
|
|
6334
|
+
language: 'afts'
|
|
6335
|
+
},
|
|
6336
|
+
include: ['path', 'allowableOperations', 'properties'],
|
|
6337
|
+
paging: {
|
|
6338
|
+
skipCount: 0,
|
|
6339
|
+
maxItems: 25
|
|
6340
|
+
},
|
|
6341
|
+
filterQueries: [
|
|
6342
|
+
{
|
|
6343
|
+
query: "+TYPE:'cm:folder' OR +TYPE:'cm:content'"
|
|
6344
|
+
},
|
|
6345
|
+
{
|
|
6346
|
+
query: "-TYPE:'cm:thumbnail' AND -TYPE:'cm:failedThumbnail' AND -TYPE:'cm:rating'"
|
|
6347
|
+
},
|
|
6348
|
+
{
|
|
6349
|
+
query: '-cm:creator:System'
|
|
6350
|
+
},
|
|
6351
|
+
{
|
|
6352
|
+
query: "-TYPE:'st:site' AND -ASPECT:'st:siteContainer' AND -ASPECT:'sys:hidden'"
|
|
6353
|
+
},
|
|
6354
|
+
{
|
|
6355
|
+
query: "-TYPE:'dl:dataList' AND -TYPE:'dl:todoList' AND -TYPE:'dl:issue'"
|
|
6356
|
+
},
|
|
6357
|
+
{
|
|
6358
|
+
query: "-TYPE:'fm:topic' AND -TYPE:'fm:post'"
|
|
6359
|
+
},
|
|
6360
|
+
{
|
|
6361
|
+
query: "-TYPE:'lnk:link'"
|
|
6362
|
+
},
|
|
6363
|
+
{
|
|
6364
|
+
query: "-PATH:'//cm:wiki/*'"
|
|
6365
|
+
},
|
|
6366
|
+
{
|
|
6367
|
+
query: "+TYPE:'cm:content'"
|
|
6368
|
+
}
|
|
6369
|
+
],
|
|
6370
|
+
facetQueries: undefined,
|
|
6371
|
+
facetIntervals: undefined,
|
|
6372
|
+
facetFields: {
|
|
6373
|
+
facets: [
|
|
6374
|
+
{
|
|
6375
|
+
field: 'creator',
|
|
6376
|
+
mincount: 1,
|
|
6377
|
+
label: 'SEARCH.FACET_FIELDS.CREATOR'
|
|
6378
|
+
},
|
|
6379
|
+
{
|
|
6380
|
+
field: 'modifier',
|
|
6381
|
+
mincount: 1,
|
|
6382
|
+
label: 'SEARCH.FACET_FIELDS.MODIFIER'
|
|
6383
|
+
}
|
|
6384
|
+
]
|
|
6385
|
+
},
|
|
6386
|
+
sort: [
|
|
6387
|
+
{
|
|
6388
|
+
type: 'SCORE',
|
|
6389
|
+
field: 'score',
|
|
6390
|
+
ascending: false
|
|
6391
|
+
}
|
|
6392
|
+
],
|
|
6393
|
+
highlight: {
|
|
6394
|
+
prefix: "<span class='aca-highlight'>",
|
|
6395
|
+
postfix: '</span>',
|
|
6396
|
+
fields: [
|
|
6397
|
+
{
|
|
6398
|
+
field: 'cm:title'
|
|
6399
|
+
},
|
|
6400
|
+
{
|
|
6401
|
+
field: 'cm:name'
|
|
6402
|
+
},
|
|
6403
|
+
{
|
|
6404
|
+
field: 'cm:description',
|
|
6405
|
+
snippetCount: 1
|
|
6406
|
+
},
|
|
6407
|
+
{
|
|
6408
|
+
field: 'cm:content',
|
|
6409
|
+
snippetCount: 1
|
|
6410
|
+
}
|
|
6411
|
+
]
|
|
6412
|
+
},
|
|
6413
|
+
facetFormat: 'V2'
|
|
6414
|
+
};
|
|
6415
|
+
let result;
|
|
6416
|
+
let retryCount = 0;
|
|
6417
|
+
const retryLimit = options?.maxRetries ?? 90;
|
|
6418
|
+
do {
|
|
6419
|
+
try {
|
|
6420
|
+
result = await this.apiService.search.search(query);
|
|
6421
|
+
}
|
|
6422
|
+
catch {
|
|
6423
|
+
result = new ResultSetPaging();
|
|
6424
|
+
}
|
|
6425
|
+
if ((result.list?.entries?.length ?? 0) === 0) {
|
|
6426
|
+
retryCount++;
|
|
6427
|
+
if (retryCount % 10 === 0) {
|
|
6428
|
+
logger.info(`searchForNode: Still waiting for file "${fileName}" after ${retryCount} retries (max ${retryLimit}).`);
|
|
6429
|
+
}
|
|
6430
|
+
if (retryCount >= retryLimit) {
|
|
6431
|
+
logger.error(`searchForNode: File "${fileName}" not found after ${retryLimit} retries.`);
|
|
6432
|
+
throw new Error(`File with name ${fileName} not found after ${retryLimit} retries`);
|
|
6433
|
+
}
|
|
6434
|
+
await Utils.delayInSeconds(1);
|
|
6435
|
+
}
|
|
6436
|
+
} while ((result.list?.entries?.length ?? 0) === 0);
|
|
6437
|
+
logger.info(`searchForNode: Search succeeded for file "${fileName}"`);
|
|
6438
|
+
return result;
|
|
6439
|
+
}
|
|
6270
6440
|
async getTotalItems(username) {
|
|
6271
6441
|
return (await this.querySearchFiles(username)).list?.pagination?.totalItems ?? 0;
|
|
6272
6442
|
}
|
|
@@ -6316,8 +6486,24 @@ class SearchApi {
|
|
|
6316
6486
|
return result.list?.pagination?.count ?? 0;
|
|
6317
6487
|
}
|
|
6318
6488
|
catch (error) {
|
|
6319
|
-
|
|
6320
|
-
|
|
6489
|
+
const errorMessage = `waitForFolderPathIndexing failed for folderId "${folderId}": ${JSON.stringify(error)}`;
|
|
6490
|
+
logger.error(errorMessage);
|
|
6491
|
+
throw new Error(errorMessage);
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
async waitFileForSearchIndexing(fileName, maxRetries) {
|
|
6495
|
+
try {
|
|
6496
|
+
const result = await this.searchForNode(fileName, { maxRetries: maxRetries });
|
|
6497
|
+
const entryNames = (result.list?.entries ?? []).map((entry) => entry.entry?.name).filter((name) => Boolean(name));
|
|
6498
|
+
if (!entryNames.includes(fileName)) {
|
|
6499
|
+
throw new Error(`File "${fileName}" not found in search results. Found: [${entryNames.join(', ')}]`);
|
|
6500
|
+
}
|
|
6501
|
+
logger.info(`waitFileForSearchIndexing: File "${fileName}" is indexed.`);
|
|
6502
|
+
}
|
|
6503
|
+
catch (error) {
|
|
6504
|
+
const errorMessage = `waitFileForSearchIndexing failed for file "${fileName}": ${JSON.stringify(error)}`;
|
|
6505
|
+
logger.error(errorMessage);
|
|
6506
|
+
throw new Error(errorMessage);
|
|
6321
6507
|
}
|
|
6322
6508
|
}
|
|
6323
6509
|
}
|