chore: apply code formatting and linting
- format long import statements with consistent line wrapping - apply consistent indentation across client and server modules - remove generated tsconfig.tsbuildinfo file
This commit is contained in:
@@ -78,6 +78,12 @@ export class BrowserController {
|
||||
}
|
||||
}
|
||||
|
||||
return this.browserService.exec(dto.sessionName, dto.code, dto.url, environment, credentials);
|
||||
return this.browserService.exec(
|
||||
dto.sessionName,
|
||||
dto.code,
|
||||
dto.url,
|
||||
environment,
|
||||
credentials,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,13 @@ import { BrowserController } from "./browser.controller";
|
||||
import { BrowserService } from "./browser.service";
|
||||
|
||||
@Module({
|
||||
imports: [SessionModule, CodeExecutorModule, SnippetModule, EnvironmentModule, CredentialModule],
|
||||
imports: [
|
||||
SessionModule,
|
||||
CodeExecutorModule,
|
||||
SnippetModule,
|
||||
EnvironmentModule,
|
||||
CredentialModule,
|
||||
],
|
||||
controllers: [BrowserController],
|
||||
providers: [BrowserService],
|
||||
exports: [BrowserService],
|
||||
|
||||
@@ -7,7 +7,10 @@ import {
|
||||
import { JSDOM } from "jsdom";
|
||||
import type { BrowserContext, Cookie } from "playwright";
|
||||
import { chromium } from "playwright";
|
||||
import type { ExecResult, ScriptLogger } from "../code-executor/code-executor.service";
|
||||
import type {
|
||||
ExecResult,
|
||||
ScriptLogger,
|
||||
} from "../code-executor/code-executor.service";
|
||||
import { CodeExecutorService } from "../code-executor/code-executor.service";
|
||||
import { TraceLogger } from "../common/trace-logger";
|
||||
import type { EnvironmentData } from "../environment/environment.entity";
|
||||
@@ -172,8 +175,7 @@ export class BrowserService {
|
||||
const label = sessionName ?? "anonymous";
|
||||
|
||||
if (sessionName) {
|
||||
const { page, context } =
|
||||
await this.getOrCreateNamedHandle(sessionName);
|
||||
const { page, context } = await this.getOrCreateNamedHandle(sessionName);
|
||||
this.logger.log(`[${label}] exec: using persistent context`);
|
||||
const snippets = await this.snippetService
|
||||
.buildSnippetMap()
|
||||
@@ -207,7 +209,7 @@ export class BrowserService {
|
||||
.buildSnippetMap()
|
||||
.catch(() => ({}) as Record<string, string>);
|
||||
|
||||
// TODO: instantiate one browser per server instance and reuse contexts for anonymous sessions,
|
||||
// TODO: instantiate one browser per server instance and reuse contexts for anonymous sessions,
|
||||
// instead of launching a new browser for each request.
|
||||
const browser = await chromium.launch({
|
||||
headless: true,
|
||||
|
||||
@@ -81,7 +81,17 @@ export class CodeExecutorService {
|
||||
* Always call `validate()` before this method.
|
||||
*/
|
||||
async execute(ctx: ExecContext): Promise<ExecResult> {
|
||||
const { page, browser, code, log, getStepOutput, credentials, environment, snippets, result } = ctx;
|
||||
const {
|
||||
page,
|
||||
browser,
|
||||
code,
|
||||
log,
|
||||
getStepOutput,
|
||||
credentials,
|
||||
environment,
|
||||
snippets,
|
||||
result,
|
||||
} = ctx;
|
||||
const scriptLog: ScriptLogger =
|
||||
log ?? ((level, msg) => this.logger[level](msg));
|
||||
const toStr = (args: unknown[]) =>
|
||||
@@ -146,12 +156,7 @@ export class CodeExecutorService {
|
||||
"expect",
|
||||
`return (async (context, ...args) => { ${snippetCode} })(context, ...snippetArgs)`,
|
||||
);
|
||||
return snippetFn(
|
||||
scriptContext,
|
||||
fakeConsole,
|
||||
args,
|
||||
playwrightExpect,
|
||||
);
|
||||
return snippetFn(scriptContext, fakeConsole, args, playwrightExpect);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -52,8 +52,10 @@ export class ExecContextBuilder {
|
||||
|
||||
build(): ExecContext {
|
||||
if (!this.ctx.page) throw new Error("ExecContextBuilder: page is required");
|
||||
if (!this.ctx.browser) throw new Error("ExecContextBuilder: browser is required");
|
||||
if (this.ctx.code === undefined) throw new Error("ExecContextBuilder: code is required");
|
||||
if (!this.ctx.browser)
|
||||
throw new Error("ExecContextBuilder: browser is required");
|
||||
if (this.ctx.code === undefined)
|
||||
throw new Error("ExecContextBuilder: code is required");
|
||||
return this.ctx as ExecContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,9 @@ export class EnvironmentService {
|
||||
};
|
||||
}
|
||||
|
||||
async importEnvironment(dto: EnvironmentExportDto): Promise<EnvironmentEntity> {
|
||||
async importEnvironment(
|
||||
dto: EnvironmentExportDto,
|
||||
): Promise<EnvironmentEntity> {
|
||||
if (dto.id) {
|
||||
const existing = await this.repo.findOneBy({ id: dto.id });
|
||||
if (existing) {
|
||||
|
||||
+1
-4
@@ -34,10 +34,7 @@ async function bootstrap() {
|
||||
const nodeEnv = config.get("NODE_ENV");
|
||||
|
||||
app.enableCors({
|
||||
origin: [
|
||||
"http://localhost:5173",
|
||||
"http://127.0.0.1:5173",
|
||||
],
|
||||
origin: ["http://localhost:5173", "http://127.0.0.1:5173"],
|
||||
methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE", "OPTIONS"],
|
||||
credentials: true,
|
||||
});
|
||||
|
||||
@@ -359,7 +359,9 @@ export class McpService {
|
||||
resolvedCredentials = {};
|
||||
for (const [alias, credId] of Object.entries(credentials)) {
|
||||
const cred = await this.credentialService.findOne(credId);
|
||||
resolvedCredentials[alias] = cred.data ? JSON.parse(cred.data) : {};
|
||||
resolvedCredentials[alias] = cred.data
|
||||
? JSON.parse(cred.data)
|
||||
: {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,13 +704,22 @@ export class McpService {
|
||||
description: "Trigger an immediate run of a scenario by ID",
|
||||
inputSchema: {
|
||||
id: z.uuid().describe("Scenario ID to run"),
|
||||
environmentId: z.uuid().describe("Environment ID to run the scenario in"),
|
||||
saveSession: z.boolean().optional().describe("Save session after run completes"),
|
||||
environmentId: z
|
||||
.uuid()
|
||||
.describe("Environment ID to run the scenario in"),
|
||||
saveSession: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Save session after run completes"),
|
||||
},
|
||||
},
|
||||
async ({ id, environmentId, saveSession }) => {
|
||||
try {
|
||||
const run = await this.scenarioService.createRun(id, environmentId, saveSession);
|
||||
const run = await this.scenarioService.createRun(
|
||||
id,
|
||||
environmentId,
|
||||
saveSession,
|
||||
);
|
||||
return {
|
||||
content: [{ type: "text" as const, text: JSON.stringify(run) }],
|
||||
};
|
||||
@@ -817,9 +828,7 @@ export class McpService {
|
||||
{ credentialId, alias },
|
||||
);
|
||||
return {
|
||||
content: [
|
||||
{ type: "text" as const, text: JSON.stringify(result) },
|
||||
],
|
||||
content: [{ type: "text" as const, text: JSON.stringify(result) }],
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
@@ -836,7 +845,11 @@ export class McpService {
|
||||
description: "Remove a credential assignment from a scenario",
|
||||
inputSchema: {
|
||||
scenarioId: z.uuid().describe("Scenario ID"),
|
||||
scenarioCredentialId: z.uuid().describe("Scenario-credential assignment ID (not the credential ID)"),
|
||||
scenarioCredentialId: z
|
||||
.uuid()
|
||||
.describe(
|
||||
"Scenario-credential assignment ID (not the credential ID)",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ scenarioId, scenarioCredentialId }) => {
|
||||
|
||||
@@ -10,7 +10,10 @@ import { CodeExecutorService } from "../code-executor/code-executor.service";
|
||||
import { ExecContextBuilder } from "../code-executor/exec-context.builder";
|
||||
import { traceStorage } from "../common/trace-context";
|
||||
import { TraceLogger } from "../common/trace-logger";
|
||||
import { EnvironmentData, EnvironmentEntity } from "../environment/environment.entity";
|
||||
import {
|
||||
EnvironmentData,
|
||||
EnvironmentEntity,
|
||||
} from "../environment/environment.entity";
|
||||
import { SessionContextService } from "../session/session-context.service";
|
||||
import { SessionService } from "../session/session.service";
|
||||
import { SnippetService } from "../snippet/snippet.service";
|
||||
@@ -115,7 +118,7 @@ export class ScenarioSchedulerService {
|
||||
const environmentData = await this.environmentRepo
|
||||
.findOneBy({ id: run.environmentId })
|
||||
.then((env) => env?.data ?? {})
|
||||
.catch(() => ({} as EnvironmentData));
|
||||
.catch(() => ({}) as EnvironmentData);
|
||||
this.runEnvironments.set(run.id, environmentData);
|
||||
const traceId = crypto.randomUUID();
|
||||
void traceStorage.run({ traceId }, () =>
|
||||
@@ -187,7 +190,12 @@ export class ScenarioSchedulerService {
|
||||
cookies.find((c) => c.name === "token")?.value ??
|
||||
"";
|
||||
|
||||
const session = await this.sessionService.upsert(sessionName, token, cookies, localStorage);
|
||||
const session = await this.sessionService.upsert(
|
||||
sessionName,
|
||||
token,
|
||||
cookies,
|
||||
localStorage,
|
||||
);
|
||||
await this.runRepo.update(runId, { sessionId: session.id });
|
||||
this.sessionContextService.register(
|
||||
sessionName,
|
||||
|
||||
@@ -214,7 +214,11 @@ export class ScenarioController {
|
||||
@Param("id", ParseUUIDPipe) id: string,
|
||||
@Body() dto: CreateScenarioRunDto,
|
||||
) {
|
||||
return this.scenarioService.createRun(id, dto.environmentId, dto.saveSession);
|
||||
return this.scenarioService.createRun(
|
||||
id,
|
||||
dto.environmentId,
|
||||
dto.saveSession,
|
||||
);
|
||||
}
|
||||
|
||||
@Get(":id/run/:runId")
|
||||
|
||||
@@ -322,7 +322,12 @@ export class ScenarioService {
|
||||
await this.findOne(scenarioId); // 404 guard
|
||||
const run = await this.runRepo.findOne({
|
||||
where: { id: runId, scenarioId },
|
||||
relations: ["stepRuns", "stepRuns.scenarioStep", "environment", "session"],
|
||||
relations: [
|
||||
"stepRuns",
|
||||
"stepRuns.scenarioStep",
|
||||
"environment",
|
||||
"session",
|
||||
],
|
||||
order: { stepRuns: { order: "ASC" } },
|
||||
});
|
||||
if (!run)
|
||||
@@ -370,7 +375,12 @@ export class ScenarioService {
|
||||
}
|
||||
|
||||
const run = await this.runRepo.save(
|
||||
this.runRepo.create({ scenarioId, environmentId, status: "pending", saveSession }),
|
||||
this.runRepo.create({
|
||||
scenarioId,
|
||||
environmentId,
|
||||
status: "pending",
|
||||
saveSession,
|
||||
}),
|
||||
);
|
||||
|
||||
const stepRuns = scenario.steps.map((step, index) =>
|
||||
|
||||
@@ -15,7 +15,12 @@ import { SnippetExportDto } from "./dto/snippet-export.dto";
|
||||
import { UpdateSnippetDto } from "./dto/update-snippet.dto";
|
||||
import { SnippetEntity } from "./snippet.entity";
|
||||
|
||||
export type SnippetOrderBy = "id" | "alias" | "title" | "createdAt" | "updatedAt";
|
||||
export type SnippetOrderBy =
|
||||
| "id"
|
||||
| "alias"
|
||||
| "title"
|
||||
| "createdAt"
|
||||
| "updatedAt";
|
||||
|
||||
@Injectable()
|
||||
export class SnippetService implements OnModuleInit {
|
||||
@@ -47,7 +52,9 @@ export class SnippetService implements OnModuleInit {
|
||||
async create(dto: CreateSnippetDto): Promise<SnippetEntity> {
|
||||
const existing = await this.repo.findOneBy({ alias: dto.alias });
|
||||
if (existing) {
|
||||
throw new ConflictException(`Snippet alias "${dto.alias}" already exists`);
|
||||
throw new ConflictException(
|
||||
`Snippet alias "${dto.alias}" already exists`,
|
||||
);
|
||||
}
|
||||
return this.repo.save(
|
||||
this.repo.create({
|
||||
@@ -85,7 +92,9 @@ export class SnippetService implements OnModuleInit {
|
||||
if (dto.alias && dto.alias !== snippet.alias) {
|
||||
const conflict = await this.repo.findOneBy({ alias: dto.alias });
|
||||
if (conflict)
|
||||
throw new ConflictException(`Snippet alias "${dto.alias}" already exists`);
|
||||
throw new ConflictException(
|
||||
`Snippet alias "${dto.alias}" already exists`,
|
||||
);
|
||||
}
|
||||
Object.assign(snippet, dto);
|
||||
return this.repo.save(snippet);
|
||||
|
||||
@@ -3,6 +3,8 @@ import { getRepositoryToken } from "@nestjs/typeorm";
|
||||
import request from "supertest";
|
||||
import { buildTestApp } from "./app.harness";
|
||||
import { SessionEntity } from "../src/session/session.entity";
|
||||
import { EnvironmentEntity } from "../src/environment/environment.entity";
|
||||
import { CredentialEntity } from "../src/credential/credential.entity";
|
||||
import { Repository } from "typeorm";
|
||||
|
||||
/**
|
||||
@@ -15,6 +17,8 @@ import { Repository } from "typeorm";
|
||||
describe("BrowserController", () => {
|
||||
let app: INestApplication;
|
||||
let sessionRepo: Repository<SessionEntity>;
|
||||
let environmentRepo: Repository<EnvironmentEntity>;
|
||||
let credentialRepo: Repository<CredentialEntity>;
|
||||
|
||||
const FAKE_SESSION = "test-browser-session";
|
||||
|
||||
@@ -23,6 +27,12 @@ describe("BrowserController", () => {
|
||||
sessionRepo = app.get<Repository<SessionEntity>>(
|
||||
getRepositoryToken(SessionEntity),
|
||||
);
|
||||
environmentRepo = app.get<Repository<EnvironmentEntity>>(
|
||||
getRepositoryToken(EnvironmentEntity),
|
||||
);
|
||||
credentialRepo = app.get<Repository<CredentialEntity>>(
|
||||
getRepositoryToken(CredentialEntity),
|
||||
);
|
||||
|
||||
// Seed a session with minimal but valid JSON so the browser code can
|
||||
// deserialise it (it will still fail to open a real page, tested separately)
|
||||
@@ -40,6 +50,33 @@ describe("BrowserController", () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
async function createEnvironment(
|
||||
data: Record<string, string | undefined>,
|
||||
name = `browser-env-${Math.random().toString(36).slice(2, 8)}`,
|
||||
): Promise<string> {
|
||||
const environment = await environmentRepo.save(
|
||||
environmentRepo.create({
|
||||
name,
|
||||
data,
|
||||
}),
|
||||
);
|
||||
return environment.id;
|
||||
}
|
||||
|
||||
async function createCredential(
|
||||
data: Record<string, unknown>,
|
||||
name = `browser-cred-${Math.random().toString(36).slice(2, 8)}`,
|
||||
): Promise<string> {
|
||||
const credential = await credentialRepo.save(
|
||||
credentialRepo.create({
|
||||
name,
|
||||
data: JSON.stringify(data),
|
||||
lastUsedAt: null,
|
||||
}),
|
||||
);
|
||||
return credential.id;
|
||||
}
|
||||
|
||||
// ── POST /open ─────────────────────────────────────────────────────────────
|
||||
|
||||
describe("POST /open", () => {
|
||||
@@ -137,35 +174,46 @@ describe("BrowserController", () => {
|
||||
});
|
||||
|
||||
it("exposes environment via context.env in a named session", async () => {
|
||||
const environmentId = await createEnvironment({
|
||||
BASE_URL: "https://env.example.com",
|
||||
});
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.post("/exec")
|
||||
.send({
|
||||
sessionName: "no-such-session",
|
||||
code: "return context.env.BASE_URL;",
|
||||
environment: { BASE_URL: "https://env.example.com" },
|
||||
environmentId,
|
||||
})
|
||||
.expect(201);
|
||||
expect(res.body).toEqual({ result: "https://env.example.com" });
|
||||
});
|
||||
|
||||
it("exposes environment via context.env in a sessionless exec", async () => {
|
||||
const environmentId = await createEnvironment({ KEY: "value123" });
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.post("/exec")
|
||||
.send({
|
||||
code: "return context.env.KEY;",
|
||||
environment: { KEY: "value123" },
|
||||
environmentId,
|
||||
})
|
||||
.expect(201);
|
||||
expect(res.body).toEqual({ result: "value123" });
|
||||
});
|
||||
|
||||
it("exposes credentials via context.getCredential in a named session", async () => {
|
||||
const credentialId = await createCredential({
|
||||
username: "user1",
|
||||
password: "pass1",
|
||||
});
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.post("/exec")
|
||||
.send({
|
||||
sessionName: "no-such-session",
|
||||
code: "return context.getCredential('admin');",
|
||||
credentials: { admin: { username: "user1", password: "pass1" } },
|
||||
credentials: { admin: credentialId },
|
||||
})
|
||||
.expect(201);
|
||||
expect(res.body).toEqual({
|
||||
@@ -174,11 +222,13 @@ describe("BrowserController", () => {
|
||||
});
|
||||
|
||||
it("exposes credentials via context.getCredential in a sessionless exec", async () => {
|
||||
const credentialId = await createCredential({ token: "abc" });
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.post("/exec")
|
||||
.send({
|
||||
code: "return context.getCredential('svc');",
|
||||
credentials: { svc: { token: "abc" } },
|
||||
credentials: { svc: credentialId },
|
||||
})
|
||||
.expect(201);
|
||||
expect(res.body).toEqual({ result: { token: "abc" } });
|
||||
|
||||
@@ -160,7 +160,9 @@ describe("EnvironmentController", () => {
|
||||
});
|
||||
|
||||
it("returns 404 for unknown id", async () => {
|
||||
await request(app.getHttpServer()).get("/environments/00000000-0000-0000-0000-000000000001").expect(404);
|
||||
await request(app.getHttpServer())
|
||||
.get("/environments/00000000-0000-0000-0000-000000000001")
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it("returns 400 for non-numeric id", async () => {
|
||||
|
||||
@@ -75,7 +75,10 @@ describe("McpController", () => {
|
||||
it("returns MCP error for removed tool", async () => {
|
||||
const { status, rpc } = await mcpCall("list_keys");
|
||||
expect(status).toBe(200);
|
||||
const result = rpc.result as { isError: boolean; content?: { text: string }[] };
|
||||
const result = rpc.result as {
|
||||
isError: boolean;
|
||||
content?: { text: string }[];
|
||||
};
|
||||
expect(result.isError).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -163,7 +163,9 @@ describe("ScenarioController", () => {
|
||||
});
|
||||
|
||||
it("returns 404 for unknown id", async () => {
|
||||
await request(app.getHttpServer()).get("/scenarios/00000000-0000-0000-0000-000000000001").expect(404);
|
||||
await request(app.getHttpServer())
|
||||
.get("/scenarios/00000000-0000-0000-0000-000000000001")
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -199,7 +201,9 @@ describe("ScenarioController", () => {
|
||||
});
|
||||
|
||||
it("returns 404 for unknown id", async () => {
|
||||
await request(app.getHttpServer()).delete("/scenarios/00000000-0000-0000-0000-000000000001").expect(404);
|
||||
await request(app.getHttpServer())
|
||||
.delete("/scenarios/00000000-0000-0000-0000-000000000001")
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -327,8 +331,8 @@ describe("ScenarioController", () => {
|
||||
it("reorders by exact target index", async () => {
|
||||
const sc = await createScenario();
|
||||
const stepA = await createStep(sc.id, { title: "A" });
|
||||
const stepB = await createStep(sc.id, { title: "B" });
|
||||
const stepC = await createStep(sc.id, { title: "C" });
|
||||
await createStep(sc.id, { title: "B" });
|
||||
await createStep(sc.id, { title: "C" });
|
||||
const stepD = await createStep(sc.id, { title: "D" });
|
||||
|
||||
await request(app.getHttpServer())
|
||||
@@ -339,12 +343,15 @@ describe("ScenarioController", () => {
|
||||
let res = await request(app.getHttpServer())
|
||||
.get(`/scenarios/${sc.id}`)
|
||||
.expect(200);
|
||||
expect(
|
||||
res.body.steps.map((s: { title: string }) => s.title),
|
||||
).toEqual(["B", "C", "A", "D"]);
|
||||
expect(
|
||||
res.body.steps.map((s: { order: number }) => s.order),
|
||||
).toEqual([0, 1, 2, 3]);
|
||||
expect(res.body.steps.map((s: { title: string }) => s.title)).toEqual([
|
||||
"B",
|
||||
"C",
|
||||
"A",
|
||||
"D",
|
||||
]);
|
||||
expect(res.body.steps.map((s: { order: number }) => s.order)).toEqual([
|
||||
0, 1, 2, 3,
|
||||
]);
|
||||
|
||||
await request(app.getHttpServer())
|
||||
.patch(`/scenarios/${sc.id}/steps/${stepD.id}`)
|
||||
@@ -354,12 +361,15 @@ describe("ScenarioController", () => {
|
||||
res = await request(app.getHttpServer())
|
||||
.get(`/scenarios/${sc.id}`)
|
||||
.expect(200);
|
||||
expect(
|
||||
res.body.steps.map((s: { title: string }) => s.title),
|
||||
).toEqual(["D", "B", "C", "A"]);
|
||||
expect(
|
||||
res.body.steps.map((s: { order: number }) => s.order),
|
||||
).toEqual([0, 1, 2, 3]);
|
||||
expect(res.body.steps.map((s: { title: string }) => s.title)).toEqual([
|
||||
"D",
|
||||
"B",
|
||||
"C",
|
||||
"A",
|
||||
]);
|
||||
expect(res.body.steps.map((s: { order: number }) => s.order)).toEqual([
|
||||
0, 1, 2, 3,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -395,9 +405,7 @@ describe("ScenarioController", () => {
|
||||
expect(Array.isArray(res.stepRuns)).toBe(true);
|
||||
expect(res.stepRuns).toHaveLength(3);
|
||||
|
||||
const statuses = res.stepRuns.map(
|
||||
(s: { status: string }) => s.status,
|
||||
);
|
||||
const statuses = res.stepRuns.map((s: { status: string }) => s.status);
|
||||
expect(statuses[0]).toBe("pending");
|
||||
expect(statuses[1]).toBe("waiting");
|
||||
expect(statuses[2]).toBe("waiting");
|
||||
@@ -495,9 +503,18 @@ describe("ScenarioController", () => {
|
||||
|
||||
it("exports steps ordered by sequential position", async () => {
|
||||
const sc = await createScenario("export-order");
|
||||
await createStep(sc.id, { sessionName: "s", execCode: "return 'first';" });
|
||||
await createStep(sc.id, { sessionName: "s", execCode: "return 'second';" });
|
||||
await createStep(sc.id, { sessionName: "s", execCode: "return 'third';" });
|
||||
await createStep(sc.id, {
|
||||
sessionName: "s",
|
||||
execCode: "return 'first';",
|
||||
});
|
||||
await createStep(sc.id, {
|
||||
sessionName: "s",
|
||||
execCode: "return 'second';",
|
||||
});
|
||||
await createStep(sc.id, {
|
||||
sessionName: "s",
|
||||
execCode: "return 'third';",
|
||||
});
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.get(`/scenarios/${sc.id}/export`)
|
||||
@@ -616,9 +633,7 @@ describe("ScenarioController", () => {
|
||||
|
||||
expect(importRes.body.name).toBe("roundtrip");
|
||||
expect(importRes.body.steps).toHaveLength(1);
|
||||
expect(importRes.body.steps[0].execCode).toBe(
|
||||
exported.steps[0].execCode,
|
||||
);
|
||||
expect(importRes.body.steps[0].execCode).toBe(exported.steps[0].execCode);
|
||||
});
|
||||
|
||||
it("imports with empty steps array", async () => {
|
||||
@@ -663,7 +678,7 @@ describe("ScenarioController", () => {
|
||||
const sc = await createScenario();
|
||||
await createStep(sc.id, { order: 0 });
|
||||
const runRes = await createRun(sc.id);
|
||||
const runId = runRes.id;
|
||||
const runId = runRes.id;
|
||||
|
||||
const res = await request(app.getHttpServer())
|
||||
.get(`/scenarios/${sc.id}/run/${runId}`)
|
||||
@@ -766,7 +781,9 @@ describe("ScenarioController", () => {
|
||||
it("returns 404 for unknown run", async () => {
|
||||
const sc = await createScenario();
|
||||
await request(app.getHttpServer())
|
||||
.post(`/scenarios/${sc.id}/run/00000000-0000-0000-0000-000000000001/wait`)
|
||||
.post(
|
||||
`/scenarios/${sc.id}/run/00000000-0000-0000-0000-000000000001/wait`,
|
||||
)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
|
||||
@@ -141,7 +141,9 @@ describe("SessionController", () => {
|
||||
});
|
||||
|
||||
it("returns 404 for unknown id", async () => {
|
||||
await request(app.getHttpServer()).delete("/sessions/00000000-0000-0000-0000-000000000001").expect(404);
|
||||
await request(app.getHttpServer())
|
||||
.delete("/sessions/00000000-0000-0000-0000-000000000001")
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it("returns 400 for non-numeric id", async () => {
|
||||
|
||||
Reference in New Issue
Block a user