@zohodesk/testinglibrary 0.2.9-experimental → 0.2.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/.babelrc CHANGED
@@ -13,7 +13,8 @@
13
13
  ]
14
14
  ],
15
15
  "plugins": [
16
- ["@babel/plugin-transform-runtime"]
16
+ ["@babel/plugin-transform-runtime"],
17
+ ["@babel/plugin-transform-modules-commonjs"]
17
18
  ],
18
19
  // Ignored as these are setup files needed during init script. Files inside that folder are copied not transformed
19
20
  "ignore": [
package/.gitlab-ci.yml ADDED
@@ -0,0 +1,45 @@
1
+ image: node:14.17.3
2
+
3
+ workflow:
4
+ rules:
5
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
6
+
7
+ stages:
8
+ - build
9
+ - unit
10
+ - uat
11
+
12
+ # Install dependencies stage
13
+ build:
14
+ stage: build
15
+ image: node:14.17.3
16
+ script:
17
+ - npm install
18
+ artifacts:
19
+ paths:
20
+ - node_modules/
21
+
22
+
23
+ # Unit tests stage
24
+ unit:
25
+ stage: unit
26
+ image: node:14.17.3
27
+ script:
28
+ - npm test
29
+ artifacts:
30
+ when: always
31
+ paths:
32
+ - test-reports
33
+
34
+ uat:
35
+ stage: uat
36
+ image: node:14.17.3
37
+ script:
38
+ - cd examples
39
+ - npm i
40
+ - npm install $(npm pack ../ | tail -1)
41
+ - npm run uat
42
+ artifacts:
43
+ when: always
44
+ paths:
45
+ - uat-reports
package/README.md CHANGED
@@ -15,4 +15,21 @@
15
15
  ### Generate Report
16
16
 
17
17
  - npm run report
18
-
18
+
19
+ ## Version History
20
+
21
+ ### v0.2.8 - 26-09-2024
22
+
23
+ #### Feature
24
+ - Added support for writing unitcases for framework implementations
25
+
26
+ ### Bug fix
27
+ - Updated the custom-reported to include the errors in tests during the executions. It will help us avoid the stage passed without the actual test execution.
28
+
29
+ ### v0.2.9 - 24-10-2024
30
+
31
+ #### Feature
32
+ - Added support for scenario level tag support
33
+ - Added a new cli optin like uat-validate to validate the feature files using playwright-bdd
34
+ - Mode based configuration implementations
35
+ - @only option enabled in dev pipeline
@@ -1,12 +1,7 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.default = void 0;
8
- var _babelJest = _interopRequireDefault(require("babel-jest"));
9
- var _default = exports.default = _babelJest.default.createTransformer({
3
+ const babelJest = require('babel-jest');
4
+ module.exports = babelJest.createTransformer({
10
5
  presets: [require.resolve('@babel/preset-env'), require.resolve('@babel/preset-react')],
11
6
  plugins: [require.resolve('babel-plugin-transform-dynamic-import')]
12
7
  });
@@ -1,9 +1,3 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- var _testUtils = _interopRequireDefault(require("react-dom/test-utils"));
5
- var _globals = require("@jest/globals");
6
- var _react = _interopRequireDefault(require("react"));
7
- var _propTypes = _interopRequireDefault(require("prop-types"));
8
- var _reactDom = _interopRequireDefault(require("react-dom"));
9
3
  require("@testing-library/jest-dom/extend-expect");
@@ -11,7 +11,7 @@ var _readConfigFile = require("../readConfigFile");
11
11
  /* eslint-disable global-require */
12
12
 
13
13
  function getTagInputFromSelectedTags(tags, inputString) {
14
- const selectedTag = tags.find(tag => tag.startsWith(inputString));
14
+ const selectedTag = [...tags].reverse().find(tag => tag.startsWith(inputString));
15
15
  let tagInput = null;
16
16
  if (selectedTag) {
17
17
  tagInput = selectedTag.split(`${inputString}_`).pop().toLowerCase();
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ var _ConfigurationHelper = require("./ConfigurationHelper");
4
+ class Configuration {
5
+ properties = {};
6
+ constructor(props) {
7
+ this.properties = props;
8
+ }
9
+ add(key, value) {
10
+ this.properties[key] = value;
11
+ }
12
+ addAll(newConfig) {
13
+ this.properties = (0, _ConfigurationHelper.combineConfiguration)(this.properties, newConfig.getAll());
14
+ }
15
+ get(key) {
16
+ return this.properties[key];
17
+ }
18
+ getAll() {
19
+ return this.properties;
20
+ }
21
+ delete(key) {
22
+ delete this.properties[key];
23
+ }
24
+ }
25
+ module.exports = Configuration;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.combineConfiguration = combineConfiguration;
8
+ exports.getApplicationConfig = getApplicationConfig;
9
+ var _path = _interopRequireDefault(require("path"));
10
+ var _logger = require("../../../utils/logger");
11
+ var _configFileNameProvider = require("../helpers/configFileNameProvider");
12
+ var _mergeObjects = require("../helpers/mergeObjects");
13
+ var _fs = require("fs");
14
+ const Configuration = require("./Configuration");
15
+ function combineConfiguration(defaultConfig, userConfiguration) {
16
+ let configurationObj = {};
17
+ Object.keys(userConfiguration).forEach(configKey => {
18
+ let configValue = userConfiguration[configKey];
19
+ if (configValue !== null && configValue !== undefined) {
20
+ configurationObj[configKey] = configValue;
21
+ } else if (defaultConfig[configKey]) {
22
+ configurationObj[configKey] = defaultConfig[configKey];
23
+ } else {
24
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `key - ${configKey} is not yet supported in uat configuration. This will not be used while creating playwright configuration`);
25
+ }
26
+ });
27
+ return (0, _mergeObjects.mergeObjects)(defaultConfig, configurationObj);
28
+ }
29
+ function getApplicationConfig(mode) {
30
+ let filePath = "";
31
+ try {
32
+ filePath = _path.default.resolve(process.cwd(), (0, _configFileNameProvider.getUATFileName)(mode));
33
+ if (!(0, _fs.existsSync)(filePath)) {
34
+ throw new Error("Exception while getting the uat file from the application - " + filePath);
35
+ }
36
+ const config = require(filePath);
37
+ return config;
38
+ } catch (err) {
39
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Founded Path - ${filePath} Application config file not Exist ...`);
40
+ _logger.Logger.error(err);
41
+ return {};
42
+ }
43
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ var _cliArgsToObject = require("../../../utils/cliArgsToObject");
4
+ class UserArgs {
5
+ static parseToObject(config) {
6
+ return (0, _cliArgsToObject.cliArgsToObject)(config);
7
+ }
8
+ static parseToArgs(object) {
9
+ return (0, _cliArgsToObject.objectToCliArgs)(object);
10
+ }
11
+ }
12
+ module.exports = UserArgs;
@@ -10,7 +10,6 @@ var _path = _interopRequireDefault(require("path"));
10
10
  var _configFileNameProvider = require("./helpers/configFileNameProvider");
11
11
  var _logger = require("../../utils/logger");
12
12
  var _getUsers = require("./helpers/auth/getUsers");
13
- var _readConfigFile = require("./readConfigFile");
14
13
  function setEnvironmentVariables(configJSON) {
15
14
  for (const key in configJSON) {
16
15
  process.env[key] = configJSON[key];
@@ -33,12 +33,17 @@ function getDefaultActorConf() {
33
33
  const {
34
34
  uatDirectory
35
35
  } = (0, _readConfigFile.generateConfigFromFile)();
36
- const defaultSettingFile = `conf/${getRunMode()}/settings.json`;
37
- const filePath = _path.default.join(uatDirectory, defaultSettingFile);
38
- if (!(0, _fs.existsSync)(filePath)) {
39
- throw new Error(`${defaultSettingFile} is missing.`);
36
+ const modeSettingsFile = `conf/${getRunMode()}/settings.json`;
37
+ const filePath = _path.default.join(uatDirectory, modeSettingsFile);
38
+ try {
39
+ if (!(0, _fs.existsSync)(filePath)) {
40
+ const defaultSettingsFile = _path.default.join(uatDirectory, `conf/default/settings.json`);
41
+ return require(defaultSettingsFile);
42
+ }
43
+ return require(filePath);
44
+ } catch (error) {
45
+ throw new Error(`${defaultSettingFile} ${filePath} both files are missing.`);
40
46
  }
41
- return require(filePath);
42
47
  }
43
48
  function getDefaultActor() {
44
49
  const {
@@ -52,18 +57,25 @@ function getListOfActors() {
52
57
  uatDirectory
53
58
  } = (0, _readConfigFile.generateConfigFromFile)();
54
59
  const mode = getRunMode();
55
- const configFile = `conf/${mode}/actors/index`;
56
- const filePath = _path.default.join(uatDirectory, configFile);
57
- if (!(0, _fs.existsSync)(filePath + '.js')) {
58
- throw new Error(`${configFile}.js is missing.`);
60
+ let configFile = _path.default.join(uatDirectory, `conf/${mode}/actors/index.js`);
61
+ if (!(0, _fs.existsSync)(configFile)) {
62
+ configFile = _path.default.join(uatDirectory, `conf/default/actors/index.js`);
63
+ }
64
+ try {
65
+ return require(configFile);
66
+ } catch (error) {
67
+ throw new Error(`Error loading actor configuration from ${configFile}`);
59
68
  }
60
- return require(filePath);
61
69
  }
62
70
  function getUserForSelectedEditionAndProfile(preferedEdition, preferredProfile, betaFeature, testDataPortal = null) {
71
+ const actorsData = getListOfActors();
72
+ if (!actorsData || !actorsData.editions) {
73
+ throw new Error("The actors data is missing.");
74
+ }
63
75
  const {
64
76
  editions: userdata,
65
77
  beta: betaPortals
66
- } = getListOfActors();
78
+ } = actorsData;
67
79
  const defaultConf = getDefaultActorConf();
68
80
  const edition = preferedEdition || defaultConf.edition;
69
81
  const profile = preferredProfile || defaultConf.profile;
@@ -9,8 +9,14 @@ exports.getReportFileName = getReportFileName;
9
9
  exports.getUATFileName = getUATFileName;
10
10
  var _path = _interopRequireDefault(require("path"));
11
11
  var _fs = _interopRequireDefault(require("fs"));
12
- function getUATFileName() {
13
- return 'uat.config.js';
12
+ var _auth = require("./auth");
13
+ function getUATFileName(mode) {
14
+ mode = mode || (0, _auth.getRunMode)();
15
+ const uatConfFilePath = _path.default.resolve(process.cwd(), `uat/conf/${mode}/uat.config.js`);
16
+ if (_fs.default.existsSync(uatConfFilePath)) {
17
+ return uatConfFilePath;
18
+ }
19
+ return _path.default.resolve(process.cwd(), `uat.config.js`);
14
20
  }
15
21
  function getEnvConfigFilePath(mode) {
16
22
  const confFilePath = _path.default.resolve(process.cwd(), `uat/conf/${mode}/settings.json`);
@@ -18,7 +24,7 @@ function getEnvConfigFilePath(mode) {
18
24
  if (_fs.default.existsSync(confFilePath)) {
19
25
  return `uat/conf/${mode}/settings.json`;
20
26
  }
21
- return `uat/env-config.json`;
27
+ return `uat/conf/default/settings.json`;
22
28
  }
23
29
  function getReportFileName() {
24
30
  return `test-summary.json`;
@@ -3,9 +3,8 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.parseUserArgs = parseUserArgs;
7
7
  var _cliArgsToObject = require("../../../utils/cliArgsToObject");
8
8
  function parseUserArgs() {
9
9
  return (0, _cliArgsToObject.cliArgsToObject)(process.argv.slice(2));
10
- }
11
- var _default = exports.default = parseUserArgs;
10
+ }
@@ -6,18 +6,24 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.generateConfigFromFile = generateConfigFromFile;
8
8
  exports.getAuthFilePath = getAuthFilePath;
9
+ exports.getDefaultConfig = getDefaultConfig;
9
10
  exports.isUserConfigFileAvailable = isUserConfigFileAvailable;
10
11
  var _fs = require("fs");
11
12
  var _path = _interopRequireDefault(require("path"));
12
13
  var _logger = require("../../utils/logger");
13
14
  var _configFileNameProvider = require("./helpers/configFileNameProvider");
14
15
  var _mergeObjects = require("./helpers/mergeObjects");
16
+ var _Configuration = _interopRequireDefault(require("./configuration/Configuration"));
17
+ var _UserArgs = _interopRequireDefault(require("./configuration/UserArgs"));
18
+ var _ConfigurationHelper = require("./configuration/ConfigurationHelper");
15
19
  let cachedConfig = null;
16
20
  function getDefaultConfig() {
17
21
  return {
18
22
  uatDirectory: _path.default.join(process.cwd(), 'uat'),
19
23
  headless: false,
20
24
  browsers: ['Chrome'],
25
+ forbidOnly: false,
26
+ retries: 0,
21
27
  trace: false,
22
28
  video: false,
23
29
  isAuthMode: false,
@@ -32,26 +38,18 @@ function getDefaultConfig() {
32
38
  height: 720
33
39
  },
34
40
  debug: false,
35
- mode: process.env.mode || 'dev',
41
+ testIdAttribute: 'data-testid',
36
42
  additionalPages: {},
37
43
  featureFilesFolder: 'feature-files',
38
44
  stepDefinitionsFolder: 'steps',
39
- testIdAttribute: 'data-testid',
40
45
  testSetup: {},
41
46
  editionOrder: ['Free', 'Express', 'Standard', 'Professional', 'Enterprise']
42
47
  };
43
48
  }
44
- function checkForDeprecatedKeys(configKey) {
45
- let deprecatedConfigInUatConfigFile = ['mode'];
46
- if (deprecatedConfigInUatConfigFile.includes(configKey)) {
47
- _logger.Logger.log(_logger.Logger.INFO_TYPE, `key ${configKey} is deprecated. Please use other options`);
48
- }
49
- }
50
49
  function combineDefaultConfigWithUserConfig(userConfiguration) {
51
50
  let defaultConfig = getDefaultConfig();
52
51
  let configurationObj = {};
53
52
  Object.keys(userConfiguration).forEach(configKey => {
54
- checkForDeprecatedKeys(configKey);
55
53
  let configValue = userConfiguration[configKey];
56
54
  if (configValue !== null && configValue !== undefined) {
57
55
  configurationObj[configKey] = configValue;
@@ -110,22 +108,26 @@ function combineDefaultConfigWithUserConfig(userConfiguration) {
110
108
  *
111
109
  * @returns {UserConfig}
112
110
  */
111
+
112
+ function getConfigFilePath() {
113
+ return _path.default.resolve(process.cwd(), (0, _configFileNameProvider.getUATFileName)());
114
+ }
113
115
  function generateConfigFromFile() {
114
- if (cachedConfig !== null) {
115
- return cachedConfig; // If cached, return the cached configuration
116
- }
117
- const filePath = _path.default.resolve(process.cwd(), (0, _configFileNameProvider.getUATFileName)());
118
- if ((0, _fs.existsSync)(filePath)) {
119
- /** @type {UserConfig} */
120
- const config = require(filePath);
121
- const modifiedConfiguration = combineDefaultConfigWithUserConfig(config);
122
- cachedConfig = modifiedConfiguration;
123
- return modifiedConfiguration;
116
+ if (cachedConfig === null) {
117
+ // Getting the default config's from framework
118
+ const uatConfig = new _Configuration.default(getDefaultConfig());
119
+ // overriding the application config's from project
120
+ const appConfig = new _Configuration.default((0, _ConfigurationHelper.getApplicationConfig)());
121
+ const userArgConfig = new _Configuration.default(_UserArgs.default.parseToObject(process.argv.slice(2)));
122
+ // overriding the user config's from CLI
123
+ uatConfig.addAll(appConfig);
124
+ uatConfig.addAll(userArgConfig);
125
+ cachedConfig = uatConfig.getAll();
124
126
  }
125
- return {};
127
+ return cachedConfig;
126
128
  }
127
129
  function isUserConfigFileAvailable() {
128
- const filePath = _path.default.resolve(process.cwd(), (0, _configFileNameProvider.getUATFileName)());
130
+ const filePath = getConfigFilePath();
129
131
  if ((0, _fs.existsSync)(filePath)) {
130
132
  return true;
131
133
  }
@@ -9,6 +9,7 @@ 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
+ const uatConfig = (0, _readConfigFile.generateConfigFromFile)();
12
13
  const {
13
14
  browsers,
14
15
  trace,
@@ -25,7 +26,7 @@ const {
25
26
  stepDefinitionsFolder,
26
27
  testIdAttribute,
27
28
  globalTimeout
28
- } = (0, _readConfigFile.generateConfigFromFile)();
29
+ } = uatConfig;
29
30
  const projects = (0, _configUtils.getProjects)({
30
31
  browsers,
31
32
  isAuthMode,
@@ -51,13 +52,11 @@ const testOptions = (0, _configUtils.getTestUseOptions)({
51
52
  * @returns {import('@playwright/test').PlaywrightTestConfig}
52
53
  */
53
54
  function getPlaywrightConfig() {
54
- return {
55
+ const playwrightConfig = {
55
56
  testDir,
56
57
  globalTimeout: globalTimeout || 3600000,
57
58
  outputDir: _path.default.join(process.cwd(), 'uat', 'test-results'),
58
59
  fullyParallel: true,
59
- forbidOnly: !!process.env.CI,
60
- retries: process.env.CI ? 2 : 0,
61
60
  reporter: [['html', {
62
61
  outputFolder: reportPath,
63
62
  open: openReportOn
@@ -76,7 +75,9 @@ function getPlaywrightConfig() {
76
75
  name: 'cleanup',
77
76
  testMatch: /.*\.teardown\.js/,
78
77
  testDir: _path.default.join(process.cwd(), 'uat')
79
- }, ...projects] : [...projects]
78
+ }, ...projects] : [...projects],
79
+ ...uatConfig
80
80
  };
81
+ return playwrightConfig;
81
82
  }
82
83
  var _default = exports.default = (0, _test.defineConfig)(getPlaywrightConfig());
@@ -18,6 +18,7 @@ class JSONSummaryReporter {
18
18
  this.skipped = [];
19
19
  this.failed = [];
20
20
  this.warned = [];
21
+ this.errored = [];
21
22
  this.interrupted = [];
22
23
  this.timedOut = [];
23
24
  this.flakey = [];
@@ -29,7 +30,7 @@ class JSONSummaryReporter {
29
30
  onBegin() {
30
31
  this.startedAt = Date.now();
31
32
  }
32
- onTestEnd(test, result) {
33
+ getTitle(test) {
33
34
  const title = [];
34
35
  const fileName = [];
35
36
  let clean = true;
@@ -39,35 +40,52 @@ class JSONSummaryReporter {
39
40
  }
40
41
  clean = false;
41
42
  title.push(s);
42
- if (s.includes('.ts') || s.includes('.js')) {
43
+ if (s.endsWith('.ts') || s.endsWith('.js')) {
43
44
  fileName.push(s);
44
45
  }
45
46
  }
46
- // This will publish the file name + line number test begins on
47
- const z = `${fileName[0]}`;
48
- // Using the t variable in the push will push a full test name + test description
49
- const t = title.join(' > ');
47
+
48
+ //Using the fullTitle variable in the push will push a full test name + test description
49
+
50
+ return {
51
+ fullTitle: title.join(' > '),
52
+ fileName: fileName[0] || ''
53
+ };
54
+ }
55
+ onTestEnd(test, result) {
56
+ const {
57
+ fullTitle,
58
+ fileName
59
+ } = this.getTitle(test);
60
+
50
61
  // Set the status
51
- const stepTitleList = result.steps.map(step => ({
62
+ const stepTitleList = result.steps.filter(step => step.error).map(step => ({
52
63
  title: step.title,
53
64
  error: step.error,
54
- testTitle: t
55
- })).filter(step => step.error !== undefined);
65
+ testTitle: fullTitle
66
+ }));
56
67
  if (stepTitleList.length > 0) {
57
68
  this.failedSteps = [...this.failedSteps, ...stepTitleList];
58
69
  }
59
- const status = !['passed', 'skipped'].includes(result.status) && t.includes('@warn') ? 'warned' : result.status;
70
+ const status = !['passed', 'skipped'].includes(result.status) && fullTitle.includes('@warn') ? 'warned' : result.status;
60
71
  // Logic to push the results into the correct array
61
72
  if (result.status === 'passed' && result.retry >= 1) {
62
- this.flakey.push(z);
73
+ this.flakey.push(fileName);
63
74
  } else {
64
- this[status].push(z);
75
+ this[status].push(fileName);
65
76
  }
66
- this[status].push(z);
77
+ this[status].push(fileName);
78
+ }
79
+ onError(error) {
80
+ this.errored.push({
81
+ error: error.message,
82
+ stack: error.stack
83
+ });
67
84
  }
68
85
  onEnd(result) {
69
86
  this.durationInMS = Date.now() - this.startedAt;
70
87
  this.status = result.status;
88
+
71
89
  // removing duplicate tests from passed array
72
90
  this.passed = this.passed.filter((element, index) => {
73
91
  return this.passed.indexOf(element) === index;
@@ -90,6 +108,14 @@ class JSONSummaryReporter {
90
108
  this.interrupted = this.interrupted.filter((element, index) => {
91
109
  return this.interrupted.indexOf(element) === index;
92
110
  });
111
+ this.errored = this.errored.filter((element, index) => {
112
+ return this.errored.indexOf(element) === index;
113
+ });
114
+ if (this.errored.length > 0) {
115
+ // Reflect setup failures in the final report status
116
+ this.status = "failed";
117
+ }
118
+
93
119
  // fs.writeFileSync('./summary.json', JSON.stringify(this, null, ' '));
94
120
  let {
95
121
  reportPath
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
+ exports.runPreprocessing = runPreprocessing;
8
9
  var _child_process = require("child_process");
9
10
  var _path = _interopRequireDefault(require("path"));
10
11
  var _customCommands = require("./custom-commands");
@@ -16,7 +17,9 @@ var _rootPath = require("../../utils/rootPath");
16
17
  var _tagProcessor = require("./tag-processor");
17
18
  var _configUtils = require("./setup/config-utils");
18
19
  var _browserTypes = require("./constants/browserTypes");
19
- var _parseUserArgs = _interopRequireDefault(require("./helpers/parseUserArgs"));
20
+ var _ConfigurationHelper = require("./configuration/ConfigurationHelper");
21
+ var _Configuration = _interopRequireDefault(require("./configuration/Configuration"));
22
+ var _UserArgs = _interopRequireDefault(require("./configuration/UserArgs"));
20
23
  function getPlaywrightArgs(userArgsObject, debug, bddMode, tagArgs, headless) {
21
24
  const {
22
25
  browsers = null
@@ -55,7 +58,7 @@ function runPreprocessing(tagArgs, configPath) {
55
58
  });
56
59
  childProcessForPreprocessing.on('error', data => {
57
60
  _logger.Logger.log(_logger.Logger.FAILURE_TYPE, data);
58
- reject();
61
+ reject(data);
59
62
  });
60
63
  childProcessForPreprocessing.on('exit', code => {
61
64
  if (code === 0) {
@@ -97,16 +100,28 @@ function runPlaywright(command, args) {
97
100
  });
98
101
  }
99
102
  function main() {
100
- const userArgsObject = (0, _parseUserArgs.default)();
101
- const uatConfig = (0, _readConfigFile.generateConfigFromFile)();
103
+ // Getting the default config's from framework
104
+ const uatConfig = new _Configuration.default((0, _readConfigFile.getDefaultConfig)());
105
+
106
+ // overriding the application config's from project
107
+
108
+ const userArgConfig = new _Configuration.default(_UserArgs.default.parseToObject(process.argv.slice(2)));
109
+ const mode = userArgConfig.get("mode");
110
+ uatConfig.addAll(new _Configuration.default((0, _ConfigurationHelper.getApplicationConfig)(mode)));
111
+
112
+ // overriding the user config's from CLI
113
+ uatConfig.addAll(userArgConfig);
102
114
  const {
115
+ isAuthMode,
116
+ editionOrder,
103
117
  debug,
104
118
  bddMode = false,
105
- headless = false,
106
- editionOrder,
107
- isAuthMode
108
- } = uatConfig;
109
- (0, _envInitializer.initializeEnvConfig)(userArgsObject.mode, isAuthMode);
119
+ headless = false
120
+ } = uatConfig.getAll();
121
+ (0, _envInitializer.initializeEnvConfig)(mode, isAuthMode);
122
+
123
+ //This is only used for pass the user arguments to need places in legacy code. We need to rewamp that also.
124
+ const userArgsObject = userArgConfig.getAll();
110
125
  const tagArgs = (0, _tagProcessor.tagProcessor)(userArgsObject, editionOrder);
111
126
  const playwrightArgs = getPlaywrightArgs(userArgsObject, debug, bddMode, tagArgs, headless);
112
127
  const playwrightPath = _path.default.resolve((0, _rootPath.getExecutableBinaryPath)('playwright'));
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _parseUserArgs = _interopRequireDefault(require("./helpers/parseUserArgs"));
9
+ var _readConfigFile = require("./readConfigFile");
10
+ var _tagProcessor = require("./tag-processor");
11
+ var _testRunner = require("./test-runner");
12
+ var _logger = require("../../utils/logger");
13
+ // @cucumber/gherkins need to be includ in package.json
14
+
15
+ // const getFeatureFiles = (dir) => {
16
+ // let featureFiles = [];
17
+ // const files = fs.readdirSync(dir, { withFileTypes: true });
18
+ // files.forEach(file => {
19
+ // const fullPath = path.join(dir, file.name);
20
+ // if (file.isDirectory()) {
21
+ // featureFiles = featureFiles.concat(getFeatureFiles(fullPath));
22
+ // } else if (file.isFile() && fullPath.endsWith('.feature')) {
23
+ // featureFiles.push(fullPath);
24
+ // }
25
+ // });
26
+ // return featureFiles;
27
+ // };
28
+
29
+ //const validateFeatureFiles = () => {
30
+ // const featuresDir = path.join(process.cwd(), 'uat/modules');
31
+ // const parser = new Parser();
32
+ // const featureFiles = getFeatureFiles(featuresDir);
33
+ // featureFiles.forEach( filePath => {
34
+ // const featureFileContent = fs.readFileSync(filePath, 'utf-8');
35
+ // try {
36
+ // parser.parse(featureFileContent);
37
+ // console.log(`${filePath}: Feature file is valid!`);
38
+ // } catch (error) {
39
+ // console.error(`${filePath}: Feature file is invalid - ${error.message}`);
40
+ // }
41
+ // })
42
+ //}
43
+
44
+ const validateFeatureFiles = () => {
45
+ const userArgsObject = (0, _parseUserArgs.default)();
46
+ const uatConfig = (0, _readConfigFile.generateConfigFromFile)();
47
+ const {
48
+ editionOrder
49
+ } = uatConfig;
50
+ const configPath = (0, _readConfigFile.isUserConfigFileAvailable)() ? require.resolve('./setup/config-creator.js') : require.resolve('../../../playwright.config.js');
51
+ const tagArgs = (0, _tagProcessor.tagProcessor)(userArgsObject, editionOrder);
52
+ (0, _testRunner.runPreprocessing)(tagArgs, configPath).then(() => {
53
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Feature files validated successfully.');
54
+ }).catch(error => {
55
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Error while validating the feature files - ${error}`);
56
+ });
57
+ };
58
+ var _default = exports.default = validateFeatureFiles;
package/build/lib/cli.js CHANGED
@@ -10,6 +10,7 @@ var _parser = require("../parser/parser");
10
10
  var _clearCaches = _interopRequireDefault(require("../core/playwright/clear-caches"));
11
11
  var _helper = _interopRequireDefault(require("../setup-folder-structure/helper"));
12
12
  var _parseUserArgs = _interopRequireDefault(require("../core/playwright/helpers/parseUserArgs"));
13
+ var _validateFeature = _interopRequireDefault(require("../core/playwright/validateFeature"));
13
14
  // import createJestRunner from '../core/jest/runner/jest-runner';
14
15
 
15
16
  const [,, option, ...otherOptions] = process.argv;
@@ -21,6 +22,11 @@ switch (option) {
21
22
  //createJestRunner();
22
23
  break;
23
24
  }
25
+ case 'validate':
26
+ {
27
+ (0, _validateFeature.default)();
28
+ break;
29
+ }
24
30
  case 're-run-failed':
25
31
  {
26
32
  _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Running Failed Tests..');
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _validateFeature = _interopRequireDefault(require("../../../../core/playwright/validateFeature"));
5
+ var _parseUserArgs = _interopRequireDefault(require("../../../../core/playwright/helpers/parseUserArgs"));
6
+ var _readConfigFile = require("../../../../core/playwright/readConfigFile");
7
+ var _tagProcessor = require("../../../../core/playwright/tag-processor");
8
+ var _testRunner = require("../../../../core/playwright/test-runner");
9
+ var _logger = require("../../../../utils/logger");
10
+ jest.mock('../../../../core/playwright/helpers/parseUserArgs', () => ({
11
+ __esModule: true,
12
+ default: jest.fn()
13
+ }));
14
+ jest.mock('../../../../core/playwright/readConfigFile');
15
+ jest.mock('../../../../core/playwright/tag-processor');
16
+ jest.mock('../../../../core/playwright/test-runner');
17
+ jest.mock('../../../../utils/logger', () => ({
18
+ __esModule: true,
19
+ Logger: {
20
+ log: jest.fn(),
21
+ SUCCESS_TYPE: 'success',
22
+ FAILURE_TYPE: 'failure'
23
+ }
24
+ }));
25
+ describe('validateFeatureFiles', () => {
26
+ beforeEach(() => {
27
+ jest.clearAllMocks();
28
+ });
29
+ test('runPreprocessing with correct arguments and log success', async () => {
30
+ const mockUserArgs = {
31
+ mode: 'dev'
32
+ };
33
+ _parseUserArgs.default.mockReturnValue(mockUserArgs);
34
+ const mockConfig = {
35
+ editionOrder: ["beta", "enterprice"]
36
+ };
37
+ _readConfigFile.generateConfigFromFile.mockReturnValue(mockConfig);
38
+ _readConfigFile.isUserConfigFileAvailable.mockReturnValue(true);
39
+ const mockTagArgs = ['@beta_admin'];
40
+ _tagProcessor.tagProcessor.mockReturnValue(mockTagArgs);
41
+ _testRunner.runPreprocessing.mockResolvedValueOnce();
42
+ await (0, _validateFeature.default)();
43
+ expect(_parseUserArgs.default).toHaveBeenCalled();
44
+ expect(_readConfigFile.generateConfigFromFile).toHaveBeenCalled();
45
+ expect(_readConfigFile.isUserConfigFileAvailable).toHaveBeenCalled();
46
+ expect(_tagProcessor.tagProcessor).toHaveBeenCalledWith(mockUserArgs, ["beta", "enterprice"]);
47
+ expect(_testRunner.runPreprocessing).toHaveBeenCalledWith(mockTagArgs, expect.stringContaining('config-creator.js'));
48
+ expect(_logger.Logger.log).toHaveBeenCalledWith(_logger.Logger.SUCCESS_TYPE, 'Feature files validated successfully.');
49
+ });
50
+ test('runPreprocessing with playwright conf', async () => {
51
+ const mockTagArgs = ['@beta_admin'];
52
+ _tagProcessor.tagProcessor.mockReturnValue(mockTagArgs);
53
+ _readConfigFile.isUserConfigFileAvailable.mockReturnValue(false);
54
+ _testRunner.runPreprocessing.mockResolvedValueOnce();
55
+ await (0, _validateFeature.default)();
56
+ expect(_testRunner.runPreprocessing).toHaveBeenCalledWith(mockTagArgs, expect.stringContaining('playwright.config.js'));
57
+ });
58
+ test('error when runPreprocessing fails', async () => {
59
+ const mockError = new Error('Test error');
60
+ _testRunner.runPreprocessing.mockRejectedValueOnce(mockError);
61
+ await await (0, _validateFeature.default)();
62
+ expect(_logger.Logger.log).toHaveBeenCalledWith(_logger.Logger.FAILURE_TYPE, `Error while validating the feature files - ${mockError}`);
63
+ });
64
+ });
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ const Configuration = require("../../../../../core/playwright/configuration/Configuration");
4
+ const {
5
+ combineConfiguration
6
+ } = require("../../../../../core/playwright/configuration/ConfigurationHelper");
7
+ jest.mock('../../../../../core/playwright/configuration/ConfigurationHelper', () => ({
8
+ combineConfiguration: jest.fn()
9
+ }));
10
+ describe('Configuration Class', () => {
11
+ let config;
12
+ let sampleData;
13
+ beforeEach(() => {
14
+ // Sample data as a JSON object
15
+ sampleData = {
16
+ headless: false,
17
+ trace: true,
18
+ video: true,
19
+ bddMode: true
20
+ };
21
+
22
+ // Initialize the Configuration instance with sample data
23
+ config = new Configuration(sampleData);
24
+ });
25
+ test('should add new key-value pair to the configuration', () => {
26
+ config.add('newKey', 'newValue');
27
+ expect(config.get('newKey')).toBe('newValue');
28
+ });
29
+ test('should combine configurations correctly using addAll', () => {
30
+ const newConfig = new Configuration({
31
+ newKey1: 'newValue1',
32
+ trace: false // existing key to test override
33
+ });
34
+ const combinedConfig = {
35
+ headless: false,
36
+ trace: false,
37
+ // trace overridden
38
+ video: true,
39
+ bddMode: true,
40
+ newKey1: 'newValue1'
41
+ };
42
+ combineConfiguration.mockReturnValue(combinedConfig);
43
+ config.addAll(newConfig);
44
+ expect(combineConfiguration).toHaveBeenCalledWith(sampleData, newConfig.getAll());
45
+ expect(config.getAll()).toEqual(combinedConfig);
46
+ });
47
+ test('should return correct value for a given key', () => {
48
+ expect(config.get('headless')).toBe(false);
49
+ expect(config.get('trace')).toBe(true);
50
+ expect(config.get('video')).toBe(true);
51
+ expect(config.get('bddMode')).toBe(true);
52
+ });
53
+ });
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _fs = require("fs");
5
+ var _path = _interopRequireDefault(require("path"));
6
+ var _configFileNameProvider = require("../../../../../core/playwright/helpers/configFileNameProvider");
7
+ jest.mock('fs');
8
+ jest.mock('path');
9
+ const mockCwd = '/mock/current/directory';
10
+ _path.default.resolve = jest.fn();
11
+ process.cwd = jest.fn(() => mockCwd);
12
+ describe('getUATFileName', () => {
13
+ beforeEach(() => {
14
+ jest.clearAllMocks();
15
+ });
16
+ test('return the pipeline matched config files for pipeline matched files exists', () => {
17
+ const mode = 'cd';
18
+ const mockPath = `${mockCwd}/uat/conf/${mode}/uat.config.js`;
19
+ _fs.existsSync.mockReturnValue(true);
20
+ _path.default.resolve.mockImplementation((...args) => args.join('/'));
21
+ const result = (0, _configFileNameProvider.getUATFileName)(mode);
22
+ expect(_fs.existsSync).toHaveBeenCalledWith(mockPath);
23
+ expect(result).toBe(mockPath);
24
+ });
25
+ test('return the default config files for pipeline matched files not exists', () => {
26
+ const mode = 'ci';
27
+ const defaultPath = `${mockCwd}/uat.config.js`;
28
+ _fs.existsSync.mockReturnValue(false);
29
+ _path.default.resolve.mockImplementation((...args) => args.join('/'));
30
+ const result = (0, _configFileNameProvider.getUATFileName)(mode);
31
+ expect(_fs.existsSync).toHaveBeenCalledWith(`${mockCwd}/uat/conf/${mode}/uat.config.js`);
32
+ expect(result).toBe(defaultPath);
33
+ });
34
+ });
@@ -36,6 +36,9 @@ function cliArgsToObject(cliArgs, isKeyNeedToBeAdded) {
36
36
  value = true;
37
37
  }
38
38
  processEnv[key] = value;
39
+ if (!isNaN(parseInt(value))) {
40
+ processEnv[key] = parseInt(value);
41
+ }
39
42
  }
40
43
  });
41
44
  return processEnv;
package/jest.config.js CHANGED
@@ -6,7 +6,7 @@ const appGlobals = path.resolve(appPath, '__testUtils__', 'globals.js');
6
6
 
7
7
  module.exports = {
8
8
  rootDir: process.cwd(),
9
- testEnvironment: 'jsdom',
9
+ testEnvironment: 'node',
10
10
 
11
11
  setupFilesAfterEnv: [
12
12
  existsSync(appGlobals) && appGlobals,
@@ -21,13 +21,21 @@ module.exports = {
21
21
  'jest',
22
22
  'preprocessor',
23
23
  'jsPreprocessor.js'
24
- )
24
+ ),
25
+ '^.+\\.jsx?$': 'babel-jest'
25
26
  },
27
+
28
+ testMatch: ['**/__tests__/**/*.test.js'],
26
29
 
27
30
  modulePathIgnorePatterns: ['/build/'],
28
31
 
29
32
  transformIgnorePatterns: [
30
- '/node_modules/(?!(@zohodesk)/)'
33
+ '/node_modules/',
34
+ '/src/setup-folder-structure/samples/'
35
+ ],
36
+
37
+ coveragePathIgnorePatterns:[
38
+ '/src/setup-folder-structure/samples/'
31
39
  ],
32
40
 
33
41
  testPathIgnorePatterns: [
@@ -48,14 +56,14 @@ module.exports = {
48
56
  collectCoverageFrom: ['src/**/*.js'],
49
57
  coverageDirectory: './build/cov',
50
58
  coverageReporters: ['lcov', 'json', 'html', 'json-summary', 'text'],
51
- coverageThreshold: {
52
- global: {
53
- branches: 100,
54
- functions: 100,
55
- lines: 100,
56
- statements: 100
57
- }
58
- },
59
+ // coverageThreshold: {
60
+ // global: {
61
+ // branches: 100,
62
+ // functions: 100,
63
+ // lines: 100,
64
+ // statements: 100
65
+ // }
66
+ // },
59
67
  globals: {
60
68
  __DEVELOPMENT__: true,
61
69
  __DOCS__: false,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/testinglibrary",
3
- "version": "0.2.1",
3
+ "version": "0.3.8-experimental",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@zohodesk/testinglibrary",
3
- "version": "0.2.9-experimental",
3
+ "version": "0.2.9",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
7
7
  "postinstall": "node bin/postinstall.js",
8
- "test": "echo \"Error: no test specified\" && exit 1",
8
+ "test": "jest",
9
9
  "clean": "rm -rf build && mkdir build",
10
10
  "build-babel": "babel -d ./build ./src --copy-files",
11
11
  "build": "npm run clean && npm run build-babel",
@@ -18,7 +18,7 @@ export default defineConfig({
18
18
  /* Run tests in files in parallel */
19
19
  fullyParallel: true,
20
20
  /* Fail the build on CI if you accidentally left test.only in the source code. */
21
- forbidOnly: !!process.env.CI,
21
+ //forbidOnly: !!process.env.CI,
22
22
  /* Retry on CI only */
23
23
  retries: process.env.CI ? 2 : 0,
24
24
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
@@ -47,7 +47,7 @@ export default defineConfig({
47
47
  {
48
48
  name: 'chromium',
49
49
  use: {
50
- channel: 'chrome',
50
+ ...devices['Desktop Chrome'],
51
51
  storageState: path.resolve(process.cwd(), 'uat', 'playwright/.auth/user.json')
52
52
  },
53
53
  dependencies: ['setup'],