@zohodesk/testinglibrary 4.1.1 → 4.1.3

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/README.md CHANGED
@@ -17,6 +17,16 @@
17
17
 
18
18
  - npm run report
19
19
 
20
+ ### v4.1.3/v3.3.2 - 08-06-2026
21
+
22
+ #### Features
23
+ - Scenario-Based Timeouts: Define custom execution limits directly in your feature files using Gherkin tags (e.g., @timeout_180).
24
+
25
+ ### v4.1.2/v3.3.1 - 21-05-2026
26
+
27
+ #### Features
28
+ - Supported UnitTest via testing-framework
29
+
20
30
  ### v4.1.1/v3.3.0 - 28-01-2026
21
31
 
22
32
  #### Features
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _caseTimeoutResolver = require("../helpers/caseTimeoutResolver");
8
+ var _default = exports.default = {
9
+ caseTimeout: [async ({
10
+ $tags
11
+ }, use, testInfo) => {
12
+ const timeoutMs = (0, _caseTimeoutResolver.resolveCaseTimeoutMs)($tags, testInfo.project.name);
13
+ if (timeoutMs !== null) {
14
+ testInfo.setTimeout(timeoutMs);
15
+ }
16
+ await use();
17
+ }, {
18
+ auto: true
19
+ }]
20
+ };
@@ -9,6 +9,7 @@ var _page = _interopRequireDefault(require("./page"));
9
9
  var _context = _interopRequireDefault(require("./context"));
10
10
  var _cacheLayer = _interopRequireDefault(require("./cacheLayer"));
11
11
  var _addTags = _interopRequireDefault(require("./addTags"));
12
+ var _caseTimeout = _interopRequireDefault(require("./caseTimeout"));
12
13
  var _i18N = _interopRequireDefault(require("./i18N"));
13
14
  var _unauthenticatedPage = _interopRequireDefault(require("./unauthenticatedPage"));
14
15
  var _executionContext = _interopRequireDefault(require("./executionContext"));
@@ -24,7 +25,8 @@ function getBuiltInFixtures(bddMode) {
24
25
  ..._cacheLayer.default,
25
26
  ..._i18N.default,
26
27
  ..._unauthenticatedPage.default,
27
- ..._executionContext.default
28
+ ..._executionContext.default,
29
+ ..._caseTimeout.default
28
30
  };
29
31
  if (bddMode) {
30
32
  builtInFixtures = {
@@ -11,5 +11,6 @@ const stage = (0, _ConfigurationHelper.getRunStage)();
11
11
  class ReporterConstants {
12
12
  static DEFAULT_REPORTER_PATH = `${_configConstants.default.TEST_SLICE_FOLDER}/${stage}/test-results/playwright-test-results.json`;
13
13
  static LAST_RUN_REPORTER_PATH = `${_configConstants.default.TEST_SLICE_FOLDER}/${stage}/test-results/.last-run.json`;
14
+ static DEFAULT_UNIT_TEST_REPORTER_PATH = `${_configConstants.default.TEST_SLICE_FOLDER}/unit-test/unit_reports/report.html`;
14
15
  }
15
16
  exports.default = ReporterConstants;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getBrowserTimeoutFactor = getBrowserTimeoutFactor;
7
+ var _browserTypes = require("../constants/browserTypes");
8
+ function getBrowserTimeoutFactor(projectName) {
9
+ if (projectName === _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX) {
10
+ return 2;
11
+ }
12
+ if (projectName === _browserTypes.BROWSER_PROJECT_MAPPING.SAFARI) {
13
+ return 4;
14
+ }
15
+ return 1;
16
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TIMEOUT_TAG_PATTERN = void 0;
7
+ exports.findTimeoutTags = findTimeoutTags;
8
+ exports.parseTimeoutSeconds = parseTimeoutSeconds;
9
+ exports.resolveCaseTimeoutMs = resolveCaseTimeoutMs;
10
+ var _logger = require("../../../utils/logger");
11
+ var _browserTimeoutFactor = require("./browserTimeoutFactor");
12
+ const TIMEOUT_TAG_PATTERN = exports.TIMEOUT_TAG_PATTERN = /^@timeout_(\d+)$/;
13
+ function findTimeoutTags(tags) {
14
+ if (!Array.isArray(tags)) {
15
+ return [];
16
+ }
17
+ return tags.filter(tag => typeof tag === 'string' && TIMEOUT_TAG_PATTERN.test(tag));
18
+ }
19
+ function parseTimeoutSeconds(tag) {
20
+ const match = tag.match(TIMEOUT_TAG_PATTERN);
21
+ return match ? Number(match[1]) : null;
22
+ }
23
+ function resolveCaseTimeoutMs(tags, projectName) {
24
+ const matched = findTimeoutTags(tags);
25
+ if (matched.length === 0) {
26
+ return null;
27
+ }
28
+ if (matched.length > 1) {
29
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `Multiple @timeout_* tags found (${matched.join(', ')}). Using the first one: ${matched[0]}`);
30
+ }
31
+ const seconds = parseTimeoutSeconds(matched[0]);
32
+ if (seconds === 0) {
33
+ return 0;
34
+ }
35
+ const factor = (0, _browserTimeoutFactor.getBrowserTimeoutFactor)(projectName);
36
+ return seconds * 1000 * factor;
37
+ }
@@ -105,7 +105,7 @@ function combineDefaultConfigWithUserConfig(userConfiguration) {
105
105
  * @property {any} reportPath : directory where report is generate
106
106
  * @property {boolean} bddMode: Feature files needs to be processed
107
107
  * @property {number} expectTimeout: time in milliseconds which the expect condition should fail
108
- * @property {number} testTimeout: time in milliseconds which the test should fail
108
+ * @property {number} testTimeout: time in milliseconds which the test should fail. Can be overridden per-scenario by tagging the scenario with `@timeout_<seconds>` (e.g. `@timeout_180`). `@timeout_0` disables the timeout. Browser scaling (Firefox 2x, Safari 4x) is preserved.
109
109
  * @property {Object} additionalPages: custom pages configuration
110
110
  * @property {string} featureFilesFolder: folder name under which feature-files will be placed. Default is feature-files
111
111
  * @property {string} stepDefinitionsFolder: folder name under which step implementations will be placed. Default is steps
@@ -0,0 +1,44 @@
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 _child_process = require("child_process");
9
+ var _path = _interopRequireDefault(require("path"));
10
+ var _logger = require("../../../utils/logger");
11
+ var _rootPath = require("../../../utils/rootPath");
12
+ var _readConfigFile = require("../readConfigFile");
13
+ class PlaywrightReporter {
14
+ static generate() {
15
+ const userArgs = process.argv.slice(3);
16
+ const playwrightPath = _path.default.resolve((0, _rootPath.getExecutableBinaryPath)('playwright'));
17
+ const command = playwrightPath;
18
+ const {
19
+ reportPath: htmlPath
20
+ } = (0, _readConfigFile.generateConfigFromFile)();
21
+ const args = ['show-report', htmlPath].concat(userArgs);
22
+ const childProcess = (0, _child_process.spawn)(command, args, {
23
+ stdio: 'inherit'
24
+ });
25
+ childProcess.on('error', error => {
26
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, error);
27
+ });
28
+ childProcess.on('exit', (code, signal) => {
29
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Child Process Exited with Code ${code} and Signal ${signal}`);
30
+ process.exit();
31
+ });
32
+ process.on('exit', () => {
33
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, 'Terminating Playwright Process...');
34
+ childProcess.kill();
35
+ return;
36
+ });
37
+ process.on('SIGINT', () => {
38
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, 'Cleaning up...');
39
+ childProcess.kill();
40
+ process.exit();
41
+ });
42
+ }
43
+ }
44
+ exports.default = PlaywrightReporter;
@@ -0,0 +1,27 @@
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 _child_process = require("child_process");
9
+ var _path = _interopRequireDefault(require("path"));
10
+ var _os = require("os");
11
+ var _logger = require("../../../utils/logger");
12
+ var _reporterConstants = _interopRequireDefault(require("../constants/reporterConstants"));
13
+ class UnitReporter {
14
+ static generate() {
15
+ const reportPath = _path.default.resolve(process.cwd(), _reporterConstants.default.DEFAULT_UNIT_TEST_REPORTER_PATH);
16
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, `Opening unit test report: ${reportPath}`);
17
+ const os = (0, _os.platform)();
18
+ const openCommand = os === 'darwin' ? 'open' : os === 'win32' ? 'start' : 'xdg-open';
19
+ (0, _child_process.execFile)(openCommand, [reportPath], error => {
20
+ if (error) {
21
+ _logger.Logger.log(_logger.Logger.FAILURE_TYPE, `Failed to open report: ${error.message}`);
22
+ }
23
+ process.exit();
24
+ });
25
+ }
26
+ }
27
+ exports.default = UnitReporter;
@@ -28,7 +28,7 @@ class SpawnRunner extends _Runner.default {
28
28
  }
29
29
  Promise.all(promises).then(() => this.runPlaywright()).catch(err => {
30
30
  _logger.Logger.error(err);
31
- process.exit();
31
+ process.exit(1);
32
32
  });
33
33
  }
34
34
 
@@ -15,6 +15,7 @@ var _readConfigFile = require("../readConfigFile");
15
15
  var _playwrightBdd = require("playwright-bdd");
16
16
  var _logger = require("../../../utils/logger");
17
17
  var _browserTypes = require("../constants/browserTypes");
18
+ var _browserTimeoutFactor = require("../helpers/browserTimeoutFactor");
18
19
  var _fileUtils = require("../../../utils/fileUtils");
19
20
  var _ConfigurationHelper = require("../configuration/ConfigurationHelper");
20
21
  var _configConstants = _interopRequireDefault(require("../constants/configConstants"));
@@ -69,11 +70,12 @@ function getBrowserConfig({
69
70
  dependencies
70
71
  };
71
72
  } else if (browser === 'firefox') {
73
+ const factor = (0, _browserTimeoutFactor.getBrowserTimeoutFactor)(_browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX);
72
74
  return {
73
75
  name: _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX,
74
- timeout: 2 * testTimeout,
76
+ timeout: factor * testTimeout,
75
77
  expect: {
76
- timeout: 2 * expectTimeout
78
+ timeout: factor * expectTimeout
77
79
  },
78
80
  use: {
79
81
  ..._test.devices['Desktop Firefox'],
@@ -82,11 +84,12 @@ function getBrowserConfig({
82
84
  dependencies
83
85
  };
84
86
  } else if (browser === 'safari') {
87
+ const factor = (0, _browserTimeoutFactor.getBrowserTimeoutFactor)(_browserTypes.BROWSER_PROJECT_MAPPING.SAFARI);
85
88
  return {
86
89
  name: _browserTypes.BROWSER_PROJECT_MAPPING.SAFARI,
87
- timeout: 4 * testTimeout,
90
+ timeout: factor * testTimeout,
88
91
  expect: {
89
- timeout: 4 * expectTimeout
92
+ timeout: factor * expectTimeout
90
93
  },
91
94
  use: {
92
95
  ..._test.devices['Desktop Safari'],
@@ -31,7 +31,7 @@
31
31
  * @property {any} reportPath : directory where report is generate
32
32
  * @property {boolean} bddMode: Feature files needs to be processed
33
33
  * @property {number} expectTimeout: time in milliseconds which the expect condition should fail
34
- * @property {number} testTimeout: time in milliseconds which the test should fail
34
+ * @property {number} testTimeout: time in milliseconds which the test should fail. Can be overridden per-scenario by tagging the scenario with `@timeout_<seconds>` (e.g. `@timeout_180`). `@timeout_0` disables the timeout. Browser scaling (Firefox 2x, Safari 4x) is preserved.
35
35
  * @property {Object} additionalPages: custom pages configuration
36
36
  * @property {string} featureFilesFolder: folder name under which feature-files will be placed. Default is feature-files
37
37
  * @property {string} stepDefinitionsFolder: folder name under which step implementations will be placed. Default is steps
package/build/lib/cli.js CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
  var _testRunner = _interopRequireDefault(require("../core/playwright/test-runner"));
5
- var _reportGenerator = _interopRequireDefault(require("../core/playwright/report-generator"));
5
+ var _unitTestingFramework = require("@zohodesk/unit-testing-framework");
6
+ var _PlaywrightReporter = _interopRequireDefault(require("../core/playwright/reporter/PlaywrightReporter"));
7
+ var _UnitReporter = _interopRequireDefault(require("../core/playwright/reporter/UnitReporter"));
6
8
  var _codegen = _interopRequireDefault(require("../core/playwright/codegen"));
7
9
  var _logger = require("../utils/logger");
8
10
  var _setupProject = _interopRequireDefault(require("../setup-folder-structure/setupProject"));
@@ -11,15 +13,24 @@ var _clearCaches = _interopRequireDefault(require("../core/playwright/clear-cach
11
13
  var _helper = _interopRequireDefault(require("../setup-folder-structure/helper"));
12
14
  var _parseUserArgs = _interopRequireDefault(require("../core/playwright/helpers/parseUserArgs"));
13
15
  var _validateFeature = _interopRequireDefault(require("../core/playwright/validateFeature"));
14
- // import createJestRunner from '../core/jest/runner/jest-runner';
15
-
16
+ var _commonUtils = require("../utils/commonUtils");
16
17
  const [,, option, ...otherOptions] = process.argv;
17
18
  switch (option) {
18
19
  case 'test':
19
20
  {
20
21
  _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Running Tests..');
21
22
  (0, _testRunner.default)();
22
- //createJestRunner();
23
+ break;
24
+ }
25
+ case 'unit-test':
26
+ {
27
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Running Unit Tests..');
28
+ (0, _unitTestingFramework.parseUnitTestArgs)(otherOptions).then(options => {
29
+ if (options.testPathPattern) {
30
+ _logger.Logger.log(_logger.Logger.INFO_TYPE, `Filtering tests with pattern: ${options.testPathPattern}`);
31
+ }
32
+ return (0, _unitTestingFramework.createJestRunner)(options);
33
+ });
23
34
  break;
24
35
  }
25
36
  case 'validate':
@@ -40,9 +51,14 @@ switch (option) {
40
51
  }
41
52
  case 'report':
42
53
  {
43
- // console.log('\x1b[36mGenerating Reports...\x1b[0m');
44
- _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Generating Reports...');
45
- (0, _reportGenerator.default)();
54
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Generating UAT Reports...');
55
+ _PlaywrightReporter.default.generate();
56
+ break;
57
+ }
58
+ case 'ut-report':
59
+ {
60
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Generating Unit Test Reports...');
61
+ _UnitReporter.default.generate();
46
62
  break;
47
63
  }
48
64
  case 'codegen':
@@ -69,6 +85,12 @@ switch (option) {
69
85
  (0, _clearCaches.default)();
70
86
  break;
71
87
  }
88
+ case 'stepsGenerator':
89
+ {
90
+ _logger.Logger.log(_logger.Logger.SUCCESS_TYPE, 'Created agents and prompts md files under .github folder...');
91
+ (0, _commonUtils.copyGithubFolder)();
92
+ break;
93
+ }
72
94
  case 'help':
73
95
  default:
74
96
  {
@@ -19,7 +19,7 @@ const testSetup = require('../../fixtures/testSetup');
19
19
  * @property {any} reportPath : directory where report is generate
20
20
  * @property {boolean} bddMode: Feature files needs to be processed
21
21
  * @property {number} expectTimeout: time in milliseconds which the expect condition should fail
22
- * @property {number} testTimeout: time in milliseconds which the test should fail
22
+ * @property {number} testTimeout: time in milliseconds which the test should fail. Can be overridden per-scenario by tagging the scenario with `@timeout_<seconds>` (e.g. `@timeout_180`). `@timeout_0` disables the timeout. Browser scaling (Firefox 2x, Safari 4x) is preserved.
23
23
  * @property {Object} additionalPages: custom pages configuration
24
24
  * @property {string} featureFilesFolder: folder name under which feature-files will be placed. Default is feature-files
25
25
  * @property {string} stepDefinitionsFolder: folder name under which step implementations will be placed. Default is steps
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _caseTimeout = _interopRequireDefault(require("../../../../../core/playwright/builtInFixtures/caseTimeout"));
5
+ var _caseTimeoutResolver = require("../../../../../core/playwright/helpers/caseTimeoutResolver");
6
+ var _browserTypes = require("../../../../../core/playwright/constants/browserTypes");
7
+ var _logger = require("../../../../../utils/logger");
8
+ jest.mock('../../../../../utils/logger');
9
+ describe('resolveCaseTimeoutMs', () => {
10
+ beforeEach(() => {
11
+ jest.clearAllMocks();
12
+ });
13
+ test('returns null when no timeout tag is present', () => {
14
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@smoke', '@edition_Free'], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBeNull();
15
+ });
16
+ test('returns null when tags is not an array', () => {
17
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(undefined, _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBeNull();
18
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(null, _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBeNull();
19
+ });
20
+ test('parses @timeout_<n> as seconds for Chrome (factor 1)', () => {
21
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_180'], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBe(180000);
22
+ });
23
+ test('applies Firefox 2x multiplier', () => {
24
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_180'], _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX)).toBe(360000);
25
+ });
26
+ test('returns 0 (no timeout) when tag is @timeout_0, regardless of browser', () => {
27
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_0'], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBe(0);
28
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_0'], _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX)).toBe(0);
29
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_0'], _browserTypes.BROWSER_PROJECT_MAPPING.SAFARI)).toBe(0);
30
+ });
31
+ test('uses the first matching tag and logs a warning when multiple are present', () => {
32
+ const result = (0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_120', '@timeout_300'], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME);
33
+ expect(result).toBe(120_000);
34
+ expect(_logger.Logger.log).toHaveBeenCalledWith(_logger.Logger.INFO_TYPE, expect.stringContaining('Multiple @timeout_* tags found'));
35
+ });
36
+ test('ignores malformed timeout-like tags', () => {
37
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_', '@timeout_abc', '@timeout_-5', '@timeoutfoo'], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBeNull();
38
+ });
39
+ test('ignores non-string entries in tags', () => {
40
+ expect((0, _caseTimeoutResolver.resolveCaseTimeoutMs)(['@timeout_60', null, undefined, 42], _browserTypes.BROWSER_PROJECT_MAPPING.CHROME)).toBe(60_000);
41
+ });
42
+ });
43
+ describe('caseTimeout fixture', () => {
44
+ beforeEach(() => {
45
+ jest.clearAllMocks();
46
+ });
47
+ function getFixture() {
48
+ return _caseTimeout.default.caseTimeout[0];
49
+ }
50
+ test('is registered as an auto fixture', () => {
51
+ expect(_caseTimeout.default.caseTimeout[1]).toEqual({
52
+ auto: true
53
+ });
54
+ });
55
+ test('calls testInfo.setTimeout with scaled value when tag matches', async () => {
56
+ const use = jest.fn();
57
+ const testInfo = {
58
+ project: {
59
+ name: _browserTypes.BROWSER_PROJECT_MAPPING.FIREFOX
60
+ },
61
+ setTimeout: jest.fn()
62
+ };
63
+ await getFixture()({
64
+ $tags: ['@timeout_30']
65
+ }, use, testInfo);
66
+ expect(testInfo.setTimeout).toHaveBeenCalledWith(60_000);
67
+ expect(use).toHaveBeenCalled();
68
+ });
69
+ test('does not call testInfo.setTimeout when no tag is present', async () => {
70
+ const use = jest.fn();
71
+ const testInfo = {
72
+ project: {
73
+ name: _browserTypes.BROWSER_PROJECT_MAPPING.CHROME
74
+ },
75
+ setTimeout: jest.fn()
76
+ };
77
+ await getFixture()({
78
+ $tags: ['@smoke']
79
+ }, use, testInfo);
80
+ expect(testInfo.setTimeout).not.toHaveBeenCalled();
81
+ expect(use).toHaveBeenCalled();
82
+ });
83
+ test('passes 0 through to testInfo.setTimeout for @timeout_0', async () => {
84
+ const use = jest.fn();
85
+ const testInfo = {
86
+ project: {
87
+ name: _browserTypes.BROWSER_PROJECT_MAPPING.SAFARI
88
+ },
89
+ setTimeout: jest.fn()
90
+ };
91
+ await getFixture()({
92
+ $tags: ['@timeout_0']
93
+ }, use, testInfo);
94
+ expect(testInfo.setTimeout).toHaveBeenCalledWith(0);
95
+ });
96
+ });