@zohodesk/testinglibrary 0.4.93-n18-experimental → 0.4.95-n18-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/.gitlab-ci.yml +15 -0
- package/README.md +12 -2
- package/build/common/data-generator/steps/DataGenerator.spec.js +4 -4
- package/build/common/data-generator/steps/DataGeneratorStepsHelper.js +4 -2
- package/build/common/searchFake/helpers/rpcRequestHelper.js +14 -3
- package/build/common/searchFake/steps/searchFake.spec.js +52 -1
- package/build/core/dataGenerator/DataGenerator.js +0 -9
- package/build/core/playwright/helpers/auth/index.js +7 -0
- package/build/core/playwright/readConfigFile.js +0 -1
- package/build/core/playwright/setup/config-creator.js +51 -24
- package/build/test/Test.js +13 -0
- package/npm-shrinkwrap.json +282 -232
- package/package.json +1 -2
- package/build/core/playwright/setup/Project.js +0 -35
- package/build/core/playwright/setup/ProjectConfiguration.js +0 -80
package/.gitlab-ci.yml
CHANGED
|
@@ -188,4 +188,19 @@ uat-data_generator:
|
|
|
188
188
|
paths:
|
|
189
189
|
- examples/uat/playwright-report
|
|
190
190
|
|
|
191
|
+
uat-search_indexing:
|
|
192
|
+
stage: uat
|
|
193
|
+
script:
|
|
194
|
+
- cd examples
|
|
195
|
+
- npm install $(npm pack ../../testing-framework | tail -1)
|
|
196
|
+
- output=$(npm run uat-search_indexing)
|
|
197
|
+
- echo "$output"
|
|
198
|
+
- node ../ValidateUATReport.js examples
|
|
199
|
+
|
|
200
|
+
artifacts:
|
|
201
|
+
when: always
|
|
202
|
+
paths:
|
|
203
|
+
- examples/uat/playwright-report
|
|
204
|
+
|
|
205
|
+
|
|
191
206
|
|
package/README.md
CHANGED
|
@@ -19,8 +19,18 @@
|
|
|
19
19
|
|
|
20
20
|
## Version History
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
### Unpublished release
|
|
23
|
+
|
|
24
|
+
### Feature
|
|
25
|
+
|
|
26
|
+
- New step `a search entity using {string}` provided for search indexing, This step will use run time data generation response as input for the indexing
|
|
27
|
+
|
|
28
|
+
### v3.2.9 - 26-09-2025
|
|
29
|
+
|
|
30
|
+
### Enhancement
|
|
31
|
+
|
|
32
|
+
- Authentication deatils for data generation can be configured in org level
|
|
33
|
+
- reference link : https://learn.zoho.in/portal/zohocorp/knowledge/manual/client-uat/article/data-generation#_Tocpd3n7yt9ngeg
|
|
24
34
|
|
|
25
35
|
### v3.2.8 - 18-09-2025
|
|
26
36
|
|
|
@@ -10,10 +10,10 @@ Given('generate a {string} entity {string} with generator {string}', async ({ pa
|
|
|
10
10
|
Given('generate a {string} entity {string} with API {string}', async ({ page, context, i18N, cacheLayer, executionContext}, module, entityName, operationId, dataTable) => {
|
|
11
11
|
await generateAndCacheTestData(executionContext, "API", operationId, dataTable, cacheLayer, entityName);
|
|
12
12
|
});
|
|
13
|
-
Given('generate a {string} entity {string} with generator {string} using {string} profile', async ({ page, context, i18N, cacheLayer, executionContext}, module, entityName, generatorName, profile, dataTable) => {
|
|
14
|
-
await generateAndCacheTestData(executionContext, "template", generatorName, dataTable, cacheLayer, entityName, profile);
|
|
13
|
+
Given('generate a {string} entity {string} with generator {string} using {string} profile', async ({ $tags, page, context, i18N, cacheLayer, executionContext}, module, entityName, generatorName, profile, dataTable) => {
|
|
14
|
+
await generateAndCacheTestData(executionContext, "template", generatorName, dataTable, cacheLayer, entityName, profile,$tags);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
Given('generate a {string} entity {string} with API {string} using {string} profile', async ({ page, context, i18N, cacheLayer, executionContext}, module, entityName, operationId, profile, dataTable) => {
|
|
18
|
-
await generateAndCacheTestData(executionContext, "API", operationId, dataTable, cacheLayer, entityName, profile);
|
|
17
|
+
Given('generate a {string} entity {string} with API {string} using {string} profile', async ({ $tags,page, context, i18N, cacheLayer, executionContext}, module, entityName, operationId, profile, dataTable) => {
|
|
18
|
+
await generateAndCacheTestData(executionContext, "API", operationId, dataTable, cacheLayer, entityName, profile, $tags);
|
|
19
19
|
});
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { test } from '@zohodesk/testinglibrary';
|
|
2
2
|
import DataGenerator from '@zohodesk/testinglibrary/DataGenerator';
|
|
3
|
+
import {extractTagInfo, getUserForSelectedEditionAndProfile} from '@zohodesk/testinglibrary/helpers'
|
|
3
4
|
|
|
4
5
|
const dataGenerator = new DataGenerator();
|
|
5
6
|
|
|
6
|
-
export async function generateAndCacheTestData(executionContext, type, identifier, dataTable, cacheLayer, entityName, profile = null) {
|
|
7
|
+
export async function generateAndCacheTestData(executionContext, type, identifier, dataTable, cacheLayer, entityName, profile = null, tags = null) {
|
|
7
8
|
let actorInfo;
|
|
8
9
|
const testInfo = test.info();
|
|
9
10
|
const scenarioName = testInfo.title.split('/').pop() || 'Unknown Scenario';
|
|
10
11
|
|
|
11
12
|
if (profile) {
|
|
12
|
-
|
|
13
|
+
const { portalInfo, betaFeature } = extractTagInfo(tags);
|
|
14
|
+
actorInfo = await getUserForSelectedEditionAndProfile(executionContext.actorInfo.edition, profile ,betaFeature, portalInfo)
|
|
13
15
|
} else {
|
|
14
16
|
actorInfo = executionContext.actorInfo;
|
|
15
17
|
}
|
|
@@ -30,11 +30,22 @@ async function entityIdReConstructor(payload) {
|
|
|
30
30
|
if (typeof payload !== 'object' || payload === null) {
|
|
31
31
|
throw new Error('Invalid payload. It must be a non-null object.');
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
|
|
34
|
+
if (!payload.arguments || (!payload.arguments.entityId)) {
|
|
35
|
+
throw new Error('Invalid payload.arguments.entityId. It must be a non-empty string or array of strings.');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const entityId = payload.arguments.entityId;
|
|
39
|
+
|
|
40
|
+
// If it's already an array, validate and clean it
|
|
41
|
+
if (Array.isArray(entityId)) {
|
|
42
|
+
payload.arguments.entityId = entityId.map(id => id.trim());
|
|
43
|
+
}
|
|
44
|
+
// If it's a string, split and convert to array
|
|
45
|
+
else if (typeof entityId === 'string') {
|
|
46
|
+
payload.arguments.entityId = entityId.split(',').map(id => id.trim());
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
payload.arguments.entityId = payload.arguments.entityId.split(',').map(id => id.trim());
|
|
38
49
|
return payload;
|
|
39
50
|
}
|
|
40
51
|
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import {createBdd } from '@zohodesk/testinglibrary';
|
|
2
2
|
import { executeRpcRequest , entityIdReConstructor } from '../helpers/rpcRequestHelper';
|
|
3
|
+
import jp from 'jsonpath';
|
|
3
4
|
|
|
4
5
|
const { Given } = createBdd();
|
|
5
6
|
|
|
7
|
+
|
|
8
|
+
// Given a search entity
|
|
9
|
+
// | moduleName | entityId | entityName | searchString |
|
|
10
|
+
// | contact | 122000006785675, 122000007141665, 122000006636472 | QA Team | testinguat |
|
|
11
|
+
|
|
6
12
|
Given('a search entity', async ({page}, dataTable)=>{
|
|
7
13
|
const data = dataTable.hashes();
|
|
8
14
|
|
|
@@ -22,5 +28,50 @@ Given('a search entity', async ({page}, dataTable)=>{
|
|
|
22
28
|
|
|
23
29
|
await executeRpcRequest(page, payload);
|
|
24
30
|
}
|
|
25
|
-
|
|
26
31
|
});
|
|
32
|
+
|
|
33
|
+
// Given data generation step
|
|
34
|
+
// Given a search entity using "C1"
|
|
35
|
+
// | moduleName | searchString | searchEntity (response of the previous data generation step) |
|
|
36
|
+
// | contact | testinguat | $.id |
|
|
37
|
+
// | contact | testinguat | $.ids |
|
|
38
|
+
// | contact | testinguat |
|
|
39
|
+
|
|
40
|
+
Given('a search entity using {string}', async ({page,cacheLayer}, reference,dataTable)=>{
|
|
41
|
+
const data = dataTable.hashes();
|
|
42
|
+
|
|
43
|
+
const row = data[0];
|
|
44
|
+
if (!row || !row.moduleName || !row.searchString) {
|
|
45
|
+
throw new Error('Invalid or missing data in dataTable');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { moduleName, searchEntity, searchString } = row;
|
|
49
|
+
|
|
50
|
+
const searchObj = cacheLayer.get(reference);
|
|
51
|
+
let entityIdValue;
|
|
52
|
+
|
|
53
|
+
if (typeof searchObj === 'string') {
|
|
54
|
+
entityIdValue = searchObj;
|
|
55
|
+
} else {
|
|
56
|
+
const jsonPath = searchEntity?.startsWith?.('$') ? searchEntity : `$.${searchEntity}`;
|
|
57
|
+
const result = jp.query(searchObj, jsonPath);
|
|
58
|
+
|
|
59
|
+
if (!result || result.length === 0) {
|
|
60
|
+
throw new Error(`JSONPath query '${jsonPath}' returned no results from cache object for reference: ${reference}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
entityIdValue = result.length === 1 ? result[0] : result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const payload = {
|
|
67
|
+
className: 'applicationDriver.rpc.desk.integrations.search.SearchFakeDataPopulator',
|
|
68
|
+
methodName: 'populateSearchData',
|
|
69
|
+
arguments: {
|
|
70
|
+
module: moduleName,
|
|
71
|
+
searchString: searchString,
|
|
72
|
+
entityId: entityIdValue
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
await entityIdReConstructor(payload);
|
|
76
|
+
await executeRpcRequest(page, payload);
|
|
77
|
+
});
|
|
@@ -47,15 +47,6 @@ class DataGenerator {
|
|
|
47
47
|
throw error;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
async getDataGenUserExecutionContext(edition, profile) {
|
|
51
|
-
try {
|
|
52
|
-
const dataGenUserDetails = await (0, _helpers.getUserForSelectedEditionAndProfile)(edition, profile);
|
|
53
|
-
return dataGenUserDetails;
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error('Error occurred while fetching data generation user details: ', error);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
50
|
}
|
|
60
51
|
async function _getGenerator(testInfo, generatorName) {
|
|
61
52
|
let generator = null;
|
|
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "accountLogin", {
|
|
|
10
10
|
return _accountLogin.default;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
+
Object.defineProperty(exports, "extractTagInfo", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _customFixturesHelper.extractTagInfo;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
13
19
|
Object.defineProperty(exports, "getDefaultActor", {
|
|
14
20
|
enumerable: true,
|
|
15
21
|
get: function () {
|
|
@@ -73,4 +79,5 @@ Object.defineProperty(exports, "verifyIfCookieFileExists", {
|
|
|
73
79
|
var _accountLogin = _interopRequireDefault(require("./accountLogin"));
|
|
74
80
|
var _checkAuthCookies = require("./checkAuthCookies");
|
|
75
81
|
var _getUsers = require("./getUsers");
|
|
82
|
+
var _customFixturesHelper = require("../customFixturesHelper");
|
|
76
83
|
var _loginSteps = _interopRequireDefault(require("./loginSteps"));
|
|
@@ -19,7 +19,6 @@ var _ConfigurationHelper = require("./configuration/ConfigurationHelper");
|
|
|
19
19
|
let cachedConfig = null;
|
|
20
20
|
function getDefaultConfig() {
|
|
21
21
|
return {
|
|
22
|
-
isTearDown: true,
|
|
23
22
|
uatDirectory: _path.default.join(process.cwd(), 'uat'),
|
|
24
23
|
headless: false,
|
|
25
24
|
browsers: ['Chrome'],
|
|
@@ -9,36 +9,47 @@ var _test = require("@playwright/test");
|
|
|
9
9
|
var _path = _interopRequireDefault(require("path"));
|
|
10
10
|
var _readConfigFile = require("../readConfigFile");
|
|
11
11
|
var _configUtils = require("./config-utils");
|
|
12
|
-
var _ProjectConfiguration = require("./ProjectConfiguration");
|
|
13
12
|
const uatConfig = (0, _readConfigFile.generateConfigFromFile)();
|
|
14
13
|
const {
|
|
15
|
-
bddMode,
|
|
16
14
|
browsers,
|
|
17
15
|
isSmokeTest,
|
|
18
|
-
|
|
16
|
+
trace,
|
|
17
|
+
video,
|
|
19
18
|
isAuthMode,
|
|
20
19
|
openReportOn,
|
|
21
20
|
reportPath,
|
|
21
|
+
bddMode,
|
|
22
22
|
expectTimeout,
|
|
23
23
|
testTimeout,
|
|
24
24
|
authFilePath,
|
|
25
25
|
viewport,
|
|
26
|
+
featureFilesFolder,
|
|
27
|
+
stepDefinitionsFolder,
|
|
28
|
+
testIdAttribute,
|
|
26
29
|
globalTimeout,
|
|
27
|
-
customReporter
|
|
28
|
-
trace,
|
|
29
|
-
video,
|
|
30
|
-
testIdAttribute
|
|
30
|
+
customReporter
|
|
31
31
|
} = uatConfig;
|
|
32
32
|
const projects = (0, _configUtils.getProjects)({
|
|
33
33
|
browsers,
|
|
34
34
|
isAuthMode,
|
|
35
35
|
isSmokeTest,
|
|
36
|
-
isTearDown,
|
|
37
36
|
authFilePath,
|
|
38
37
|
expectTimeout,
|
|
39
38
|
testTimeout,
|
|
40
39
|
viewport
|
|
41
40
|
});
|
|
41
|
+
const testDir = (0, _configUtils.getTestDir)(bddMode, {
|
|
42
|
+
featureFilesFolder: (0, _configUtils.getPathsForFeatureFiles)(process.cwd()),
|
|
43
|
+
stepDefinitionsFolder: _path.default.join(process.cwd(), 'uat', '**', 'steps', '*.spec.js'),
|
|
44
|
+
outputDir: _path.default.join(process.cwd(), 'uat', '.features-gen'),
|
|
45
|
+
uatPath: _path.default.join(process.cwd(), 'uat')
|
|
46
|
+
});
|
|
47
|
+
const use = {
|
|
48
|
+
trace,
|
|
49
|
+
video,
|
|
50
|
+
viewport,
|
|
51
|
+
testIdAttribute
|
|
52
|
+
};
|
|
42
53
|
let reporter = [['html', {
|
|
43
54
|
outputFolder: reportPath,
|
|
44
55
|
open: openReportOn
|
|
@@ -55,22 +66,29 @@ if (customReporter) {
|
|
|
55
66
|
* @returns {import('@playwright/test').PlaywrightTestConfig}
|
|
56
67
|
*/
|
|
57
68
|
|
|
58
|
-
const use = {
|
|
59
|
-
trace,
|
|
60
|
-
video,
|
|
61
|
-
viewport,
|
|
62
|
-
testIdAttribute
|
|
63
|
-
};
|
|
64
|
-
const testDir = (0, _configUtils.getTestDir)(bddMode, {
|
|
65
|
-
featureFilesFolder: (0, _configUtils.getPathsForFeatureFiles)(process.cwd()),
|
|
66
|
-
stepDefinitionsFolder: _path.default.join(process.cwd(), 'uat', '**', 'steps', '*.spec.js'),
|
|
67
|
-
outputDir: _path.default.join(process.cwd(), 'uat', '.features-gen'),
|
|
68
|
-
uatPath: _path.default.join(process.cwd(), 'uat')
|
|
69
|
-
});
|
|
70
69
|
function getPlaywrightConfig() {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
const commonConfig = {
|
|
71
|
+
storageState: isAuthMode ? (0, _readConfigFile.getAuthFilePath)(_path.default.resolve(process.cwd(), authFilePath)) : {}
|
|
72
|
+
};
|
|
73
|
+
const dependencies = isAuthMode ? ['setup'] : [];
|
|
74
|
+
const smokeTestProject = isSmokeTest ? smokeTestConfig() : [];
|
|
75
|
+
function smokeTestConfig() {
|
|
76
|
+
const smokeTestDir = (0, _configUtils.getTestDir)(bddMode, {
|
|
77
|
+
featureFilesFolder: _path.default.join(process.cwd(), 'uat', 'smokeTest', '**', '*.feature'),
|
|
78
|
+
stepDefinitionsFolder: _path.default.join(process.cwd(), 'uat', '**', 'steps', '*.spec.js'),
|
|
79
|
+
outputDir: _path.default.join(process.cwd(), 'uat', '.features-smoke-gen'),
|
|
80
|
+
uatPath: _path.default.join(process.cwd(), 'uat', 'smokeTest')
|
|
81
|
+
});
|
|
82
|
+
return [{
|
|
83
|
+
name: 'smokeTest',
|
|
84
|
+
testDir: smokeTestDir,
|
|
85
|
+
use: {
|
|
86
|
+
...commonConfig
|
|
87
|
+
},
|
|
88
|
+
dependencies: dependencies,
|
|
89
|
+
retries: 0
|
|
90
|
+
}];
|
|
91
|
+
}
|
|
74
92
|
const playwrightConfig = {
|
|
75
93
|
testDir,
|
|
76
94
|
globalTimeout: globalTimeout || 3600000,
|
|
@@ -82,7 +100,16 @@ function getPlaywrightConfig() {
|
|
|
82
100
|
timeout: expectTimeout
|
|
83
101
|
},
|
|
84
102
|
use,
|
|
85
|
-
projects:
|
|
103
|
+
projects: isAuthMode ? [{
|
|
104
|
+
name: 'setup',
|
|
105
|
+
testMatch: /.*\.setup\.js/,
|
|
106
|
+
testDir: _path.default.join(process.cwd(), 'uat'),
|
|
107
|
+
teardown: 'cleanup'
|
|
108
|
+
}, ...smokeTestProject, {
|
|
109
|
+
name: 'cleanup',
|
|
110
|
+
testMatch: /.*\.teardown\.js/,
|
|
111
|
+
testDir: _path.default.join(process.cwd(), 'uat')
|
|
112
|
+
}, ...projects] : [...projects, ...smokeTestProject],
|
|
86
113
|
...uatConfig
|
|
87
114
|
};
|
|
88
115
|
return playwrightConfig;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
delete require.cache[require.resolve('../core/playwright/runner/Runner')];
|
|
4
|
+
function test() {
|
|
5
|
+
const inputString = "@hc";
|
|
6
|
+
const selectedTag = ["@hc_1234"].reverse().find(tag => tag.startsWith(inputString));
|
|
7
|
+
let tagInput = null;
|
|
8
|
+
if (selectedTag) {
|
|
9
|
+
tagInput = selectedTag.split(`${inputString}_`).pop().toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
console.log(tagInput);
|
|
12
|
+
}
|
|
13
|
+
test();
|