askui
Version:
Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on
291 lines (290 loc) • 16.5 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateExampleProject = void 0;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const util_1 = require("util");
const child_process_1 = require("child_process");
const listr_1 = __importDefault(require("listr"));
const chalk_1 = __importDefault(require("chalk"));
const nunjucks_1 = __importDefault(require("nunjucks"));
const yup_1 = require("yup");
const path_2 = require("../../utils/path");
const add_remove_script_package_json_1 = require("./add-remove-script-package-json");
class CreateExampleProject {
constructor(cliOptions) {
this.cliOptions = cliOptions;
this.exampleTemplateDirectoryName = 'askui_example';
this.projectRootDirectoryPath = process.cwd();
this.automationsDirectoryName = this.getAutomationsDirectoryName();
this.automationsDirectoryPath = path_1.default.join(this.projectRootDirectoryPath, this.automationsDirectoryName);
this.askUIControllerUrl = 'https://docs.askui.com/docs/suite/Components/AskUI-Development-Environment#askui-startcontroller-command';
this.helperTemplateConfig = {};
}
getAutomationsDirectoryName() {
if (this.cliOptions.automationsDirectory) {
if (/\s/g.test(this.cliOptions.automationsDirectory.trim())) {
throw new yup_1.ValidationError('Automations directory (-ad, --automations-directory) must not contain whitespaces');
}
return this.cliOptions.automationsDirectory.trim();
}
return this.exampleTemplateDirectoryName;
}
copyTemplateProject() {
return __awaiter(this, void 0, void 0, function* () {
const exampleProjectPath = path_1.default.join('example_projects_templates', 'typescript', this.exampleTemplateDirectoryName);
const runCommand = (0, util_1.promisify)(child_process_1.exec);
return [
{
title: 'Detect Operating System',
task: () => __awaiter(this, void 0, void 0, function* () {
if (process.platform === 'win32') {
this.cliOptions.operatingSystem = 'windows';
}
else if (process.platform === 'darwin') {
this.cliOptions.operatingSystem = 'macos';
}
else if (process.platform === 'linux'
|| process.platform === 'freebsd'
|| process.platform === 'openbsd') {
this.cliOptions.operatingSystem = 'linux';
}
else {
throw new Error(`The detected operating system is ${process.platform}. We only support 'windows', 'macos' and 'linux'`);
}
}),
},
{
title: 'Copy project files',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs_extra_1.default.copy(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), exampleProjectPath), this.automationsDirectoryPath);
}),
},
{
title: 'Install askui dependency',
task: () => __awaiter(this, void 0, void 0, function* () {
yield runCommand('npm init -y');
yield (0, add_remove_script_package_json_1.removeScript)(`${this.projectRootDirectoryPath}/package.json`, 'test');
yield runCommand('npm i -D askui ');
}),
},
];
});
}
copyTestFrameworkConfig() {
return __awaiter(this, void 0, void 0, function* () {
const frameworkConfigs = {
jest: 'jest.config.ts',
};
const configFilePath = path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), 'example_projects_templates', 'configs', frameworkConfigs.jest);
yield fs_extra_1.default.copyFile(configFilePath, path_1.default.join(this.automationsDirectoryPath, frameworkConfigs.jest));
});
}
addTestFrameWorkTimeout() {
return __awaiter(this, void 0, void 0, function* () {
const frameworkTimeoutstring = {
jest: 'jest.setTimeout(60 * 1000 * 60);',
};
this.helperTemplateConfig['timeout_placeholder'] = frameworkTimeoutstring.jest;
});
}
addReporterConfig() {
return __awaiter(this, void 0, void 0, function* () {
this.helperTemplateConfig['allure_stepreporter_import'] = "import { AskUIAllureStepReporter } from '@askui/askui-reporters';";
this.helperTemplateConfig['reporter_placeholder'] = 'reporter: new AskUIAllureStepReporter(),';
this.helperTemplateConfig['allure_stepreporter_attach_video'] = `const video = await aui.readVideoRecording();
await AskUIAllureStepReporter.attachVideo(video);`;
});
}
addAskuiRunCommand() {
return __awaiter(this, void 0, void 0, function* () {
const frameworkExecutionCommand = {
jest: `jest --config ./${this.automationsDirectoryName}/jest.config.ts --runInBand`,
};
yield (0, add_remove_script_package_json_1.addScript)(`${this.projectRootDirectoryPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
});
}
addESLintRunCommand() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, add_remove_script_package_json_1.addScript)(`${this.projectRootDirectoryPath}/package.json`, 'lint', 'eslint . --ext .ts');
});
}
createAskUIHelperFromTemplate() {
return __awaiter(this, void 0, void 0, function* () {
return [{
title: 'Write askui config',
task: () => __awaiter(this, void 0, void 0, function* () {
return new listr_1.default([
{
title: 'Create askui-helper.ts ',
task: () => __awaiter(this, void 0, void 0, function* () {
const askuiHelperTemplateFilePath = path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), 'example_projects_templates', 'templates');
const templateFileName = 'askui-helper.nj';
nunjucks_1.default.configure(askuiHelperTemplateFilePath, { autoescape: false });
const result = nunjucks_1.default.render(templateFileName, this.helperTemplateConfig);
const filePath = path_1.default.join(this.automationsDirectoryPath, 'helpers', 'askui-helper.ts');
if (!fs_extra_1.default.existsSync(path_1.default.join(this.automationsDirectoryPath, 'helpers'))) {
yield fs_extra_1.default.mkdir(path_1.default.join(this.automationsDirectoryPath, 'helpers'));
}
yield fs_extra_1.default.writeFile(filePath, result, 'utf8');
}),
},
]);
}),
}];
});
}
setupTestFrameWork() {
return __awaiter(this, void 0, void 0, function* () {
return [{
title: 'Setup Test framework',
task: () => __awaiter(this, void 0, void 0, function* () {
return new listr_1.default([
{
title: 'Install jest',
task: () => __awaiter(this, void 0, void 0, function* () { return CreateExampleProject.installTestFrameworkPackages(); }),
},
{
title: 'Copy config file',
task: () => __awaiter(this, void 0, void 0, function* () { return this.copyTestFrameworkConfig(); }),
},
{
title: 'Add timeout',
task: () => __awaiter(this, void 0, void 0, function* () { return this.addTestFrameWorkTimeout(); }),
},
{
title: 'Add reporter',
task: () => __awaiter(this, void 0, void 0, function* () { return this.addReporterConfig(); }),
},
{
title: 'Add askui run command',
task: () => __awaiter(this, void 0, void 0, function* () { return this.addAskuiRunCommand(); }),
},
{
title: 'Add eslint run command',
task: () => __awaiter(this, void 0, void 0, function* () { return this.addESLintRunCommand(); }),
},
]);
}),
}];
});
}
static installTestFrameworkPackages() {
return __awaiter(this, void 0, void 0, function* () {
const runCommand = (0, util_1.promisify)(child_process_1.exec);
const frameworkDependencies = {
jest: 'npm i -D @askui/askui-reporters typescript ts-node @types/jest@30.0.0 ts-jest@29.4.0 jest@29.7.0 @askui/jest-allure-circus eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-import @askui/eslint-plugin-askui hpagent',
};
yield runCommand(frameworkDependencies.jest);
});
}
copyESLintConfigFiles() {
return __awaiter(this, void 0, void 0, function* () {
const esLintRcFilePath = path_1.default.join('example_projects_templates', 'typescript', '.eslintrc.json-template');
const esLintIgnoreFilePath = path_1.default.join('example_projects_templates', 'typescript', '.eslintignore-template');
return [{
title: 'Copy ESLint config files',
task: () => __awaiter(this, void 0, void 0, function* () {
return new listr_1.default([
{
title: 'Add eslintrc.json',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintRcFilePath), path_1.default.join(this.projectRootDirectoryPath, '.eslintrc.json'));
}),
},
{
title: 'Add .eslintignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), esLintIgnoreFilePath), path_1.default.join(this.projectRootDirectoryPath, '.eslintignore'));
}),
},
]);
}),
},
];
});
}
copyGitignore() {
return __awaiter(this, void 0, void 0, function* () {
const gitignoreFilePath = path_1.default.join('example_projects_templates', 'typescript', 'gitignore');
return [{
title: 'Copy .gitignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return new listr_1.default([
{
title: 'Add .gitignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), gitignoreFilePath), path_1.default.join(this.projectRootDirectoryPath, '.gitignore'));
}),
},
]);
}),
},
];
});
}
addVSCodeSettings() {
return __awaiter(this, void 0, void 0, function* () {
const vscodeSettingsFilePath = path_1.default.join('example_projects_templates', 'configs', 'vscode-settings.json');
const vscodeSettingsTargetDirPath = path_1.default.join(this.projectRootDirectoryPath, '.vscode');
const vscodeSettingsTargetFilePath = path_1.default.join(vscodeSettingsTargetDirPath, 'settings.json');
return [{
enabled: () => !fs_extra_1.default.existsSync(vscodeSettingsTargetFilePath),
task: () => __awaiter(this, void 0, void 0, function* () {
yield fs_extra_1.default.mkdir(vscodeSettingsTargetDirPath, { recursive: true });
yield fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), vscodeSettingsFilePath), vscodeSettingsTargetFilePath);
}),
title: 'Copy VSCode settings',
}];
});
}
copyTsConfigFile() {
return __awaiter(this, void 0, void 0, function* () {
const tsConfigFilePath = path_1.default.join('example_projects_templates', 'typescript', 'tsconfig.json');
const tsConfigTargetFilePath = path_1.default.join(this.projectRootDirectoryPath, 'tsconfig.json');
return [
{
enabled: () => this.cliOptions.typescriptConfig || !fs_extra_1.default.existsSync(tsConfigTargetFilePath),
task: () => __awaiter(this, void 0, void 0, function* () {
return fs_extra_1.default.copyFile(path_1.default.join((0, path_2.getPathToNodeModulesRoot)(), tsConfigFilePath), tsConfigTargetFilePath);
}),
title: 'Copy ts config file',
},
];
});
}
createExampleProject() {
return __awaiter(this, void 0, void 0, function* () {
const tasks = new listr_1.default();
tasks.add([
...(yield this.copyTemplateProject()),
...(yield this.addVSCodeSettings()),
...(yield this.setupTestFrameWork()),
...(yield this.copyESLintConfigFiles()),
...(yield this.copyGitignore()),
...(yield this.copyTsConfigFile()),
...(yield this.createAskUIHelperFromTemplate()),
]);
yield tasks.run();
/* eslint-disable no-console */
console.log(chalk_1.default.greenBright('\nCongratulations!'));
console.log(`askui example was created under ${chalk_1.default.gray(this.automationsDirectoryPath)}`);
console.log(chalk_1.default.redBright(`\nPlease make sure the AskUI Controller is running: ${this.askUIControllerUrl}\n`));
console.log(`You can start your automation with this command ${chalk_1.default.green('AskUI-RunProject')}`);
/* eslint-enable no-console */
});
}
}
exports.CreateExampleProject = CreateExampleProject;