transit-core-taf 1.0.4 → 1.0.7

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 (34) hide show
  1. package/dist/transit-core-taf/baseapi/apiutils.d.ts +9 -0
  2. package/dist/transit-core-taf/baseapi/apiutils.js +23 -0
  3. package/dist/transit-core-taf/baseapi/baseapihelpers.d.ts +10 -0
  4. package/dist/transit-core-taf/baseapi/baseapihelpers.js +45 -0
  5. package/dist/transit-core-taf/baseui/basepageactions.d.ts +178 -0
  6. package/dist/transit-core-taf/baseui/basepageactions.js +288 -0
  7. package/dist/transit-core-taf/baseui/basepagevalidations.d.ts +309 -0
  8. package/dist/transit-core-taf/baseui/basepagevalidations.js +478 -0
  9. package/dist/transit-core-taf/baseui/basepagewaits.d.ts +71 -0
  10. package/dist/transit-core-taf/baseui/basepagewaits.js +202 -0
  11. package/dist/transit-core-taf/baseui/commonpageactions.d.ts +40 -0
  12. package/dist/transit-core-taf/baseui/commonpageactions.js +118 -0
  13. package/dist/transit-core-taf/baseui/commonpagevalidations.d.ts +10 -0
  14. package/dist/transit-core-taf/baseui/commonpagevalidations.js +21 -0
  15. package/dist/transit-core-taf/baseui/commonpagewaits.d.ts +28 -0
  16. package/dist/transit-core-taf/baseui/commonpagewaits.js +57 -0
  17. package/dist/transit-core-taf/baseui/logger.d.ts +10 -0
  18. package/dist/transit-core-taf/baseui/logger.js +42 -0
  19. package/dist/transit-core-taf/constants/test-tags.d.ts +4 -0
  20. package/dist/transit-core-taf/constants/test-tags.js +7 -0
  21. package/dist/transit-core-taf/fixtures.d.ts +20 -0
  22. package/dist/transit-core-taf/fixtures.js +58 -0
  23. package/dist/transit-core-taf/global-setup.d.ts +2 -0
  24. package/dist/transit-core-taf/global-setup.js +103 -0
  25. package/dist/transit-core-taf/index.d.ts +13 -0
  26. package/dist/transit-core-taf/index.js +29 -0
  27. package/dist/transit-core-taf/reporters/testrail-reporter.d.ts +11 -0
  28. package/dist/transit-core-taf/reporters/testrail-reporter.js +79 -0
  29. package/dist/transit-core-taf/utils/Utils.d.ts +114 -0
  30. package/dist/transit-core-taf/utils/Utils.js +219 -0
  31. package/dist/transit-core-taf/utils/testrail/client.d.ts +15 -0
  32. package/dist/transit-core-taf/utils/testrail/client.js +71 -0
  33. package/package.json +10 -4
  34. package/README.md +0 -286
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const dotenv = __importStar(require("dotenv"));
40
+ const path_1 = __importDefault(require("path"));
41
+ const fs = __importStar(require("fs"));
42
+ // Function to find the project root
43
+ const findProjectRoot = (startPath) => {
44
+ let currentPath = startPath;
45
+ while (currentPath !== path_1.default.parse(currentPath).root) {
46
+ if (fs.existsSync(path_1.default.join(currentPath, 'package.json'))) {
47
+ return currentPath;
48
+ }
49
+ currentPath = path_1.default.dirname(currentPath);
50
+ }
51
+ return startPath; // Fallback to the original directory if not found
52
+ };
53
+ async function globalSetup() {
54
+ const env = process.env.ENV || 'stage';
55
+ const projectRoot = path_1.default.resolve(__dirname, '..');
56
+ const envPath = path_1.default.join(projectRoot, `.env.${env}`);
57
+ // Load env file
58
+ if (fs.existsSync(envPath)) {
59
+ dotenv.config({ path: envPath, override: true });
60
+ console.log(`✅ Loaded ${envPath} from project root ${projectRoot} ✅`);
61
+ }
62
+ else {
63
+ throw new Error(`❌ Environment file .env.${env} not found in project root ${projectRoot} ❌`);
64
+ }
65
+ const argv = process.argv;
66
+ // Find all arguments related to project selection
67
+ const projectArgs = argv.map((arg, i) => {
68
+ if (arg === '--project' && i + 1 < argv.length) {
69
+ return argv[i + 1];
70
+ }
71
+ if (arg.startsWith('--project=')) {
72
+ return arg.split('=')[1];
73
+ }
74
+ return null;
75
+ }).filter(p => p !== null);
76
+ let runAuth = false;
77
+ if (projectArgs.length > 0) {
78
+ // --project flag is used. Only run if 'api-tests' is specified.
79
+ if (projectArgs.includes('api-tests')) {
80
+ runAuth = true;
81
+ }
82
+ }
83
+ else {
84
+ // No --project flag. Check for test path arguments.
85
+ const testCommandIndex = argv.indexOf('test');
86
+ const argsAfterTest = testCommandIndex !== -1 ? argv.slice(testCommandIndex + 1) : [];
87
+ const pathArgs = argsAfterTest.filter(arg => !arg.startsWith('-'));
88
+ if (pathArgs.length === 0) {
89
+ // No path arguments, so it's a full run.
90
+ runAuth = true;
91
+ }
92
+ else {
93
+ // Path arguments are present. Check if any are in the api-tests directory.
94
+ if (pathArgs.some(p => p.startsWith('tests/api-tests'))) {
95
+ runAuth = true;
96
+ }
97
+ }
98
+ }
99
+ if (runAuth) {
100
+ console.log('Global setup for api-tests is running...');
101
+ }
102
+ }
103
+ exports.default = globalSetup;
@@ -0,0 +1,13 @@
1
+ export * from './baseui/basepagevalidations';
2
+ export * from './baseui/basepageactions';
3
+ export * from './baseui/basepagewaits';
4
+ export * from './baseui/commonpageactions';
5
+ export * from './baseui/commonpagevalidations';
6
+ export * from './baseui/commonpagewaits';
7
+ export * from './baseui/logger';
8
+ export * from './utils/Utils';
9
+ export * from './baseapi/baseapihelpers';
10
+ export * from './baseapi/apiutils';
11
+ export * from './constants/test-tags';
12
+ export * from './reporters/testrail-reporter';
13
+ export * from './utils/testrail/client';
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./baseui/basepagevalidations"), exports);
18
+ __exportStar(require("./baseui/basepageactions"), exports);
19
+ __exportStar(require("./baseui/basepagewaits"), exports);
20
+ __exportStar(require("./baseui/commonpageactions"), exports);
21
+ __exportStar(require("./baseui/commonpagevalidations"), exports);
22
+ __exportStar(require("./baseui/commonpagewaits"), exports);
23
+ __exportStar(require("./baseui/logger"), exports);
24
+ __exportStar(require("./utils/Utils"), exports);
25
+ __exportStar(require("./baseapi/baseapihelpers"), exports);
26
+ __exportStar(require("./baseapi/apiutils"), exports);
27
+ __exportStar(require("./constants/test-tags"), exports);
28
+ __exportStar(require("./reporters/testrail-reporter"), exports);
29
+ __exportStar(require("./utils/testrail/client"), exports);
@@ -0,0 +1,11 @@
1
+ import { Reporter, FullConfig, Suite, TestCase, TestResult } from '@playwright/test/reporter';
2
+ declare class TestRailReporter implements Reporter {
3
+ private client;
4
+ private runId;
5
+ private suiteId;
6
+ private enabled;
7
+ constructor();
8
+ onBegin(config: FullConfig, suite: Suite): Promise<void>;
9
+ onTestEnd(test: TestCase, result: TestResult): Promise<void>;
10
+ }
11
+ export default TestRailReporter;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const client_1 = require("@/utils/testrail/client");
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ dotenv_1.default.config();
9
+ class TestRailReporter {
10
+ client = null;
11
+ runId = null;
12
+ suiteId = null;
13
+ enabled = false;
14
+ constructor() {
15
+ if (process.env.TESTRAIL_REPORTER_ENABLED === 'true') {
16
+ this.enabled = true;
17
+ try {
18
+ const host = process.env.TESTRAIL_HOST;
19
+ const user = process.env.TESTRAIL_USER;
20
+ const token = process.env.TESTRAIL_PASSWORD;
21
+ const projectId = process.env.TESTRAIL_PROJECT_ID;
22
+ if (!host || !user || !token || !projectId) {
23
+ throw new Error('TestRail credentials are not fully set in environment variables.');
24
+ }
25
+ this.client = new client_1.TestRailClient(host, user, token, projectId);
26
+ const suiteIdEnv = process.env.TESTRAIL_SUITE_ID;
27
+ if (!suiteIdEnv) {
28
+ throw new Error('TESTRAIL_SUITE_ID environment variable is not set.');
29
+ }
30
+ this.suiteId = parseInt(suiteIdEnv, 10);
31
+ if (isNaN(this.suiteId)) {
32
+ throw new Error('TESTRAIL_SUITE_ID is not a valid number.');
33
+ }
34
+ }
35
+ catch (error) {
36
+ console.error('Failed to initialize TestRail reporter:', error);
37
+ this.enabled = false;
38
+ }
39
+ }
40
+ else {
41
+ console.log("TestRail reporter is disabled. Set TESTRAIL_REPORTER_ENABLED to 'true' to enable.");
42
+ }
43
+ }
44
+ async onBegin(config, suite) {
45
+ if (!this.enabled || !this.client || !this.suiteId)
46
+ return;
47
+ const timestamp = new Date().toLocaleString();
48
+ const runName = `Automated Test Run - ${timestamp}`;
49
+ const runDescription = `Playwright test run executed on ${timestamp}`;
50
+ try {
51
+ const run = await this.client.createTestRun(this.suiteId, runName, runDescription);
52
+ this.runId = run.id;
53
+ }
54
+ catch (error) {
55
+ console.error('Failed to create TestRail test run. Disabling reporter.');
56
+ this.enabled = false;
57
+ }
58
+ }
59
+ async onTestEnd(test, result) {
60
+ if (!this.enabled || !this.client || !this.runId)
61
+ return;
62
+ const caseIdRegex = /C(\d+)/;
63
+ const match = test.title.match(caseIdRegex);
64
+ if (match) {
65
+ const caseId = parseInt(match[1], 10);
66
+ const comment = result.status === 'failed' || result.status === 'timedOut'
67
+ ? `Test failed with error: ${result.error?.message}`
68
+ : `Test completed with status: ${result.status}`;
69
+ try {
70
+ await this.client.addResultForCase(this.runId, caseId, result.status, comment);
71
+ console.log(`Successfully reported result for Case C${caseId} to TestRail.`);
72
+ }
73
+ catch (error) {
74
+ console.error(`Failed to report result for Case C${caseId}.`);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ exports.default = TestRailReporter;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Generates a random alphanumeric string of specified length.
3
+ * @param {number} length - The number of characters in the generated string.
4
+ * @returns {string} - Randomly generated string.
5
+ */
6
+ export declare function generateRandomString(length: number): string;
7
+ /**
8
+ * Generates a random first name.
9
+ * @returns A random first name.
10
+ */
11
+ export declare function generateFirstName(): string;
12
+ /**
13
+ * Generates a random last name.
14
+ * @returns A random last name.
15
+ */
16
+ export declare function generateLastName(): string;
17
+ /**
18
+ * Generates a random household name.
19
+ * @returns A random household name, typically in the format "[LastName] Household".
20
+ */
21
+ export declare function generateHouseholdName(): string;
22
+ /**
23
+ * Generates a dynamic US address.
24
+ * @returns An object containing a full US address.
25
+ */
26
+ export declare function generateUSAddress(): {
27
+ streetAddressLine1: string;
28
+ streetAddressLine2: string;
29
+ city: string;
30
+ state: string;
31
+ zipCode: string;
32
+ country: string;
33
+ };
34
+ /**
35
+ * Generates a random phone number for a given country.
36
+ * @param country - The country for which to generate the phone number.
37
+ * @returns A random phone number.
38
+ */
39
+ export declare function generatePhoneNumber(country: string): string;
40
+ /**
41
+ * Generates a random email address with the yopmail.com domain.
42
+ * @returns A random email address.
43
+ */
44
+ export declare function generateYopmailEmail(): string;
45
+ /**
46
+ * Returns the current timestamp.
47
+ * @returns The current timestamp in milliseconds.
48
+ */
49
+ export declare function getTimestamp(): number;
50
+ /**
51
+ * Calculates the time difference between two timestamps and returns a formatted string.
52
+ * @param startTime - The starting timestamp in milliseconds.
53
+ * @param endTime - The ending timestamp in milliseconds.
54
+ * @returns A formatted string like "5 sec 34 ms".
55
+ */
56
+ export declare function getTimeDifference(startTime: number, endTime: number): string;
57
+ export declare function readAccountApiResponse(accountId: string): any;
58
+ /**
59
+ * Generates a random integer between 0 (inclusive) and the given length (exclusive).
60
+ * @param {number} length - The upper bound (non-inclusive) for the random number.
61
+ * If less than or equal to 0, the function returns 0.
62
+ * @returns {number} A random integer between 0 and length - 1, or 0 if length <= 0.
63
+ */
64
+ export declare function getRandomNumber(length: number): number;
65
+ /**
66
+ * Generates a random future date.
67
+ * @returns An object containing the day, month, and year of a random future date.
68
+ */
69
+ export declare function generateRandomFutureDate(): {
70
+ day: number;
71
+ month: number;
72
+ year: number;
73
+ };
74
+ /**
75
+ * @description
76
+ * This function provides flexible date formatting similar to moment.js.
77
+ * It supports both padded (e.g., 03) and unpadded (e.g., 3) date/time tokens.
78
+ * Ideal for logs, filenames, UI display, or readable timestamps.
79
+ *
80
+ * 🧩 Supported format tokens:
81
+ * ┌────────┬────────────────────────────┐
82
+ * │ Token │ Description │
83
+ * ├────────┼────────────────────────────┤
84
+ * │ YYYY │ 4-digit year (e.g. 2025) │
85
+ * │ M │ Month (1–12) │
86
+ * │ MM │ Month (01–12) │
87
+ * │ D │ Day of month (1–31) │
88
+ * │ DD │ Day of month (01–31) │
89
+ * │ h │ Hour (0–23) │
90
+ * │ hh │ Hour (00–23) │
91
+ * │ m │ Minute (0–59) │
92
+ * │ mm │ Minute (00–59) │
93
+ * │ s │ Second (0–59) │
94
+ * │ ss │ Second (00–59) │
95
+ * └────────┴────────────────────────────┘
96
+ *
97
+ * @examples
98
+ * getDate("YYYY-MM-DD hh:mm:ss") → "2025-11-03 04:05:09"
99
+ * getDate("YYYY-M-D h:m:s") → "2025-11-3 4:5:9"
100
+ * getDate("D/M/YYYY") → "3/11/2025"
101
+ *
102
+ * @param format - (Optional) The desired date format string. Defaults to "YYYY-MM-DD".
103
+ * @returns A formatted date/time string.
104
+ */
105
+ export declare function getDate(format?: string): string;
106
+ /**
107
+ * Normalizes a date input to a timestamp (ms since epoch).
108
+ * - If input is a string, it will be parsed with Date.parse().
109
+ * - If input is a number (timestamp), it will be used directly.
110
+ *
111
+ * @param input Date as a timestamp (ms) or string
112
+ * @returns timestamp in milliseconds
113
+ */
114
+ export declare function getParsedDate(input: number | string | null | undefined): number;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateRandomString = generateRandomString;
7
+ exports.generateFirstName = generateFirstName;
8
+ exports.generateLastName = generateLastName;
9
+ exports.generateHouseholdName = generateHouseholdName;
10
+ exports.generateUSAddress = generateUSAddress;
11
+ exports.generatePhoneNumber = generatePhoneNumber;
12
+ exports.generateYopmailEmail = generateYopmailEmail;
13
+ exports.getTimestamp = getTimestamp;
14
+ exports.getTimeDifference = getTimeDifference;
15
+ exports.readAccountApiResponse = readAccountApiResponse;
16
+ exports.getRandomNumber = getRandomNumber;
17
+ exports.generateRandomFutureDate = generateRandomFutureDate;
18
+ exports.getDate = getDate;
19
+ exports.getParsedDate = getParsedDate;
20
+ const faker_1 = require("@faker-js/faker");
21
+ const fs_1 = __importDefault(require("fs"));
22
+ const path_1 = __importDefault(require("path"));
23
+ /**
24
+ * Generates a random alphanumeric string of specified length.
25
+ * @param {number} length - The number of characters in the generated string.
26
+ * @returns {string} - Randomly generated string.
27
+ */
28
+ function generateRandomString(length) {
29
+ // Define the characters to choose from: uppercase, lowercase, and digits
30
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
31
+ let result = ''; // Initialize the result string
32
+ const charsLength = chars.length; // Total number of characters available
33
+ // Loop 'length' times to build the result string
34
+ for (let i = 0; i < length; i++) {
35
+ // Pick a random index and append the corresponding character to the result
36
+ result += chars.charAt(Math.floor(Math.random() * charsLength));
37
+ }
38
+ return result; // Return the generated string
39
+ }
40
+ /**
41
+ * Generates a random first name.
42
+ * @returns A random first name.
43
+ */
44
+ function generateFirstName() {
45
+ const firstName = faker_1.faker.person.firstName();
46
+ return firstName;
47
+ }
48
+ /**
49
+ * Generates a random last name.
50
+ * @returns A random last name.
51
+ */
52
+ function generateLastName() {
53
+ const lastName = faker_1.faker.person.lastName();
54
+ return lastName;
55
+ }
56
+ /**
57
+ * Generates a random household name.
58
+ * @returns A random household name, typically in the format "[LastName] Household".
59
+ */
60
+ function generateHouseholdName() {
61
+ const householdName = `${faker_1.faker.person.lastName()} Household`;
62
+ console.log(`Generated household name: ${householdName}`);
63
+ return householdName;
64
+ }
65
+ /**
66
+ * Generates a dynamic US address.
67
+ * @returns An object containing a full US address.
68
+ */
69
+ function generateUSAddress() {
70
+ const state = faker_1.faker.location.state({ abbreviated: true });
71
+ const city = faker_1.faker.location.city();
72
+ const zipCode = faker_1.faker.location.zipCode();
73
+ const streetAddress = faker_1.faker.location.streetAddress();
74
+ const secondaryAddress = faker_1.faker.location.secondaryAddress();
75
+ console.log(`Generated US address: ${streetAddress}, ${secondaryAddress}, ${city}, ${state} ${zipCode}`);
76
+ return {
77
+ streetAddressLine1: streetAddress,
78
+ streetAddressLine2: secondaryAddress,
79
+ city,
80
+ state,
81
+ zipCode,
82
+ country: 'United States',
83
+ };
84
+ }
85
+ /**
86
+ * Generates a random phone number for a given country.
87
+ * @param country - The country for which to generate the phone number.
88
+ * @returns A random phone number.
89
+ */
90
+ function generatePhoneNumber(country) {
91
+ // Note: Faker's phone number generation is not strictly country-specific for all locales.
92
+ // It generates a number in a format common to the locale.
93
+ return faker_1.faker.phone.number();
94
+ }
95
+ /**
96
+ * Generates a random email address with the yopmail.com domain.
97
+ * @returns A random email address.
98
+ */
99
+ function generateYopmailEmail() {
100
+ return `${faker_1.faker.internet.userName()}@yopmail.com`;
101
+ }
102
+ /**
103
+ * Returns the current timestamp.
104
+ * @returns The current timestamp in milliseconds.
105
+ */
106
+ function getTimestamp() {
107
+ return Date.now();
108
+ }
109
+ /**
110
+ * Calculates the time difference between two timestamps and returns a formatted string.
111
+ * @param startTime - The starting timestamp in milliseconds.
112
+ * @param endTime - The ending timestamp in milliseconds.
113
+ * @returns A formatted string like "5 sec 34 ms".
114
+ */
115
+ function getTimeDifference(startTime, endTime) {
116
+ const diff = endTime - startTime;
117
+ const seconds = Math.floor(diff / 1000);
118
+ const milliseconds = diff % 1000;
119
+ return `${seconds} sec ${milliseconds}ms`;
120
+ }
121
+ function readAccountApiResponse(accountId) {
122
+ try {
123
+ const filePath = path_1.default.join(__dirname, `../resources/apiresponses/accounts/${process.env.ENV}/${accountId}.json`);
124
+ const fileContent = fs_1.default.readFileSync(filePath, 'utf-8');
125
+ return JSON.parse(fileContent);
126
+ }
127
+ catch (error) {
128
+ console.error(`Error loading account API response for accountId: ${accountId}`, error);
129
+ throw new Error(`Could not find or load API response for accountId: ${accountId}`);
130
+ }
131
+ }
132
+ /**
133
+ * Generates a random integer between 0 (inclusive) and the given length (exclusive).
134
+ * @param {number} length - The upper bound (non-inclusive) for the random number.
135
+ * If less than or equal to 0, the function returns 0.
136
+ * @returns {number} A random integer between 0 and length - 1, or 0 if length <= 0.
137
+ */
138
+ function getRandomNumber(length) {
139
+ if (length <= 0)
140
+ return 0;
141
+ return Math.floor(Math.random() * length);
142
+ }
143
+ /**
144
+ * Generates a random future date.
145
+ * @returns An object containing the day, month, and year of a random future date.
146
+ */
147
+ function generateRandomFutureDate() {
148
+ const today = new Date();
149
+ const futureDate = new Date(today);
150
+ futureDate.setDate(today.getDate() + Math.floor(Math.random() * 365) + 1);
151
+ return {
152
+ day: futureDate.getDate(),
153
+ month: futureDate.getMonth() + 1,
154
+ year: futureDate.getFullYear(),
155
+ };
156
+ }
157
+ /**
158
+ * @description
159
+ * This function provides flexible date formatting similar to moment.js.
160
+ * It supports both padded (e.g., 03) and unpadded (e.g., 3) date/time tokens.
161
+ * Ideal for logs, filenames, UI display, or readable timestamps.
162
+ *
163
+ * 🧩 Supported format tokens:
164
+ * ┌────────┬────────────────────────────┐
165
+ * │ Token │ Description │
166
+ * ├────────┼────────────────────────────┤
167
+ * │ YYYY │ 4-digit year (e.g. 2025) │
168
+ * │ M │ Month (1–12) │
169
+ * │ MM │ Month (01–12) │
170
+ * │ D │ Day of month (1–31) │
171
+ * │ DD │ Day of month (01–31) │
172
+ * │ h │ Hour (0–23) │
173
+ * │ hh │ Hour (00–23) │
174
+ * │ m │ Minute (0–59) │
175
+ * │ mm │ Minute (00–59) │
176
+ * │ s │ Second (0–59) │
177
+ * │ ss │ Second (00–59) │
178
+ * └────────┴────────────────────────────┘
179
+ *
180
+ * @examples
181
+ * getDate("YYYY-MM-DD hh:mm:ss") → "2025-11-03 04:05:09"
182
+ * getDate("YYYY-M-D h:m:s") → "2025-11-3 4:5:9"
183
+ * getDate("D/M/YYYY") → "3/11/2025"
184
+ *
185
+ * @param format - (Optional) The desired date format string. Defaults to "YYYY-MM-DD".
186
+ * @returns A formatted date/time string.
187
+ */
188
+ function getDate(format = "YYYY-MM-DD") {
189
+ const date = new Date();
190
+ const parts = {
191
+ YYYY: date.getFullYear().toString(),
192
+ M: (date.getMonth() + 1).toString(),
193
+ MM: String(date.getMonth() + 1).padStart(2, "0"),
194
+ D: date.getDate().toString(),
195
+ DD: String(date.getDate()).padStart(2, "0"),
196
+ h: date.getHours().toString(),
197
+ hh: String(date.getHours()).padStart(2, "0"),
198
+ m: date.getMinutes().toString(),
199
+ mm: String(date.getMinutes()).padStart(2, "0"),
200
+ s: date.getSeconds().toString(),
201
+ ss: String(date.getSeconds()).padStart(2, "0"),
202
+ };
203
+ return format.replace(/(YYYY|MM|M|DD|D|hh|h|mm|m|ss|s)/g, (token) => parts[token]);
204
+ }
205
+ /**
206
+ * Normalizes a date input to a timestamp (ms since epoch).
207
+ * - If input is a string, it will be parsed with Date.parse().
208
+ * - If input is a number (timestamp), it will be used directly.
209
+ *
210
+ * @param input Date as a timestamp (ms) or string
211
+ * @returns timestamp in milliseconds
212
+ */
213
+ function getParsedDate(input) {
214
+ if (input == null)
215
+ return NaN;
216
+ if (typeof input === "number")
217
+ return input;
218
+ return Date.parse(input);
219
+ }
@@ -0,0 +1,15 @@
1
+ declare const statusMap: {
2
+ [key: string]: number;
3
+ };
4
+ export declare class TestRailClient {
5
+ private host;
6
+ private user;
7
+ private token;
8
+ private projectId;
9
+ private auth;
10
+ constructor(host: string, user: string, token: string, projectId: string);
11
+ private apiPost;
12
+ createTestRun(suiteId: number, name: string, description: string): Promise<any>;
13
+ addResultForCase(runId: number, caseId: number, status: keyof typeof statusMap, comment?: string): Promise<any>;
14
+ }
15
+ export {};
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TestRailClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const statusMap = {
9
+ passed: 1,
10
+ failed: 5,
11
+ timedOut: 5,
12
+ skipped: 2, // Mapped to 'Blocked'
13
+ };
14
+ class TestRailClient {
15
+ host;
16
+ user;
17
+ token;
18
+ projectId;
19
+ auth;
20
+ constructor(host, user, token, projectId) {
21
+ if (!host || !user || !token || !projectId) {
22
+ throw new Error('TestRail host, user, token, or project ID is missing.');
23
+ }
24
+ this.host = host;
25
+ this.user = user;
26
+ this.token = token;
27
+ this.projectId = projectId;
28
+ this.auth = `Basic ${Buffer.from(`${this.user}:${this.token}`).toString('base64')}`;
29
+ }
30
+ async apiPost(endpoint, data) {
31
+ const url = `${this.host}index.php?/api/v2/${endpoint}`;
32
+ try {
33
+ const response = await axios_1.default.post(url, data, {
34
+ headers: {
35
+ 'Content-Type': 'application/json',
36
+ Authorization: this.auth,
37
+ },
38
+ });
39
+ return response.data;
40
+ }
41
+ catch (error) {
42
+ console.error(`TestRail API Error: Failed to post to ${endpoint}.`, error.response ? error.response.data : error.message);
43
+ throw error;
44
+ }
45
+ }
46
+ async createTestRun(suiteId, name, description) {
47
+ console.log(`Creating TestRail Test Run for project ID: ${this.projectId}...`);
48
+ const data = {
49
+ suite_id: suiteId,
50
+ name,
51
+ description,
52
+ include_all: true,
53
+ };
54
+ const run = await this.apiPost(`add_run/${this.projectId}`, data);
55
+ console.log(`Successfully created Test Run with ID: ${run.id}`);
56
+ return run;
57
+ }
58
+ async addResultForCase(runId, caseId, status, comment) {
59
+ const status_id = statusMap[status];
60
+ if (status_id === undefined) {
61
+ console.warn(`Unknown test status: ${status}. Skipping TestRail update.`);
62
+ return;
63
+ }
64
+ const data = { status_id };
65
+ if (comment) {
66
+ data.comment = comment;
67
+ }
68
+ return this.apiPost(`add_result_for_case/${runId}/${caseId}`, data);
69
+ }
70
+ }
71
+ exports.TestRailClient = TestRailClient;