@zohodesk/testinglibrary 0.0.5 → 0.0.6

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.
Files changed (111) hide show
  1. package/.babelrc +19 -0
  2. package/.eslintrc.js +27 -0
  3. package/.prettierrc +6 -0
  4. package/{changelog.md → Changelog.md} +38 -25
  5. package/README.md +17 -17
  6. package/bin/cli.js +2 -2
  7. package/bin/postinstall.js +1 -16
  8. package/build/bdd-framework/cli/commands/env.js +43 -0
  9. package/build/bdd-framework/cli/commands/export.js +48 -0
  10. package/build/bdd-framework/cli/commands/test.js +59 -0
  11. package/build/bdd-framework/cli/index.js +11 -0
  12. package/build/bdd-framework/cli/options.js +20 -0
  13. package/build/bdd-framework/cli/worker.js +13 -0
  14. package/build/bdd-framework/config/dir.js +27 -0
  15. package/build/bdd-framework/config/env.js +49 -0
  16. package/build/bdd-framework/config/index.js +91 -0
  17. package/build/bdd-framework/cucumber/buildStepDefinition.js +43 -0
  18. package/build/bdd-framework/cucumber/gherkin.d.js +5 -0
  19. package/build/bdd-framework/cucumber/gherkin.d.ts +45 -0
  20. package/build/bdd-framework/cucumber/loadConfig.js +17 -0
  21. package/build/bdd-framework/cucumber/loadFeatures.js +39 -0
  22. package/build/bdd-framework/cucumber/loadSnippetBuilder.js +20 -0
  23. package/build/bdd-framework/cucumber/loadSources.js +57 -0
  24. package/build/bdd-framework/cucumber/loadSteps.js +35 -0
  25. package/build/bdd-framework/decorators.js +22 -0
  26. package/build/bdd-framework/gen/formatter.js +88 -0
  27. package/build/bdd-framework/gen/i18n.js +35 -0
  28. package/build/bdd-framework/gen/index.js +160 -0
  29. package/build/bdd-framework/gen/poms.js +46 -0
  30. package/build/bdd-framework/gen/testFile.js +356 -0
  31. package/build/bdd-framework/gen/testNode.js +48 -0
  32. package/build/bdd-framework/gen/testPoms.js +123 -0
  33. package/build/bdd-framework/index.js +45 -0
  34. package/build/bdd-framework/playwright/fixtureParameterNames.js +77 -0
  35. package/build/bdd-framework/playwright/getLocationInFile.js +46 -0
  36. package/build/bdd-framework/playwright/loadConfig.js +42 -0
  37. package/build/bdd-framework/playwright/testTypeImpl.js +41 -0
  38. package/build/bdd-framework/playwright/transform.js +80 -0
  39. package/build/bdd-framework/playwright/types.js +5 -0
  40. package/build/bdd-framework/playwright/utils.js +34 -0
  41. package/build/bdd-framework/run/bddFixtures.js +108 -0
  42. package/build/bdd-framework/run/bddWorld.js +87 -0
  43. package/build/bdd-framework/snippets/index.js +131 -0
  44. package/build/bdd-framework/snippets/snippetSyntax.js +41 -0
  45. package/build/bdd-framework/snippets/snippetSyntaxDecorators.js +26 -0
  46. package/build/bdd-framework/snippets/snippetSyntaxTs.js +18 -0
  47. package/build/bdd-framework/stepDefinitions/createBdd.js +49 -0
  48. package/build/bdd-framework/stepDefinitions/createDecorators.js +109 -0
  49. package/build/bdd-framework/stepDefinitions/decorators/poms.js +50 -0
  50. package/build/bdd-framework/stepDefinitions/decorators/steps.js +94 -0
  51. package/build/bdd-framework/stepDefinitions/defineStep.js +61 -0
  52. package/build/bdd-framework/stepDefinitions/stepConfig.js +24 -0
  53. package/build/bdd-framework/utils/index.js +50 -0
  54. package/build/bdd-framework/utils/jsStringWrap.js +44 -0
  55. package/build/bdd-framework/utils/logger.js +29 -0
  56. package/build/core/jest/preprocessor/jsPreprocessor.js +13 -0
  57. package/{src → build}/core/jest/runner/jest-runner.js +46 -44
  58. package/build/core/jest/setup/index.js +9 -0
  59. package/build/core/playwright/codegen.js +55 -0
  60. package/build/core/playwright/custom-commands.js +8 -0
  61. package/build/core/playwright/env-initializer.js +21 -0
  62. package/{src → build}/core/playwright/index.js +112 -82
  63. package/build/core/playwright/readConfigFile.js +69 -0
  64. package/build/core/playwright/report-generator.js +41 -0
  65. package/build/core/playwright/setup/config-creator.js +117 -0
  66. package/build/core/playwright/test-runner.js +132 -0
  67. package/build/decorators.d.ts +1 -0
  68. package/build/decorators.js +16 -0
  69. package/build/index.d.ts +5 -0
  70. package/build/index.js +59 -0
  71. package/build/lib/cli.js +54 -0
  72. package/build/lib/post-install.js +17 -0
  73. package/build/lint/index.js +4 -0
  74. package/build/parser/parser.js +206 -0
  75. package/build/parser/sample.feature +34 -0
  76. package/build/parser/sample.spec.js +37 -0
  77. package/build/parser/verifier.js +130 -0
  78. package/build/setup-folder-structure/samples/auth-setup-sample.js +72 -0
  79. package/build/setup-folder-structure/samples/authUsers-sample.json +9 -0
  80. package/build/setup-folder-structure/samples/env-config-sample.json +21 -0
  81. package/build/setup-folder-structure/samples/git-ignore.sample.js +33 -0
  82. package/build/setup-folder-structure/samples/uat-config-sample.js +35 -0
  83. package/build/setup-folder-structure/setupProject.js +100 -0
  84. package/{src → build}/utils/cliArgsToObject.js +65 -63
  85. package/build/utils/fileUtils.js +53 -0
  86. package/build/utils/getFilePath.js +11 -0
  87. package/build/utils/logger.js +58 -0
  88. package/build/utils/rootPath.js +46 -0
  89. package/build/utils/stepDefinitionsFormatter.js +12 -0
  90. package/jest.config.js +63 -63
  91. package/npm-shrinkwrap.json +8790 -5772
  92. package/package.json +51 -30
  93. package/playwright.config.js +112 -112
  94. package/src/core/jest/preprocessor/jsPreprocessor.js +0 -9
  95. package/src/core/jest/setup/index.js +0 -165
  96. package/src/core/playwright/codegen.js +0 -60
  97. package/src/core/playwright/custom-commands.js +0 -3
  98. package/src/core/playwright/env-initializer.js +0 -24
  99. package/src/core/playwright/readConfigFile.js +0 -63
  100. package/src/core/playwright/report-generator.js +0 -45
  101. package/src/core/playwright/setup/config-creator.js +0 -77
  102. package/src/core/playwright/test-runner.js +0 -67
  103. package/src/index.js +0 -9
  104. package/src/lib/cli.js +0 -42
  105. package/src/setup-folder-structure/env-config-sample.json +0 -17
  106. package/src/setup-folder-structure/setupProject.js +0 -99
  107. package/src/setup-folder-structure/uat-config-sample.js +0 -22
  108. package/src/setup-folder-structure/user-example.json +0 -3
  109. package/src/utils/getFilePath.js +0 -9
  110. package/src/utils/logger.js +0 -28
  111. package/src/utils/rootPath.js +0 -51
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _testRunner = _interopRequireDefault(require("../core/playwright/test-runner"));
5
+ var _reportGenerator = _interopRequireDefault(require("../core/playwright/report-generator"));
6
+ var _codegen = _interopRequireDefault(require("../core/playwright/codegen"));
7
+ var _logger = require("../utils/logger");
8
+ var _setupProject = _interopRequireDefault(require("../setup-folder-structure/setupProject"));
9
+ var _parser = require("../parser/parser");
10
+ // import createJestRunner from '../core/jest/runner/jest-runner';
11
+
12
+ const [,, option, ...otherOptions] = process.argv;
13
+ // const args = process.argv.slice(3);
14
+ // const appPath = process.cwd();
15
+
16
+ switch (option) {
17
+ case 'test':
18
+ {
19
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Running Tests..');
20
+ (0, _testRunner.default)();
21
+ //createJestRunner();
22
+ break;
23
+ }
24
+ case 'report':
25
+ {
26
+ // console.log('\x1b[36mGenerating Reports...\x1b[0m');
27
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Generating Reports...');
28
+ (0, _reportGenerator.default)();
29
+ break;
30
+ }
31
+ case 'codegen':
32
+ {
33
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, 'The purpose of codegen is to assist developer .....');
34
+ (0, _codegen.default)();
35
+ break;
36
+ }
37
+ case 'init':
38
+ {
39
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Initializing projects...');
40
+ (0, _setupProject.default)();
41
+ break;
42
+ }
43
+ case 'generateSpecFile':
44
+ {
45
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Generating Spec file...');
46
+ (0, _parser.generateSpecCodeForFeatureFile)(otherOptions);
47
+ break;
48
+ }
49
+ default:
50
+ {
51
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Supported Commands test and report');
52
+ break;
53
+ }
54
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _path = _interopRequireDefault(require("path"));
5
+ var _child_process = require("child_process");
6
+ var _logger = require("../utils/logger");
7
+ var _getFilePath = _interopRequireDefault(require("../utils/getFilePath"));
8
+ const playwrightPath = _path.default.resolve('node_modules', '.bin', (0, _getFilePath.default)('playwright'));
9
+ const command = playwrightPath;
10
+ const args = ['install'];
11
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, 'Downloading browsers for running tests');
12
+ const childProcess = (0, _child_process.spawn)(command, args, {
13
+ stdio: 'inherit'
14
+ });
15
+ childProcess.on('error', error => {
16
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, error);
17
+ });
@@ -0,0 +1,4 @@
1
+ // const { parse, Document } = require('gherkin-io');
2
+
3
+ // const document = await parse("Feature: Test\n...", "./features/test.feature");
4
+ "use strict";
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.generateSpecCodeForFeatureFile = generateSpecCodeForFeatureFile;
8
+ exports.parseFeature = parseFeature;
9
+ exports.specFileGenerator = specFileGenerator;
10
+ var _fs = _interopRequireDefault(require("fs"));
11
+ var _path = _interopRequireDefault(require("path"));
12
+ var _logger = require("../utils/logger");
13
+ var _cliArgsToObject = require("../utils/cliArgsToObject");
14
+ var _fileUtils = require("../utils/fileUtils");
15
+ var _readConfigFile = require("../core/playwright/readConfigFile");
16
+ var _stepDefinitionsFormatter = require("../utils/stepDefinitionsFormatter");
17
+ function parseFeature(featureContent) {
18
+ const lines = featureContent.split('\n');
19
+ let currentFeature = null;
20
+ let currentScenario = null;
21
+ let insideExampleTable = false;
22
+ let isHeaderRow = false; // To skip the first row in the Examples section
23
+
24
+ const parsedData = {
25
+ feature: null,
26
+ scenarios: []
27
+ };
28
+ for (const line of lines) {
29
+ const trimmedLine = line.trim();
30
+ if (trimmedLine.startsWith('Feature:')) {
31
+ if (currentFeature) {
32
+ parsedData.feature = currentFeature;
33
+ }
34
+ currentFeature = {
35
+ name: trimmedLine.replace('Feature:', '').trim(),
36
+ scenarios: []
37
+ };
38
+ } else if (trimmedLine.startsWith('Scenario:')) {
39
+ if (currentScenario) {
40
+ currentFeature.scenarios.push(currentScenario);
41
+ }
42
+ currentScenario = {
43
+ name: trimmedLine.replace('Scenario:', '').trim(),
44
+ steps: [],
45
+ examples: []
46
+ };
47
+ insideExampleTable = false;
48
+ } else if (trimmedLine.startsWith('Examples:')) {
49
+ insideExampleTable = true;
50
+ isHeaderRow = true; // Reset to true for each Examples section
51
+ const headerLine = lines[lines.indexOf(line) + 1].trim();
52
+ const tableHeader = headerLine.split('|').filter(cell => cell !== "").map(cell => cell.trim());
53
+ currentScenario.examples.push({
54
+ tableHeader,
55
+ tableRows: []
56
+ });
57
+ } else if (insideExampleTable && trimmedLine.startsWith('|')) {
58
+ if (!isHeaderRow) {
59
+ const exampleRow = trimmedLine.split('|').filter(cell => cell !== "").map(cell => cell.trim());
60
+ if (exampleRow.length === currentScenario.examples[0].tableHeader.length) {
61
+ currentScenario.examples[0].tableRows.push(exampleRow);
62
+ }
63
+ } else {
64
+ isHeaderRow = false;
65
+ }
66
+ } else if (trimmedLine.startsWith('Given') || trimmedLine.startsWith('When') || trimmedLine.startsWith('Then') || trimmedLine.startsWith('And')) {
67
+ currentScenario.steps.push(trimmedLine);
68
+ }
69
+ }
70
+ if (currentFeature) {
71
+ parsedData.feature = currentFeature;
72
+ }
73
+ if (currentScenario) {
74
+ currentFeature.scenarios.push(currentScenario);
75
+ }
76
+ return parsedData;
77
+ }
78
+ function generateSpecFileContent({
79
+ feature
80
+ }) {
81
+ let specContent = 'import { test } from "@zohodesk/testinglibrary";\n\n';
82
+ if (feature && feature.scenarios && feature.scenarios.length > 0) {
83
+ //specContent += `test.describe('${feature.name}', () => {\n`;
84
+ specContent += `// Feature: ${feature.name} \n`;
85
+ feature.scenarios.forEach(scenario => {
86
+ // specContent += ' /*\n'
87
+ // if (scenario.steps && scenario.steps.length > 0) {
88
+ // scenario.steps.forEach(step => {
89
+ // specContent += ` ** ${step}\n`
90
+ // })
91
+
92
+ // }
93
+ // specContent += ' */\n'
94
+ specContent += `test('${scenario.name}', async({ Given, When, Then, And }) => {\n`;
95
+ //specContent += ` // Your implementation here\n`;
96
+ if (scenario.steps && scenario.steps.length > 0) {
97
+ scenario.steps.forEach(step => {
98
+ let foundDelimiter = (0, _stepDefinitionsFormatter.findDelimiterFromStep)(step);
99
+ if (foundDelimiter) {
100
+ // Wrap the part of the string after the delimiter with a function call
101
+ let splitResult = step.split(foundDelimiter);
102
+ let wrappedString = ` await ${foundDelimiter}(${JSON.stringify(splitResult[1].trim())}, () => {\n //${foundDelimiter} Implementation will be here\n })();\n\n`;
103
+ specContent += wrappedString;
104
+ }
105
+ });
106
+ }
107
+ specContent += `});\n\n`;
108
+ });
109
+ //specContent += `});\n\n`;
110
+ }
111
+
112
+ return specContent;
113
+ }
114
+ function updateExistingSpecFile({
115
+ feature
116
+ }, specFile) {
117
+ if (feature && feature.scenarios && feature.scenarios.length > 0) {
118
+ let specFileCode = _fs.default.readFileSync(specFile, 'utf8');
119
+ feature.scenarios.forEach(({
120
+ name,
121
+ steps
122
+ }) => {
123
+ const scenarioComment = `/*\n${steps.map(step => ` ** ${step}`).join('\n')}\n */`;
124
+ const testNamePattern = new RegExp(`test\\('${name}',`, 'g');
125
+ const testNameMatches = specFileCode.match(testNamePattern);
126
+ if (testNameMatches) {
127
+ testNameMatches.forEach(match => {
128
+ const startIdx = specFileCode.indexOf(match);
129
+
130
+ // Find the index of the comment above the test block
131
+ const commentStartIdx = specFileCode.lastIndexOf('/*', startIdx);
132
+ const commentEndIdx = specFileCode.lastIndexOf('*/', startIdx);
133
+ if (commentStartIdx >= 0 && commentEndIdx > commentStartIdx) {
134
+ // Remove the old comment above the test block
135
+ specFileCode = specFileCode.slice(0, commentStartIdx) + scenarioComment + specFileCode.slice(commentEndIdx + 2);
136
+ }
137
+ });
138
+ } else {
139
+ // Create a new test block if the test name is not found
140
+ const newTestBlock = ` ${scenarioComment}\n test('${name}', () => {\n // Your implementation here\n });\n\n\n`;
141
+ // Locate the closest describe block for the new test
142
+ const lastDescribeEndIdx = specFileCode.lastIndexOf('});');
143
+ specFileCode = specFileCode.slice(0, lastDescribeEndIdx) + newTestBlock + specFileCode.slice(lastDescribeEndIdx);
144
+ }
145
+ });
146
+
147
+ // Save the updated code back to the spec file
148
+ _fs.default.writeFileSync(specFile, specFileCode, 'utf8');
149
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Spec file updated successfully');
150
+ }
151
+ }
152
+ function specFileGenerator(filePath, isUpdate) {
153
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `Generating spec file using file ${filePath}`);
154
+ // Read the Gherkin feature file
155
+ let {
156
+ featureFilesFolder = 'feature-files',
157
+ stepDefinitionsFolder = 'steps'
158
+ } = (0, _readConfigFile.generateConfigFromFile)();
159
+ _fs.default.readFile(filePath, 'utf8', (err, data) => {
160
+ if (err) {
161
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Error reading the file: ${err}`);
162
+ } else {
163
+ // Parse the feature file content and get the JSON-like object
164
+ const parsedFeature = parseFeature(data);
165
+ let specFilePath = filePath.replace(/\.feature$/, '.spec.js');
166
+ if (filePath.includes(`${featureFilesFolder}`)) {
167
+ specFilePath = specFilePath.replace(`/${featureFilesFolder}/`, `/${stepDefinitionsFolder}/`);
168
+ } else {
169
+ specFilePath = specFilePath.replace('./', `${stepDefinitionsFolder}`);
170
+ }
171
+ if ((0, _fileUtils.checkIfFileExists)(specFilePath)) {
172
+ if (isUpdate) {
173
+ updateExistingSpecFile(parsedFeature, specFilePath);
174
+ } else {
175
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, 'File Already exists. Make sure to either delete or pass --update option true');
176
+ }
177
+ return;
178
+ }
179
+
180
+ // Output the JSON-like object
181
+ //console.log(JSON.stringify(parsedFeature, null, 2));
182
+ //fs.writeFileSync('./sample.json', JSON.stringify(parsedFeature, null, 2));
183
+ const specFileContent = generateSpecFileContent(parsedFeature);
184
+
185
+ // Write the spec file content to a new file
186
+ try {
187
+ (0, _fileUtils.writeFileContents)(specFilePath, specFileContent);
188
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Spec file generated successfully.');
189
+ } catch (writeErr) {
190
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Error writing the spec file: ${writeErr}`);
191
+ }
192
+ }
193
+ });
194
+ }
195
+ function generateSpecCodeForFeatureFile(options) {
196
+ let cliObj = (0, _cliArgsToObject.cliArgsToObject)(options);
197
+ let {
198
+ featureFile: featureFilePath = null,
199
+ update = false
200
+ } = cliObj;
201
+ if (featureFilePath) {
202
+ specFileGenerator(_path.default.join(process.cwd(), './', featureFilePath), update);
203
+ } else {
204
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, 'Need option --featureFile to run this command');
205
+ }
206
+ }
@@ -0,0 +1,34 @@
1
+ Feature: Home Page
2
+
3
+ Scenario: Home Page Default content
4
+ Given user is on "<App>" home page
5
+ Then user gets a "<App>" bootcamp section
6
+ And username is also displayed on right corner
7
+
8
+ Examples:
9
+ | App |
10
+ | GitHub |
11
+
12
+ Scenario: GitHub Bootcamp Section
13
+ Given user is on "<Site>" home page
14
+ When user focuses on "<Site>" Bootcamp Section
15
+ Then user gets an option to setup git
16
+ And user gets an option to create repository
17
+ And user gets an option to Fork Repository
18
+ And user gets an option to work together
19
+
20
+ Examples:
21
+ | Site |
22
+ | GitHub |
23
+
24
+ Scenario: Top Banner content
25
+ Given user is on "<Product>" home page
26
+ When user focuses on Top Banner
27
+ Then user gets an option of home page
28
+ And user gets an option to search
29
+ And user gets settings options
30
+ And user gets an option to logout
31
+
32
+ Examples:
33
+ | Product |
34
+ | GitHub |
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ var _testinglibrary = require("@zohodesk/testinglibrary");
4
+ _testinglibrary.test.describe('Home Page', () => {
5
+ /*
6
+ ** Given user is on "<App>" home page
7
+ ** Then user gets a "<App>" bootcamp section
8
+ ** And username is also displayed on right corner
9
+ */
10
+ (0, _testinglibrary.test)('Home Page Default content', () => {
11
+ // Your implementation here
12
+ });
13
+
14
+ /*
15
+ ** Given user is on "<Site>" home page
16
+ ** When user focuses on "<Site>" Bootcamp Section
17
+ ** Then user gets an option to setup git
18
+ ** And user gets an option to create repository
19
+ ** And user gets an option to Fork Repository
20
+ ** And user gets an option to work together
21
+ */
22
+ (0, _testinglibrary.test)('GitHub Bootcamp Section', () => {
23
+ // Your implementation here
24
+ });
25
+
26
+ /*
27
+ ** Given user is on "<Product>" home page
28
+ ** When user focuses on Top Banner
29
+ ** Then user gets an option of home page
30
+ ** And user gets an option to search
31
+ ** And user gets settings options
32
+ ** And user gets an option to logout
33
+ */
34
+ (0, _testinglibrary.test)('Top Banner content', () => {
35
+ // Your implementation here
36
+ });
37
+ });
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _path = _interopRequireDefault(require("path"));
5
+ var _fastGlob = _interopRequireDefault(require("fast-glob"));
6
+ var _parser = require("./parser");
7
+ var _logger = require("../utils/logger");
8
+ var _fileUtils = require("../utils/fileUtils");
9
+ var _readConfigFile = require("../core/playwright/readConfigFile");
10
+ var _stepDefinitionsFormatter = require("../utils/stepDefinitionsFormatter");
11
+ // Specify the directory where you want to search for .feature and .spec.js files
12
+ const directoryPath = './uat';
13
+
14
+ // Use glob to match .feature files in the directory
15
+ const featurePattern = _path.default.join(process.cwd(), directoryPath, '**/*.feature');
16
+
17
+ // function onSpecFileNotFound() { }
18
+
19
+ function verifyIfMultipleStepsExists(steps) {
20
+ let isMultipleStepsFound = false;
21
+ Object.keys(steps).map(step => {
22
+ if (steps[step].length > 1) {
23
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `Multiple Steps Found for ${step} \n`);
24
+ steps[step].forEach(fileName => {
25
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `Files: \n ${fileName} \n`);
26
+ });
27
+ // multipleSteps.push({ step: steps[step] });
28
+ isMultipleStepsFound = true;
29
+ }
30
+ });
31
+ return isMultipleStepsFound;
32
+ }
33
+ function extractExamplesToSeperateFile(examples, scenarioIndex, filePath, featureName) {
34
+ let exampleFileContent = `export const ${featureName.toUpperCase()}_SCENARIO_${scenarioIndex} = ${JSON.stringify(examples, null, 2)};\r\n`;
35
+ const cleanedData = exampleFileContent.replace(/\r\n/g, '\n');
36
+ try {
37
+ (0, _fileUtils.writeFileContents)(filePath, cleanedData, {
38
+ flag: 'a'
39
+ });
40
+ } catch (err) {
41
+ _logger.Logger.error(err);
42
+ throw new Error(`Error appending or creating the test data file: ${filePath}`);
43
+ }
44
+ }
45
+ function verifyFeatureFileWithSpecFile() {
46
+ try {
47
+ let errorCount = 0;
48
+ let allStepsFound = {};
49
+ let {
50
+ featureFilesFolder = 'feature-files',
51
+ stepDefinitionsFolder = 'steps'
52
+ } = (0, _readConfigFile.generateConfigFromFile)();
53
+ const featureFiles = _fastGlob.default.globSync([featurePattern], {
54
+ dot: true
55
+ });
56
+ featureFiles.forEach(featureFile => {
57
+ // Construct the corresponding .spec.js filename
58
+ const specFile = featureFile.replace(/\.feature$/, '.spec.js').replace(`/${featureFilesFolder}/`, `/${stepDefinitionsFolder}/`);
59
+ let featureFileNameExtract = featureFile.split('/').pop();
60
+ let featurePrefixName = featureFileNameExtract.split('.')[0];
61
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `parsing feature file ${featureFileNameExtract}...`);
62
+ // Check if the .spec.js file exists
63
+
64
+ if ((0, _fileUtils.checkIfFileExists)(specFile)) {
65
+ let featureContents = (0, _fileUtils.readFileContents)(featureFile);
66
+ let specContents = (0, _fileUtils.readFileContents)(specFile);
67
+ //let [featureContents, specContents] = Promise.all([readFileContents(featureFile), readFileContents(specFile)]);
68
+ if (featureContents !== null && specContents !== null) {
69
+ const featureJSON = (0, _parser.parseFeature)(featureContents);
70
+ if (featureJSON && featureJSON.feature) {
71
+ let featureName = featureJSON.feature.name;
72
+ if (specContents.includes(featureName)) {
73
+ const scenarios = featureJSON.feature.scenarios;
74
+ const specLines = specContents.split('\n'); // Split specContents into lines
75
+ let testDataFilePath = featureFile.replace(`/${featureFilesFolder}/`, '/test-data/').replace(/\.feature$/, '.data.js');
76
+ // Examples to test data conversion. we are deleting the existing test data file and create a new file.
77
+ (0, _fileUtils.deleteFile)(testDataFilePath);
78
+ for (let i = 0; i < scenarios.length; i++) {
79
+ let scenario = scenarios[i];
80
+ const scenarioName = scenario.name;
81
+ const scenarioExamples = scenario.examples;
82
+ extractExamplesToSeperateFile(scenarioExamples, i, testDataFilePath, featurePrefixName);
83
+
84
+ // spec file check
85
+ if (!specLines.some(line => line.includes(scenarioName))) {
86
+ errorCount++;
87
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Scenario: ${scenarioName} is missing in spec file`);
88
+ }
89
+ for (const step of scenario.steps) {
90
+ if (!allStepsFound[step]) {
91
+ allStepsFound[step] = [specFile];
92
+ } else {
93
+ allStepsFound[step].push(specFile);
94
+ }
95
+ const foundDelimiter = (0, _stepDefinitionsFormatter.findDelimiterFromStep)(step);
96
+ if (foundDelimiter) {
97
+ let splitResult = step.split(foundDelimiter);
98
+ if (!specLines.some(line => line.includes(splitResult[1].trim().replace(/"/g, '\\"')))) {
99
+ errorCount++;
100
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Scenario: ${scenarioName} \n Step: ${step} is missing in the spec file ${specFile}`);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ } else {
106
+ errorCount++;
107
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, `Feature Name ${featureName} does not match/exist in ${specFile}`);
108
+ }
109
+ }
110
+ } else {
111
+ errorCount++;
112
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Error while reading feature file ${featureFile} or spec file ${specFile}`);
113
+ }
114
+ } else {
115
+ errorCount++;
116
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `No corresponding .spec.js file found for ${featureFile}`);
117
+ }
118
+ });
119
+ // Multiple steps found warning
120
+ verifyIfMultipleStepsExists(allStepsFound);
121
+ if (errorCount > 0) {
122
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Total Number of Errors found - ${errorCount}`);
123
+ throw new Error('Error while parsing feature files. Please fix the above issues before running test cases');
124
+ }
125
+ } catch (err) {
126
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, err);
127
+ process.exit(1);
128
+ }
129
+ }
130
+ verifyFeatureFileWithSpecFile();
@@ -0,0 +1,72 @@
1
+ /* eslint-disable no-console */
2
+ import { test as setup, expect } from '@zohodesk/testinglibrary';
3
+ import path from 'path';
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
5
+
6
+ const userdata = require('./authUsers.json');
7
+
8
+ const authDirectory = path.resolve(process.cwd(), 'uat', 'playwright', '.auth');
9
+
10
+ const authContent = { "cookies": [] };
11
+
12
+ const LOGIN_ERR_MESSAGE = 'Need go be logged in';
13
+ // const AUTH_ERR_MESSAGE = `Founded Path - ${path.resolve(process.cwd(),'uat','playwright','.auth')} \n Find if file is Properly Created. Cookies Cannot Be Read .. `
14
+
15
+
16
+ function convertCookiesToParse(cookies, authFilePath) {
17
+ try {
18
+ return JSON.parse(cookies)
19
+ } catch (err) {
20
+ throw new Error(` Error while parsing cookies ${err} \n${path.resolve(process.cwd(), authFilePath)} File is Empty`)
21
+ // process.exit()
22
+ }
23
+ }
24
+
25
+ if (!existsSync(authDirectory)) {
26
+ console.log('Creating auth directory for the first time setup...');
27
+ mkdirSync(authDirectory, { recursive: true });
28
+ }
29
+
30
+ userdata.forEach((data) => {
31
+ const authFile = path.resolve(path.join(authDirectory, `${data.filename}`));
32
+ if (!existsSync(authFile)) {
33
+ console.log('creating auth file..');
34
+ writeFileSync(authFile, JSON.stringify(authContent, null, 2))
35
+ }
36
+ setup(data.description, async ({ page }) => {
37
+
38
+ try {
39
+ const cookies = readFileSync(authFile);
40
+ const parsedCookies = convertCookiesToParse(cookies, authFile);
41
+ await page.context().addCookies(parsedCookies.cookies === undefined ? [] : parsedCookies.cookies)
42
+ await page.goto(page.getBaseUrl());
43
+ await page.waitForLoadState();
44
+ if (await page.url().includes(process.env.domain)) {
45
+ await page.waitForSelector(data.locator);
46
+ } else {
47
+ throw new Error(LOGIN_ERR_MESSAGE);
48
+ }
49
+
50
+
51
+ } catch (err) {
52
+ if (err.message === LOGIN_ERR_MESSAGE) {
53
+
54
+ await expect(page.locator('.load-bg')).toBeHidden();
55
+ await page.locator('#login_id').type(data.useremail);
56
+ await page.locator('#nextbtn').click();
57
+ await page.locator('#password').type(data.password);
58
+ await page.locator('#nextbtn').click();
59
+
60
+ await page.waitForLoadState("networkidle");
61
+
62
+ await page.waitForSelector(data.locator)
63
+
64
+ await page.context().storageState({ path: authFile });
65
+ }
66
+
67
+ }
68
+
69
+ });
70
+
71
+
72
+ })
@@ -0,0 +1,9 @@
1
+ [
2
+ {
3
+ "useremail": "/ user name /",
4
+ "password": "/ password /",
5
+ "description": "/ description/",
6
+ "filename": "user.json",
7
+ "locator": "/ selector to identify page has been loaded completely /"
8
+ }
9
+ ]
@@ -0,0 +1,21 @@
1
+ {
2
+ "dev": {
3
+ "domain": "https://desk.localzoho.com/agent",
4
+ "orgName": "org-name",
5
+ "deptName": "dept-name",
6
+ "moduleName": "module-name",
7
+ "devURL": "Provide your devURL here"
8
+ },
9
+ "prod": {
10
+ "domain": "https://desk.localzoho.com/agent",
11
+ "orgName": "org-name",
12
+ "deptName": "dept-name",
13
+ "moduleName": "module-name"
14
+ },
15
+ "k8test": {
16
+ "domain": "https://desk.localzoho.com/agent",
17
+ "orgName": "org-name",
18
+ "deptName": "dept-name",
19
+ "moduleName": "module-name"
20
+ }
21
+ }
@@ -0,0 +1,33 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import path from 'path';
3
+ import { Logger } from '../utils/logger';
4
+ import { generateConfigFromFile } from '../core/playwright/readConfigFile';
5
+
6
+
7
+ const { reportPath = path.resolve(process.cwd(), 'uat', 'playwright-reports') } = generateConfigFromFile();
8
+ const testResultsPath = path.resolve(process.cwd(), 'uat', 'test-results');
9
+
10
+ const testResultsRelativepath = path.relative(path.resolve(process.cwd(), '../', '../'), testResultsPath)
11
+ const reportRelativepath = path.relative(path.resolve(process.cwd(), '../', '../'), reportPath)
12
+
13
+ const dirpathtoIgnore = `${testResultsRelativepath}\n${reportRelativepath}`
14
+
15
+ function updateGitIgnore() {
16
+ if (existsSync(path.resolve(process.cwd(), '../', '../', '.gitignore'))) {
17
+ let gitIgnoreData = readFileSync(path.resolve(process.cwd(), '../', '../', '.gitignore'), 'utf-8', (err) => {
18
+ if (err) {
19
+ Logger.log(Logger.FAILURE_TYPE, 'cannot able to read git ignore ')
20
+ // process.exit()
21
+ }
22
+ })
23
+ if (gitIgnoreData.includes(dirpathtoIgnore)) {
24
+ return
25
+ } else {
26
+ writeFileSync(path.resolve(process.cwd(), '../', '../', '.gitignore', dirpathtoIgnore, null, 2))
27
+ }
28
+ } else {
29
+ Logger.log(Logger.INFO_TYPE, 'GitIgnore file is No Found ....')
30
+ }
31
+ }
32
+
33
+ export default updateGitIgnore;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Represents the user configuration object.
3
+ * @typedef {Object} UserConfig
4
+ * @property {string} headless - Headless Browsers mode.
5
+ * @property {number} trace - trace for test cases.
6
+ * @property {boolean} video - video for test cases,
7
+ * @property {boolean} debug - debug mode
8
+ * @property {string} mode: mode in which the test cases needs to run
9
+ * @property {boolean} isAuthMode - Auth Mode
10
+ * @property {string} authFilePath - File Path where the cookies stored
11
+ * @property {any} browsers: List of browsers
12
+ * @property {string} openReportOn: default Option value (never, on-failure and always)
13
+ * @property {any} reportPath : directory where report is generate
14
+ * @property {boolean} bddMode: Feature files needs to be processed
15
+ * @property {number} expectTimeout: time in milliseconds which the expect condition should fail
16
+ * @property {number} testTimeout: time in milliseconds which the test should fail
17
+ * @property {Object} additionalPages: custom pages configuration
18
+ * @property {string} featureFilesFolder: folder name under which feature-files will be placed. Default is feature-files
19
+ * @property {string} stepDefinitionsFolder: folder name under which step implementations will be placed. Default is steps
20
+ */
21
+
22
+ /**
23
+ * @type {UserConfig}
24
+ */
25
+ module.exports = {
26
+ headless: false,
27
+ browsers: ['Chrome', 'Firefox', 'Safari', 'Edge'],
28
+ mode: 'dev',
29
+ isAuthMode: true,
30
+ authFilePath: 'uat/playwright/.auth/user.json',
31
+ trace: true,
32
+ video: true,
33
+ featureFilesFolder: 'feature-files',
34
+ stepDefinitionsFolder: 'steps'
35
+ }