e2e test environment fortwenty-cli (#15123)
# Introduction Defining very first basis of the twenty-cli e2e testing env. Dynamically generating tests cases based on a list of applications names that will be matched to stored twenty-apps and run install delete and reinstall with their configuration on the same instance We could use a glob pattern with a specific e2e configuration in every apps but right now overkill ## Notes - We should define typescript path aliasing to ease import devxp - parse the config using a zod object ## Some vision on test granularity Right now we only check that the server sent back success or failure on below operation. In the future the synchronize will return a report of what has been installed per entity exactly. We will be able to snapshot everything in order to detect regressions We should also be testing the cli directly for init and other stuff in the end, we could get some inspiration from what's done in preconstruct e2e tests with an on heap virtual file system ## Conclusion Any suggestions are more than welcomed ! close https://github.com/twentyhq/core-team-issues/issues/1721
This commit is contained in:
@@ -1,21 +1,26 @@
|
||||
import inquirer from 'inquirer';
|
||||
import chalk from 'chalk';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import inquirer from 'inquirer';
|
||||
import { CURRENT_EXECUTION_DIRECTORY } from '../constants/current-execution-directory';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { ApiResponse } from '../types/config.types';
|
||||
import { loadManifest } from '../utils/app-manifest-loader';
|
||||
|
||||
export class AppDeleteCommand {
|
||||
private apiService = new ApiService();
|
||||
|
||||
async execute(): Promise<void> {
|
||||
async execute({
|
||||
appPath = CURRENT_EXECUTION_DIRECTORY,
|
||||
askForConfirmation,
|
||||
}: {
|
||||
appPath?: string;
|
||||
askForConfirmation: boolean;
|
||||
}): Promise<ApiResponse<any>> {
|
||||
try {
|
||||
const appPath = CURRENT_EXECUTION_DIRECTORY;
|
||||
|
||||
console.log(chalk.blue('🚀 Deleting Twenty Application'));
|
||||
console.log(chalk.gray(`📁 App Path: ${appPath}`));
|
||||
console.log('');
|
||||
|
||||
if (!(await this.confirmationPrompt())) {
|
||||
if (askForConfirmation && !(await this.confirmationPrompt())) {
|
||||
console.error(chalk.red('⛔️ Aborting deletion'));
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -26,16 +31,17 @@ export class AppDeleteCommand {
|
||||
|
||||
if (!result.success) {
|
||||
console.error(chalk.red('❌ Deletion failed:'), result.error);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(chalk.green('✅ Application deleted successfully'));
|
||||
}
|
||||
|
||||
console.log(chalk.green('✅ Application deleted successfully'));
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
chalk.red('Deletion failed:'),
|
||||
error instanceof Error ? error.message : error,
|
||||
);
|
||||
process.exit(1);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import chalk from 'chalk';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { CURRENT_EXECUTION_DIRECTORY } from '../constants/current-execution-directory';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { ApiResponse } from '../types/config.types';
|
||||
import { loadManifest } from '../utils/app-manifest-loader';
|
||||
|
||||
export class AppSyncCommand {
|
||||
private apiService = new ApiService();
|
||||
|
||||
async execute(): Promise<void> {
|
||||
// TODO improve typing
|
||||
async execute(
|
||||
appPath: string = CURRENT_EXECUTION_DIRECTORY,
|
||||
): Promise<ApiResponse<any>> {
|
||||
try {
|
||||
const appPath = CURRENT_EXECUTION_DIRECTORY;
|
||||
|
||||
console.log(chalk.blue('🚀 Syncing Twenty Application'));
|
||||
console.log(chalk.gray(`📁 App Path: ${appPath}`));
|
||||
console.log('');
|
||||
@@ -24,16 +26,17 @@ export class AppSyncCommand {
|
||||
|
||||
if (!result.success) {
|
||||
console.error(chalk.red('❌ Sync failed:'), result.error);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(chalk.green('✅ Application synced successfully'));
|
||||
}
|
||||
|
||||
console.log(chalk.green('✅ Application synced successfully'));
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
chalk.red('Sync failed:'),
|
||||
error instanceof Error ? error.message : error,
|
||||
);
|
||||
process.exit(1);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'commander';
|
||||
import { AppSyncCommand } from './app-sync.command';
|
||||
import { AppDevCommand } from './app-dev.command';
|
||||
import { AppInitCommand } from './app-init.command';
|
||||
import { AppDeleteCommand } from './app-delete.command';
|
||||
import {
|
||||
AppAddCommand,
|
||||
isSyncableEntity,
|
||||
SyncableEntity,
|
||||
} from './app-add.command';
|
||||
import chalk from 'chalk';
|
||||
import { AppDeleteCommand } from './app-delete.command';
|
||||
import { AppDevCommand } from './app-dev.command';
|
||||
import { AppInitCommand } from './app-init.command';
|
||||
import { AppSyncCommand } from './app-sync.command';
|
||||
|
||||
export class AppCommand {
|
||||
private devCommand = new AppDevCommand();
|
||||
@@ -33,14 +33,30 @@ export class AppCommand {
|
||||
.command('sync')
|
||||
.description('Sync application to Twenty')
|
||||
.action(async () => {
|
||||
await this.syncCommand.execute();
|
||||
try {
|
||||
const result = await this.syncCommand.execute();
|
||||
if (!result.success) {
|
||||
process.exit(1);
|
||||
}
|
||||
} catch {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
appCommand
|
||||
.command('delete')
|
||||
.description('Delete application from Twenty')
|
||||
.action(async () => {
|
||||
await this.deleteCommand.execute();
|
||||
try {
|
||||
const result = await this.deleteCommand.execute({
|
||||
askForConfirmation: true,
|
||||
});
|
||||
if (!result.success) {
|
||||
process.exit(1);
|
||||
}
|
||||
} catch {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
appCommand
|
||||
|
||||
Reference in New Issue
Block a user