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
284 lines (283 loc) • 15.3 kB
JavaScript
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());
});
};
import path from 'path';
import fs from 'fs-extra';
import { promisify } from 'util';
import { exec } from 'child_process';
import Listr from 'listr';
import chalk from 'chalk';
import nunjucks from 'nunjucks';
import { ValidationError } from 'yup';
import { getPathToNodeModulesRoot } from '../../utils/path';
import { addScript, removeScript } from './add-remove-script-package-json';
export class CreateExampleProject {
constructor(cliOptions) {
this.cliOptions = cliOptions;
this.exampleTemplateDirectoryName = 'askui_example';
this.projectRootDirectoryPath = process.cwd();
this.automationsDirectoryName = this.getAutomationsDirectoryName();
this.automationsDirectoryPath = path.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 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.join('example_projects_templates', 'typescript', this.exampleTemplateDirectoryName);
const runCommand = promisify(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.copy(path.join(getPathToNodeModulesRoot(), exampleProjectPath), this.automationsDirectoryPath);
}),
},
{
title: 'Install askui dependency',
task: () => __awaiter(this, void 0, void 0, function* () {
yield runCommand('npm init -y');
yield 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.join(getPathToNodeModulesRoot(), 'example_projects_templates', 'configs', frameworkConfigs.jest);
yield fs.copyFile(configFilePath, path.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 addScript(`${this.projectRootDirectoryPath}/package.json`, 'askui', frameworkExecutionCommand.jest);
});
}
addESLintRunCommand() {
return __awaiter(this, void 0, void 0, function* () {
yield 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([
{
title: 'Create askui-helper.ts ',
task: () => __awaiter(this, void 0, void 0, function* () {
const askuiHelperTemplateFilePath = path.join(getPathToNodeModulesRoot(), 'example_projects_templates', 'templates');
const templateFileName = 'askui-helper.nj';
nunjucks.configure(askuiHelperTemplateFilePath, { autoescape: false });
const result = nunjucks.render(templateFileName, this.helperTemplateConfig);
const filePath = path.join(this.automationsDirectoryPath, 'helpers', 'askui-helper.ts');
if (!fs.existsSync(path.join(this.automationsDirectoryPath, 'helpers'))) {
yield fs.mkdir(path.join(this.automationsDirectoryPath, 'helpers'));
}
yield fs.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([
{
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 = promisify(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.join('example_projects_templates', 'typescript', '.eslintrc.json-template');
const esLintIgnoreFilePath = path.join('example_projects_templates', 'typescript', '.eslintignore-template');
return [{
title: 'Copy ESLint config files',
task: () => __awaiter(this, void 0, void 0, function* () {
return new Listr([
{
title: 'Add eslintrc.json',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintRcFilePath), path.join(this.projectRootDirectoryPath, '.eslintrc.json'));
}),
},
{
title: 'Add .eslintignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs.copyFile(path.join(getPathToNodeModulesRoot(), esLintIgnoreFilePath), path.join(this.projectRootDirectoryPath, '.eslintignore'));
}),
},
]);
}),
},
];
});
}
copyGitignore() {
return __awaiter(this, void 0, void 0, function* () {
const gitignoreFilePath = path.join('example_projects_templates', 'typescript', 'gitignore');
return [{
title: 'Copy .gitignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return new Listr([
{
title: 'Add .gitignore',
task: () => __awaiter(this, void 0, void 0, function* () {
return fs.copyFile(path.join(getPathToNodeModulesRoot(), gitignoreFilePath), path.join(this.projectRootDirectoryPath, '.gitignore'));
}),
},
]);
}),
},
];
});
}
addVSCodeSettings() {
return __awaiter(this, void 0, void 0, function* () {
const vscodeSettingsFilePath = path.join('example_projects_templates', 'configs', 'vscode-settings.json');
const vscodeSettingsTargetDirPath = path.join(this.projectRootDirectoryPath, '.vscode');
const vscodeSettingsTargetFilePath = path.join(vscodeSettingsTargetDirPath, 'settings.json');
return [{
enabled: () => !fs.existsSync(vscodeSettingsTargetFilePath),
task: () => __awaiter(this, void 0, void 0, function* () {
yield fs.mkdir(vscodeSettingsTargetDirPath, { recursive: true });
yield fs.copyFile(path.join(getPathToNodeModulesRoot(), vscodeSettingsFilePath), vscodeSettingsTargetFilePath);
}),
title: 'Copy VSCode settings',
}];
});
}
copyTsConfigFile() {
return __awaiter(this, void 0, void 0, function* () {
const tsConfigFilePath = path.join('example_projects_templates', 'typescript', 'tsconfig.json');
const tsConfigTargetFilePath = path.join(this.projectRootDirectoryPath, 'tsconfig.json');
return [
{
enabled: () => this.cliOptions.typescriptConfig || !fs.existsSync(tsConfigTargetFilePath),
task: () => __awaiter(this, void 0, void 0, function* () {
return fs.copyFile(path.join(getPathToNodeModulesRoot(), tsConfigFilePath), tsConfigTargetFilePath);
}),
title: 'Copy ts config file',
},
];
});
}
createExampleProject() {
return __awaiter(this, void 0, void 0, function* () {
const tasks = new Listr();
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.greenBright('\nCongratulations!'));
console.log(`askui example was created under ${chalk.gray(this.automationsDirectoryPath)}`);
console.log(chalk.redBright(`\nPlease make sure the AskUI Controller is running: ${this.askUIControllerUrl}\n`));
console.log(`You can start your automation with this command ${chalk.green('AskUI-RunProject')}`);
/* eslint-enable no-console */
});
}
}