@playq/core 0.2.77
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 +41 -0
- package/bin/playq.js +175 -0
- package/cucumber.js +10 -0
- package/dist/exec/featureFileCache.d.ts +21 -0
- package/dist/exec/featureFileCache.js +124 -0
- package/dist/exec/featureFilePreProcess.d.ts +12 -0
- package/dist/exec/featureFilePreProcess.js +208 -0
- package/dist/exec/preLoader.d.ts +1 -0
- package/dist/exec/preLoader.js +72 -0
- package/dist/exec/preProcessEntry.d.ts +1 -0
- package/dist/exec/preProcessEntry.js +83 -0
- package/dist/exec/preProcess_old_todelete.d.ts +1 -0
- package/dist/exec/preProcess_old_todelete.js +258 -0
- package/dist/exec/runner.d.ts +1 -0
- package/dist/exec/runner.js +221 -0
- package/dist/exec/runner_orchestrator.d.ts +1 -0
- package/dist/exec/runner_orchestrator.js +85 -0
- package/dist/exec/sgGenerator.d.ts +11 -0
- package/dist/exec/sgGenerator.js +310 -0
- package/dist/global.d.ts +15 -0
- package/dist/global.js +185 -0
- package/dist/helper/actions/api/apiRequestActions.d.ts +117 -0
- package/dist/helper/actions/api/apiRequestActions.js +374 -0
- package/dist/helper/actions/api/apiValidationActions.d.ts +119 -0
- package/dist/helper/actions/api/apiValidationActions.js +615 -0
- package/dist/helper/actions/apiActions.d.ts +18 -0
- package/dist/helper/actions/apiActions.js +34 -0
- package/dist/helper/actions/apiStepDefs.d.ts +1 -0
- package/dist/helper/actions/apiStepDefs.js +64 -0
- package/dist/helper/actions/comm/commonActions.d.ts +58 -0
- package/dist/helper/actions/comm/commonActions.js +198 -0
- package/dist/helper/actions/comm/utilityActions.d.ts +131 -0
- package/dist/helper/actions/comm/utilityActions.js +351 -0
- package/dist/helper/actions/commActions.d.ts +18 -0
- package/dist/helper/actions/commActions.js +34 -0
- package/dist/helper/actions/commStepDefs.d.ts +1 -0
- package/dist/helper/actions/commStepDefs.js +57 -0
- package/dist/helper/actions/stepGroupStepDefs.d.ts +1 -0
- package/dist/helper/actions/stepGroupStepDefs.js +15 -0
- package/dist/helper/actions/web/alertActions.d.ts +61 -0
- package/dist/helper/actions/web/alertActions.js +224 -0
- package/dist/helper/actions/web/cookieActions.d.ts +45 -0
- package/dist/helper/actions/web/cookieActions.js +186 -0
- package/dist/helper/actions/web/downloadActions.d.ts +40 -0
- package/dist/helper/actions/web/downloadActions.js +153 -0
- package/dist/helper/actions/web/elementReaderActions.d.ts +95 -0
- package/dist/helper/actions/web/elementReaderActions.js +326 -0
- package/dist/helper/actions/web/formActions.d.ts +122 -0
- package/dist/helper/actions/web/formActions.js +423 -0
- package/dist/helper/actions/web/iframeActions.d.ts +23 -0
- package/dist/helper/actions/web/iframeActions.js +108 -0
- package/dist/helper/actions/web/javascriptActions.d.ts +14 -0
- package/dist/helper/actions/web/javascriptActions.js +77 -0
- package/dist/helper/actions/web/keyboardActions.d.ts +35 -0
- package/dist/helper/actions/web/keyboardActions.js +118 -0
- package/dist/helper/actions/web/localStorageActions.d.ts +51 -0
- package/dist/helper/actions/web/localStorageActions.js +163 -0
- package/dist/helper/actions/web/mouseActions.d.ts +240 -0
- package/dist/helper/actions/web/mouseActions.js +609 -0
- package/dist/helper/actions/web/reportingActions.d.ts +34 -0
- package/dist/helper/actions/web/reportingActions.js +58 -0
- package/dist/helper/actions/web/screenshotActions.d.ts +34 -0
- package/dist/helper/actions/web/screenshotActions.js +151 -0
- package/dist/helper/actions/web/testDataActions.d.ts +21 -0
- package/dist/helper/actions/web/testDataActions.js +211 -0
- package/dist/helper/actions/web/validationActions.d.ts +547 -0
- package/dist/helper/actions/web/validationActions.js +1754 -0
- package/dist/helper/actions/web/waitActions.d.ts +191 -0
- package/dist/helper/actions/web/waitActions.js +589 -0
- package/dist/helper/actions/web/webNavigation.d.ts +104 -0
- package/dist/helper/actions/web/webNavigation.js +288 -0
- package/dist/helper/actions/webActions.d.ts +32 -0
- package/dist/helper/actions/webActions.js +48 -0
- package/dist/helper/actions/webStepDefs.d.ts +1 -0
- package/dist/helper/actions/webStepDefs.js +455 -0
- package/dist/helper/browsers/browserManager.d.ts +1 -0
- package/dist/helper/browsers/browserManager.js +56 -0
- package/dist/helper/bundle/defaultEntries.d.ts +6 -0
- package/dist/helper/bundle/defaultEntries.js +200 -0
- package/dist/helper/bundle/env.d.ts +1 -0
- package/dist/helper/bundle/env.js +157 -0
- package/dist/helper/bundle/vars.d.ts +9 -0
- package/dist/helper/bundle/vars.js +375 -0
- package/dist/helper/faker/customFaker.d.ts +55 -0
- package/dist/helper/faker/customFaker.js +45 -0
- package/dist/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
- package/dist/helper/faker/modules/dateTime.d.ts +18 -0
- package/dist/helper/faker/modules/dateTime.js +106 -0
- package/dist/helper/faker/modules/mobile.d.ts +4 -0
- package/dist/helper/faker/modules/mobile.js +59 -0
- package/dist/helper/faker/modules/nric.d.ts +32 -0
- package/dist/helper/faker/modules/nric.js +84 -0
- package/dist/helper/faker/modules/passport.d.ts +3 -0
- package/dist/helper/faker/modules/passport.js +36 -0
- package/dist/helper/faker/modules/person.d.ts +14 -0
- package/dist/helper/faker/modules/person.js +73 -0
- package/dist/helper/faker/modules/postcode.d.ts +6 -0
- package/dist/helper/faker/modules/postcode.js +47 -0
- package/dist/helper/fixtures/locAggregate.d.ts +7 -0
- package/dist/helper/fixtures/locAggregate.js +94 -0
- package/dist/helper/fixtures/logFixture.d.ts +8 -0
- package/dist/helper/fixtures/logFixture.js +56 -0
- package/dist/helper/fixtures/webFixture.d.ts +19 -0
- package/dist/helper/fixtures/webFixture.js +186 -0
- package/dist/helper/fixtures/webLocFixture.d.ts +2 -0
- package/dist/helper/fixtures/webLocFixture.js +144 -0
- package/dist/helper/report/allureStepLogger.d.ts +0 -0
- package/dist/helper/report/allureStepLogger.js +25 -0
- package/dist/helper/report/customiseReport.d.ts +1 -0
- package/dist/helper/report/customiseReport.js +55 -0
- package/dist/helper/report/init.d.ts +1 -0
- package/dist/helper/report/init.js +14 -0
- package/dist/helper/report/report.d.ts +1 -0
- package/dist/helper/report/report.js +102 -0
- package/dist/helper/util/dataLoader.d.ts +10 -0
- package/dist/helper/util/dataLoader.js +73 -0
- package/dist/helper/util/logger.d.ts +4 -0
- package/dist/helper/util/logger.js +61 -0
- package/dist/helper/util/session/sessionUtil.d.ts +26 -0
- package/dist/helper/util/session/sessionUtil.js +729 -0
- package/dist/helper/util/stepHelpers.d.ts +2 -0
- package/dist/helper/util/stepHelpers.js +16 -0
- package/dist/helper/util/test-data/dataLoader.d.ts +7 -0
- package/dist/helper/util/test-data/dataLoader.js +145 -0
- package/dist/helper/util/test-data/dataTest.d.ts +10 -0
- package/dist/helper/util/test-data/dataTest.js +216 -0
- package/dist/helper/util/totp/totpHelper.d.ts +38 -0
- package/dist/helper/util/totp/totpHelper.js +117 -0
- package/dist/helper/util/utilities/cryptoUtil.d.ts +2 -0
- package/dist/helper/util/utilities/cryptoUtil.js +53 -0
- package/dist/helper/util/utilities/schemaGeneratorUtil.d.ts +2 -0
- package/dist/helper/util/utilities/schemaGeneratorUtil.js +129 -0
- package/dist/helper/util/utils.d.ts +2 -0
- package/dist/helper/util/utils.js +22 -0
- package/dist/helper/wrapper/PlaywrightWrappers.d.ts +8 -0
- package/dist/helper/wrapper/PlaywrightWrappers.js +26 -0
- package/dist/helper/wrapper/assert.d.ts +9 -0
- package/dist/helper/wrapper/assert.js +23 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +57 -0
- package/dist/scripts/get-versions.d.ts +1 -0
- package/dist/scripts/get-versions.js +98 -0
- package/dist/scripts/posttest.d.ts +1 -0
- package/dist/scripts/posttest.js +29 -0
- package/dist/scripts/pretest.d.ts +1 -0
- package/dist/scripts/pretest.js +57 -0
- package/dist/scripts/util.d.ts +1 -0
- package/dist/scripts/util.js +376 -0
- package/package.json +68 -0
- package/src/exec/featureFileCache.ts +80 -0
- package/src/exec/featureFilePreProcess.ts +239 -0
- package/src/exec/preLoader.ts +72 -0
- package/src/exec/preProcessEntry.ts +59 -0
- package/src/exec/preProcess_old_todelete.ts +289 -0
- package/src/exec/runner.ts +241 -0
- package/src/exec/runnerCuke.js +90 -0
- package/src/exec/runner_orchestrator.ts +91 -0
- package/src/exec/sgGenerator.ts +373 -0
- package/src/global.ts +130 -0
- package/src/helper/actions/api/apiRequestActions.ts +362 -0
- package/src/helper/actions/api/apiValidationActions.ts +594 -0
- package/src/helper/actions/apiActions.ts +18 -0
- package/src/helper/actions/apiStepDefs.ts +80 -0
- package/src/helper/actions/comm/commonActions.ts +165 -0
- package/src/helper/actions/comm/utilityActions.ts +344 -0
- package/src/helper/actions/commActions.ts +18 -0
- package/src/helper/actions/commStepDefs.ts +72 -0
- package/src/helper/actions/stepGroupStepDefs.ts +17 -0
- package/src/helper/actions/web/alertActions.ts +179 -0
- package/src/helper/actions/web/cookieActions.ts +124 -0
- package/src/helper/actions/web/downloadActions.ts +129 -0
- package/src/helper/actions/web/elementReaderActions.ts +323 -0
- package/src/helper/actions/web/formActions.ts +469 -0
- package/src/helper/actions/web/iframeActions.ts +67 -0
- package/src/helper/actions/web/javascriptActions.ts +38 -0
- package/src/helper/actions/web/keyboardActions.ts +101 -0
- package/src/helper/actions/web/localStorageActions.ts +109 -0
- package/src/helper/actions/web/mouseActions.ts +864 -0
- package/src/helper/actions/web/reportingActions.ts +53 -0
- package/src/helper/actions/web/screenshotActions.ts +124 -0
- package/src/helper/actions/web/testDataActions.ts +162 -0
- package/src/helper/actions/web/validationActions.ts +2287 -0
- package/src/helper/actions/web/waitActions.ts +757 -0
- package/src/helper/actions/web/webNavigation.ts +313 -0
- package/src/helper/actions/webActions.ts +33 -0
- package/src/helper/actions/webStepDefs.ts +505 -0
- package/src/helper/browsers/browserManager.ts +23 -0
- package/src/helper/bundle/defaultEntries.ts +208 -0
- package/src/helper/bundle/env.ts +119 -0
- package/src/helper/bundle/vars.ts +368 -0
- package/src/helper/faker/customFaker.ts +107 -0
- package/src/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
- package/src/helper/faker/modules/dateTime.ts +121 -0
- package/src/helper/faker/modules/mobile.ts +58 -0
- package/src/helper/faker/modules/nric.ts +109 -0
- package/src/helper/faker/modules/passport.ts +34 -0
- package/src/helper/faker/modules/person.ts +93 -0
- package/src/helper/faker/modules/postcode.ts +57 -0
- package/src/helper/fixtures/locAggregate.ts +61 -0
- package/src/helper/fixtures/logFixture.ts +57 -0
- package/src/helper/fixtures/webFixture.ts +206 -0
- package/src/helper/fixtures/webLocFixture.ts +143 -0
- package/src/helper/report/allureStepLogger.ts +26 -0
- package/src/helper/report/customiseReport.ts +61 -0
- package/src/helper/report/init.ts +18 -0
- package/src/helper/report/report.ts +72 -0
- package/src/helper/util/dataLoader.ts +42 -0
- package/src/helper/util/logger.ts +32 -0
- package/src/helper/util/session/sessionUtil.ts +839 -0
- package/src/helper/util/stepHelpers.ts +14 -0
- package/src/helper/util/test-data/dataLoader.ts +108 -0
- package/src/helper/util/test-data/dataTest.ts +191 -0
- package/src/helper/util/test-data/registerUser.json +7 -0
- package/src/helper/util/totp/totpHelper.ts +102 -0
- package/src/helper/util/utilities/cryptoUtil.ts +53 -0
- package/src/helper/util/utilities/schemaGeneratorUtil.ts +143 -0
- package/src/helper/util/utils.ts +28 -0
- package/src/helper/wrapper/PlaywrightWrappers.ts +28 -0
- package/src/helper/wrapper/assert.ts +25 -0
- package/src/index.ts +17 -0
- package/src/scripts/get-versions.ts +68 -0
- package/src/scripts/posttest.ts +32 -0
- package/src/scripts/pretest.ts +48 -0
- package/src/scripts/util.ts +406 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { expect, Page } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
export default class Assert {
|
|
4
|
+
|
|
5
|
+
constructor(private page: Page) { }
|
|
6
|
+
|
|
7
|
+
async assertTitle(title: string) {
|
|
8
|
+
await expect(this.page).toHaveTitle(title);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async assertTitleContains(title: string) {
|
|
12
|
+
const pageTitle = await this.page.title();
|
|
13
|
+
expect(pageTitle).toContain(title);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async assertURL(url: string) {
|
|
17
|
+
await expect(this.page).toHaveURL(url);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async assertURLContains(title: string) {
|
|
21
|
+
const pageURL = this.page.url();
|
|
22
|
+
expect(pageURL).toContain(title);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Public entrypoint for @playq/core
|
|
2
|
+
// Re-export commonly used framework APIs
|
|
3
|
+
|
|
4
|
+
// Global aggregator (vars, fixtures, actions, utils, faker, etc.)
|
|
5
|
+
export * from './global';
|
|
6
|
+
|
|
7
|
+
// Lightweight config/env helpers for use in config files
|
|
8
|
+
export { loadEnv } from './helper/bundle/env';
|
|
9
|
+
export * as vars from './helper/bundle/vars';
|
|
10
|
+
|
|
11
|
+
// Optional: direct exports for key fixtures
|
|
12
|
+
export { webFixture } from './helper/fixtures/webFixture';
|
|
13
|
+
export { logFixture } from './helper/fixtures/logFixture';
|
|
14
|
+
export { webLocResolver } from './helper/fixtures/webLocFixture';
|
|
15
|
+
import { getLocNamespace } from './helper/fixtures/locAggregate';
|
|
16
|
+
// Expose loc from global if already initialized (via alias import), else build a best-effort namespace
|
|
17
|
+
export const loc: any = (globalThis as any).loc || getLocNamespace();
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
function getVersion(command: string): string {
|
|
6
|
+
try {
|
|
7
|
+
return execSync(command, { encoding: 'utf8' }).trim();
|
|
8
|
+
} catch (error) {
|
|
9
|
+
return 'Not installed';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getPackageVersion(packageName: string): string {
|
|
14
|
+
try {
|
|
15
|
+
const packageJsonPath = path.join(process.cwd(), 'node_modules', packageName, 'package.json');
|
|
16
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
18
|
+
return packageJson.version;
|
|
19
|
+
}
|
|
20
|
+
return 'Not found';
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return 'Error reading version';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getInstalledVersion(packageName: string): string {
|
|
27
|
+
try {
|
|
28
|
+
const output = execSync(`npm list ${packageName} --depth=0`, { encoding: 'utf8' });
|
|
29
|
+
const match = output.match(new RegExp(`${packageName}@([\\d\\.]+)`));
|
|
30
|
+
return match ? match[1] : 'Not found';
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return 'Not installed';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
function getPackageInfo() {
|
|
38
|
+
try {
|
|
39
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
40
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
41
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
42
|
+
}
|
|
43
|
+
return { name: 'Unknown', version: 'Unknown' };
|
|
44
|
+
} catch (error) {
|
|
45
|
+
return { name: 'Error reading package.json', version: 'Error' };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log('🔍 PlayQ Framework Version Information\n');
|
|
50
|
+
|
|
51
|
+
console.log('| Component | Version |');
|
|
52
|
+
console.log('|-----------|---------|');
|
|
53
|
+
console.log(`| Programming Language (TypeScript) | ${getVersion('npx tsc --version').replace('Version ', '')} |`);
|
|
54
|
+
console.log(`| Runtime Environment (Node.js) | ${getVersion('node --version').replace('v', '')} |`);
|
|
55
|
+
console.log(`| Automation Framework (Playwright) | ${getInstalledVersion('@playwright/test')} |`);
|
|
56
|
+
console.log(`| Test Runner (Playwright Test Runner) | ${getInstalledVersion('@playwright/test')} |`);
|
|
57
|
+
console.log(`| BDD Framework (Cucumber) | ${getInstalledVersion('@cucumber/cucumber')} |`);
|
|
58
|
+
console.log(`| Reporting (Allure Playwright) | ${getInstalledVersion('allure-playwright')} |`);
|
|
59
|
+
console.log(`| Data Generation Utility (Faker.js) | ${getInstalledVersion('@faker-js/faker')} |`);
|
|
60
|
+
console.log(`| Cross Platform (cross-env) | ${getInstalledVersion('cross-env')} |`);
|
|
61
|
+
console.log(`| File Operations (rimraf) | ${getInstalledVersion('rimraf')} |`);
|
|
62
|
+
|
|
63
|
+
console.log('\n📦 Package Manager Information:');
|
|
64
|
+
console.log(`| npm | ${getVersion('npm --version')} |`);
|
|
65
|
+
|
|
66
|
+
const packageInfo = getPackageInfo();
|
|
67
|
+
console.log(`| Package Name | ${packageInfo.name || 'play-ts-cucumber'} |`);
|
|
68
|
+
console.log(`| Package Version | ${packageInfo.version || '1.0.0'} |`);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import minimist from 'minimist';
|
|
2
|
+
import { loadEnv } from '../helper/bundle/env';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { rmSync } from 'fs';
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
import { vars } from '../global'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export function executePostTest() {
|
|
10
|
+
|
|
11
|
+
loadEnv();
|
|
12
|
+
|
|
13
|
+
if (process.env.PLAYQ_RUNNER === 'cucumber') {
|
|
14
|
+
// CUCUMBER RUNNER
|
|
15
|
+
} else {
|
|
16
|
+
// PLAYWRIGHT RUNNER
|
|
17
|
+
let allureSingleFile = (vars.getConfigValue('report.allure.singleFile') == 'true') ? '--single-file' : '';
|
|
18
|
+
execSync(`npx allure generate ${allureSingleFile} ./allure-results --output ./allure-report`, { stdio: 'inherit', cwd: path.resolve(__dirname, '../../') });
|
|
19
|
+
if (process.env.PLAYQ_REPORT_OPEN.toLowerCase() !== 'false' && vars.getConfigValue('testExecution.autoReportOpen') !== 'false') {
|
|
20
|
+
console.log('- [INFO] Report open disabled using PLAYQ_REPORT_OPEN');
|
|
21
|
+
execSync('npx allure open ./allure-report', { stdio: 'inherit', cwd: path.resolve(__dirname, '../../') });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// If called directly (not imported)
|
|
30
|
+
if (require.main === module) {
|
|
31
|
+
executePostTest();
|
|
32
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { loadEnv } from '../helper/bundle/env';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { rmSync } from 'fs';
|
|
4
|
+
|
|
5
|
+
export function setupEnvironment() {
|
|
6
|
+
loadEnv();
|
|
7
|
+
|
|
8
|
+
// If running in Cucumber mode, we need to handle pre-processing differently
|
|
9
|
+
if (process.env.PLAYQ_RUNNER === 'cucumber') {
|
|
10
|
+
// CUCUMBER RUNNER
|
|
11
|
+
// Remove allure-report directory in the project folder for cucumber runner
|
|
12
|
+
try {
|
|
13
|
+
rmSync(path.resolve(process.env['PLAYQ_PROJECT_ROOT'], 'test-results'), { recursive: true, force: true });
|
|
14
|
+
} catch (err) {
|
|
15
|
+
console.warn('Warning: Failed to remove allure-report', err);
|
|
16
|
+
}
|
|
17
|
+
require(path.resolve(process.env['PLAYQ_CORE_ROOT'], 'exec/preProcessEntry.ts'));
|
|
18
|
+
} else {
|
|
19
|
+
// PLAYWRIGHT RUNNER
|
|
20
|
+
// Remove allure-report and allure-results directories
|
|
21
|
+
try {
|
|
22
|
+
rmSync(path.resolve(process.env['PLAYQ_PROJECT_ROOT'], 'allure-report'), { recursive: true, force: true });
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.warn('Warning: Failed to remove ./allure-report', err);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
rmSync(path.resolve(process.env['PLAYQ_PROJECT_ROOT'], 'allure-results'), { recursive: true, force: true });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.warn('Warning: Failed to remove ./allure-results', err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// General directory cleanup
|
|
33
|
+
try {
|
|
34
|
+
rmSync(path.resolve(process.env['PLAYQ_PROJECT_ROOT'], '_Temp/sessions'), { recursive: true, force: true });
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.warn('Warning: Failed to remove _Temp/sessions folder', err);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
rmSync(path.resolve(process.env['PLAYQ_PROJECT_ROOT'], '_Temp/smartAI'), { recursive: true, force: true });
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.warn('Warning: Failed to remove _Temp/smartAI folder', err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// If called directly (not imported)
|
|
46
|
+
if (require.main === module) {
|
|
47
|
+
setupEnvironment();
|
|
48
|
+
}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import * as readline from 'readline';
|
|
2
|
+
import { comm, vars } from "../global";
|
|
3
|
+
import * as clipboardy from 'clipboardy';
|
|
4
|
+
import * as crypto from 'crypto';
|
|
5
|
+
import { TOTPHelper } from '../helper/util/totp/totpHelper';
|
|
6
|
+
import * as fs from 'node:fs';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
let encryptedValue: string = '';
|
|
11
|
+
let outputValue: string = '';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Handle Ctrl+C gracefully
|
|
20
|
+
process.on('SIGINT', () => {
|
|
21
|
+
console.log('\n🚪 Process interrupted by user (Ctrl+C)');
|
|
22
|
+
rl.close();
|
|
23
|
+
process.exit(0);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
async function question(prompt: string): Promise<string> {
|
|
27
|
+
return new Promise(resolve => {
|
|
28
|
+
rl.question(prompt, (answer) => {
|
|
29
|
+
// Check for specific exit commands
|
|
30
|
+
if (answer.toLowerCase() === 'exit' ||
|
|
31
|
+
answer.toLowerCase() === 'quit' ||
|
|
32
|
+
answer.toLowerCase() === 'q' ||
|
|
33
|
+
answer === '\u001b') {
|
|
34
|
+
console.log('🚪 Exiting...');
|
|
35
|
+
rl.close();
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
resolve(answer);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function encryptUserInput(): Promise<void> {
|
|
44
|
+
try {
|
|
45
|
+
console.log('🔐 PlayQ Utility Helper\n');
|
|
46
|
+
console.log('💡 Type "exit", "quit", "q", or press Ctrl+C to exit anytime\n');
|
|
47
|
+
|
|
48
|
+
console.log('What would you like to do?');
|
|
49
|
+
console.log('1. Password (strong encryption)');
|
|
50
|
+
console.log('2. Text (strong encryption)');
|
|
51
|
+
console.log('3. Decrypt');
|
|
52
|
+
console.log('4. Generate 32bit Key');
|
|
53
|
+
console.log('5. Generate TOTP Code');
|
|
54
|
+
console.log('6. Generate API Schema from OpenAPI');
|
|
55
|
+
console.log('7. Exit');
|
|
56
|
+
|
|
57
|
+
const choice = await question('\nEnter your choice (1-7): ');
|
|
58
|
+
|
|
59
|
+
switch (choice) {
|
|
60
|
+
case '1':
|
|
61
|
+
await encryptPassword();
|
|
62
|
+
break;
|
|
63
|
+
case '2':
|
|
64
|
+
await encryptText();
|
|
65
|
+
break;
|
|
66
|
+
case '3':
|
|
67
|
+
await decrypt();
|
|
68
|
+
break;
|
|
69
|
+
case '4':
|
|
70
|
+
await generate32ByteKey();
|
|
71
|
+
break;
|
|
72
|
+
case '5':
|
|
73
|
+
await generateTotpCode();
|
|
74
|
+
break;
|
|
75
|
+
case '6':
|
|
76
|
+
await generateApiSchema();
|
|
77
|
+
break;
|
|
78
|
+
case '7':
|
|
79
|
+
console.log('🚪 Goodbye!');
|
|
80
|
+
return;
|
|
81
|
+
default:
|
|
82
|
+
console.log('❌ Invalid choice. Please run again.');
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Ask user what to copy to clipboard (only for encryption/decryption operations)
|
|
87
|
+
if (choice !== '6') { // Skip clipboard for schema generation
|
|
88
|
+
console.log('\nWhat would you like to copy to clipboard?');
|
|
89
|
+
console.log('1. Copy encrypted value');
|
|
90
|
+
console.log('2. Nothing (skip copy)');
|
|
91
|
+
console.log('3. Exit');
|
|
92
|
+
|
|
93
|
+
const copyChoice = await question('Enter choice (1-3): ');
|
|
94
|
+
|
|
95
|
+
switch (copyChoice) {
|
|
96
|
+
case '1':
|
|
97
|
+
if (encryptedValue) {
|
|
98
|
+
await copyToClipboard(encryptedValue, 'Encrypted Password');
|
|
99
|
+
} else if (outputValue) {
|
|
100
|
+
await copyToClipboard(outputValue, 'Output Value');
|
|
101
|
+
} else {
|
|
102
|
+
console.log('❌ No encrypted / output value to copy');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
break;
|
|
106
|
+
case '2':
|
|
107
|
+
console.log('📋 Skipped copying to clipboard');
|
|
108
|
+
break;
|
|
109
|
+
case '3':
|
|
110
|
+
console.log('🚪 Exiting...');
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
console.log('❌ Invalid choice');
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('❌ Error:', error);
|
|
120
|
+
} finally {
|
|
121
|
+
rl.close();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function copyToClipboard(text: string, description: string): Promise<void> {
|
|
126
|
+
try {
|
|
127
|
+
await clipboardy.default.write(text);
|
|
128
|
+
console.log(`✅ ${description} copied to clipboard!`);
|
|
129
|
+
console.log(`📋 Copied: ${text.length > 50 ? text.substring(0, 50) + '...' : text}`);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('❌ Failed to copy to clipboard:', error);
|
|
132
|
+
console.log('📝 Manual copy:');
|
|
133
|
+
console.log(text);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function encryptPassword(): Promise<void> {
|
|
138
|
+
const passwordText = await question('Enter password to encrypt (or "exit" to quit): ');
|
|
139
|
+
|
|
140
|
+
if (!passwordText) {
|
|
141
|
+
console.log('❌ Password cannot be empty');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
console.log('🔄 Encrypting password...');
|
|
147
|
+
encryptedValue = await comm.encryptPassword(passwordText);
|
|
148
|
+
|
|
149
|
+
console.log('\n📋 🔐 Encrypted Password Result:');
|
|
150
|
+
console.log('='.repeat(50));
|
|
151
|
+
console.log(encryptedValue);
|
|
152
|
+
console.log('='.repeat(50));
|
|
153
|
+
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error('❌ Encryption failed:', error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function encryptText(): Promise<void> {
|
|
160
|
+
const encryptText = await question('Enter text to encrypt (or "exit" to quit): ');
|
|
161
|
+
|
|
162
|
+
if (!encryptText) {
|
|
163
|
+
console.log('❌ Text cannot be empty');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
console.log('🔄 Encrypting text...');
|
|
169
|
+
encryptedValue = await comm.encryptText(encryptText);
|
|
170
|
+
|
|
171
|
+
console.log('\n📋 🔐 Encrypted Text Result:');
|
|
172
|
+
console.log('='.repeat(50));
|
|
173
|
+
console.log(encryptedValue);
|
|
174
|
+
console.log('='.repeat(50));
|
|
175
|
+
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error('❌ Encryption failed:', error);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function decrypt(): Promise<void> {
|
|
182
|
+
const decryptText = await question('Enter text to decrypt (or "exit" to quit): ');
|
|
183
|
+
|
|
184
|
+
if (!decryptText) {
|
|
185
|
+
console.log('❌ Text cannot be empty');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
console.log('🔄 Decrypting text...');
|
|
191
|
+
encryptedValue = await vars.replaceVariables('#{' + decryptText + '}');
|
|
192
|
+
|
|
193
|
+
console.log('\n📋 🔓 Decrypted Text Result:');
|
|
194
|
+
console.log('='.repeat(50));
|
|
195
|
+
console.log(encryptedValue);
|
|
196
|
+
console.log('='.repeat(50));
|
|
197
|
+
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error('❌ Decryption failed:', error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async function generate32ByteKey(): Promise<void> {
|
|
205
|
+
try {
|
|
206
|
+
const key = crypto.randomBytes(32).toString('hex');
|
|
207
|
+
encryptedValue = key;
|
|
208
|
+
console.log('\n🔑 32-byte Key Generated:');
|
|
209
|
+
console.log('='.repeat(50));
|
|
210
|
+
console.log(key);
|
|
211
|
+
console.log('='.repeat(50));
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error('❌ Failed to generate key:', error);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function generateTotpCode(): Promise<void> {
|
|
218
|
+
try {
|
|
219
|
+
let secretKey = process.env.PLAYQ_TOTP_SECRET_KEY;
|
|
220
|
+
if (!secretKey) {
|
|
221
|
+
const inputSecret = await question('Enter TOTP secret key (or "exit" to quit): ');
|
|
222
|
+
if (!inputSecret) {
|
|
223
|
+
throw new Error('❌ TOTP secret key cannot be empty');
|
|
224
|
+
}
|
|
225
|
+
process.env.PLAYQ_TOTP_SECRET_KEY = inputSecret;
|
|
226
|
+
secretKey = inputSecret;
|
|
227
|
+
}
|
|
228
|
+
if (secretKey.startsWith("enc.")) {
|
|
229
|
+
secretKey = vars.replaceVariables(`#{${secretKey}}`);
|
|
230
|
+
}
|
|
231
|
+
// const secret = crypto.randomBytes(20).toString('hex');
|
|
232
|
+
const totpHelper = new TOTPHelper(secretKey);
|
|
233
|
+
const token = totpHelper.generateToken();
|
|
234
|
+
outputValue = token;
|
|
235
|
+
console.log('\n🔑 TOTP Code Generated:');
|
|
236
|
+
console.log('='.repeat(50));
|
|
237
|
+
console.log(token);
|
|
238
|
+
console.log('='.repeat(50));
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error('❌ Failed to generate TOTP code:', error);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function generateApiSchema(): Promise<void> {
|
|
245
|
+
try {
|
|
246
|
+
console.log('\n📋 API Schema Generator');
|
|
247
|
+
console.log('Generate TypeScript schema files from OpenAPI specifications\n');
|
|
248
|
+
|
|
249
|
+
console.log('Select input source:');
|
|
250
|
+
console.log('1. URL (HTTP/HTTPS)');
|
|
251
|
+
console.log('2. Local file path');
|
|
252
|
+
|
|
253
|
+
const sourceChoice = await question('Enter choice (1-2): ');
|
|
254
|
+
|
|
255
|
+
let input: string = '';
|
|
256
|
+
let url: string = '';
|
|
257
|
+
|
|
258
|
+
if (sourceChoice === '1') {
|
|
259
|
+
url = await question('Enter OpenAPI JSON URL: ');
|
|
260
|
+
if (!url) {
|
|
261
|
+
console.log('❌ URL cannot be empty');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
} else if (sourceChoice === '2') {
|
|
265
|
+
input = await question('Enter path to OpenAPI JSON file: ');
|
|
266
|
+
if (!input) {
|
|
267
|
+
console.log('❌ File path cannot be empty');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
console.log('❌ Invalid choice');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const outDir = await question('Enter output directory (default: resources/schemas): ') || 'resources/schemas';
|
|
276
|
+
const prefix = await question('Enter export name prefix (optional, e.g., "Api"): ') || '';
|
|
277
|
+
const indexFile = await question('Enter index file name (default: index.ts): ') || 'index.ts';
|
|
278
|
+
|
|
279
|
+
console.log('\n🔄 Generating schema files...');
|
|
280
|
+
|
|
281
|
+
await generateSchemaFiles({
|
|
282
|
+
input: input || undefined,
|
|
283
|
+
url: url || undefined,
|
|
284
|
+
outDir,
|
|
285
|
+
prefix,
|
|
286
|
+
indexFile
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log('✅ Schema generation completed successfully!');
|
|
290
|
+
outputValue = `Schema files generated in: ${path.resolve(outDir)}`;
|
|
291
|
+
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.error('❌ Failed to generate API schema:', error);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Schema generator types and functions
|
|
298
|
+
type OpenApiDoc = {
|
|
299
|
+
openapi: string;
|
|
300
|
+
components?: {
|
|
301
|
+
schemas?: Record<string, any>;
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
type SchemaArgs = {
|
|
306
|
+
input?: string;
|
|
307
|
+
url?: string;
|
|
308
|
+
outDir: string;
|
|
309
|
+
prefix: string;
|
|
310
|
+
indexFile: string;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
async function loadOpenApi(args: SchemaArgs): Promise<OpenApiDoc> {
|
|
314
|
+
if (args.input) {
|
|
315
|
+
const p = path.resolve(args.input);
|
|
316
|
+
const raw = fs.readFileSync(p, "utf8");
|
|
317
|
+
return JSON.parse(raw);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// URL
|
|
321
|
+
const res = await fetch(args.url!, {
|
|
322
|
+
headers: { Accept: "application/json" },
|
|
323
|
+
});
|
|
324
|
+
if (!res.ok) {
|
|
325
|
+
throw new Error(`Failed to fetch OpenAPI JSON from ${args.url}. HTTP ${res.status}`);
|
|
326
|
+
}
|
|
327
|
+
return (await res.json()) as OpenApiDoc;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function safeIdent(name: string): string {
|
|
331
|
+
// Make a valid TS identifier-ish name (keeps underscores)
|
|
332
|
+
const cleaned = name.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
333
|
+
// Avoid leading digit
|
|
334
|
+
if (/^\d/.test(cleaned)) return "_" + cleaned;
|
|
335
|
+
return cleaned;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function exportNameFor(schemaName: string, prefix: string): string {
|
|
339
|
+
// AgentVersion -> AgentVersionSchema, optional prefix -> ApiAgentVersionSchema
|
|
340
|
+
const base = `${schemaName}Schema`;
|
|
341
|
+
return prefix ? `${prefix}${base}` : base;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function ensureOutDir(outDir: string) {
|
|
345
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function writeSchemaFile(outDir: string, schemaKey: string, exportName: string, schema: any, openapiVersion: string) {
|
|
349
|
+
const fileName = `${schemaKey}.schema.ts`;
|
|
350
|
+
const fullPath = path.join(outDir, fileName);
|
|
351
|
+
|
|
352
|
+
const content =
|
|
353
|
+
`/* Auto-generated by PlayQ schema generator - OpenAPI ${openapiVersion} */\n` +
|
|
354
|
+
`/* Source schema: #/components/schemas/${schemaKey} */\n\n` +
|
|
355
|
+
`export const ${exportName} = ${JSON.stringify(schema, null, 2)} as const;\n`;
|
|
356
|
+
|
|
357
|
+
fs.writeFileSync(fullPath, content, "utf8");
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function writeIndexFile(outDir: string, indexFile: string, entries: Array<{ schemaKey: string; exportName: string }>) {
|
|
361
|
+
const fullPath = path.join(outDir, indexFile);
|
|
362
|
+
const lines = entries
|
|
363
|
+
.sort((a, b) => a.schemaKey.localeCompare(b.schemaKey))
|
|
364
|
+
.map(e => `export { ${e.exportName} } from "./${e.schemaKey}.schema";`);
|
|
365
|
+
|
|
366
|
+
fs.writeFileSync(fullPath, lines.join("\n") + "\n", "utf8");
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async function generateSchemaFiles(args: SchemaArgs) {
|
|
370
|
+
const doc = await loadOpenApi(args);
|
|
371
|
+
|
|
372
|
+
if (!doc.openapi?.startsWith("3.1")) {
|
|
373
|
+
// still might work, but you said OAS 3.1 and this generator assumes that
|
|
374
|
+
console.warn(`⚠️ OpenAPI version is "${doc.openapi}". Generator is optimised for 3.1.x.`);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const schemas = doc.components?.schemas ?? {};
|
|
378
|
+
const schemaKeys = Object.keys(schemas);
|
|
379
|
+
if (!schemaKeys.length) {
|
|
380
|
+
throw new Error(`No components.schemas found in the OpenAPI document.`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const outDir = path.resolve(args.outDir);
|
|
384
|
+
ensureOutDir(outDir);
|
|
385
|
+
|
|
386
|
+
const indexEntries: Array<{ schemaKey: string; exportName: string }> = [];
|
|
387
|
+
|
|
388
|
+
for (const rawKey of schemaKeys) {
|
|
389
|
+
const schemaKey = safeIdent(rawKey);
|
|
390
|
+
const exportName = exportNameFor(schemaKey, args.prefix);
|
|
391
|
+
const schema = schemas[rawKey];
|
|
392
|
+
|
|
393
|
+
writeSchemaFile(outDir, schemaKey, exportName, schema, doc.openapi);
|
|
394
|
+
indexEntries.push({ schemaKey, exportName });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
writeIndexFile(outDir, args.indexFile, indexEntries);
|
|
398
|
+
|
|
399
|
+
console.log(`✅ Generated ${schemaKeys.length} schemas into: ${outDir}`);
|
|
400
|
+
console.log(`✅ Barrel export: ${path.join(outDir, args.indexFile)}`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Main execution
|
|
404
|
+
if (require.main === module) {
|
|
405
|
+
encryptUserInput();
|
|
406
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2019",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"emitDeclarationOnly": false,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"types": [
|
|
15
|
+
"node"
|
|
16
|
+
],
|
|
17
|
+
"lib": [
|
|
18
|
+
"es2020",
|
|
19
|
+
"dom"
|
|
20
|
+
],
|
|
21
|
+
"noEmitOnError": false
|
|
22
|
+
},
|
|
23
|
+
"include": [
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
26
|
+
"exclude": [
|
|
27
|
+
"dist",
|
|
28
|
+
"node_modules"
|
|
29
|
+
]
|
|
30
|
+
}
|