diff --git a/src/cli.ts b/src/cli.ts index b41ab6a..52de606 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -5,14 +5,15 @@ import { createEnvironment, deleteEnvironment, executeTests, - getNotifications, - getTestCase, - getTestReport, + listNotifications, + listTestCase, + listTestReport, listEnvironments, listPrivateLocations, registerLocation, unregisterLocation, updateEnvironment, + listTestCases, } from "./tools"; import { Config, loadConfig, saveConfig } from "./config"; import { promptUser, resolveTestTargetId } from "./helpers"; @@ -163,7 +164,7 @@ export const buildCmd = (): Command => { .option("-t, --test-target-id ", "Test target ID") .action(async (options) => { const testTargetId = await resolveTestTargetId(options.testTargetId); - await getTestReport({ + await listTestReport({ ...options, testTargetId, }); @@ -255,7 +256,7 @@ export const buildCmd = (): Command => { .option( "-l, --host-network", "Use host network (default: false). If set you can use localhost directly", - false + false, ) .action(startPrivateLocationWorker); @@ -272,7 +273,7 @@ export const buildCmd = (): Command => { options.testTargetId ); command.setOptionValue("testTargetId", resolvedTestTargetId); - void getNotifications(options); + void listNotifications(options); }); createCommandWithCommonOptions("test-case") @@ -284,7 +285,7 @@ export const buildCmd = (): Command => { options.testTargetId ); command.setOptionValue("testTargetId", resolvedTestTargetId); - void getTestCase(options); + void listTestCase(options); }); createCommandWithCommonOptions("create-discovery") @@ -309,5 +310,16 @@ export const buildCmd = (): Command => { void createDiscovery(options); }); + createCommandWithCommonOptions("list-test-cases") + .description("List all test cases") + .option("-t, --test-target-id ", "Test target ID") + .action(async (options, command) => { + const resolvedTestTargetId = await resolveTestTargetId( + options.testTargetId, + ); + command.setOptionValue("testTargetId", resolvedTestTargetId); + void listTestCases({...options, status: "ENABLED"}); + }); + return program; }; diff --git a/src/tools/client.ts b/src/tools/client.ts index 03ff9ff..4279cec 100644 --- a/src/tools/client.ts +++ b/src/tools/client.ts @@ -47,6 +47,9 @@ export const handleError = (error: ErrorResponse) => { } }; -export const outputResult = (result: unknown): void => { +export type ListOptions = { + json?: boolean; +}; +export const logJson = (result: unknown): void => { console.log(JSON.stringify(result, null, 2)); }; diff --git a/src/tools/discoveries.ts b/src/tools/discoveries.ts index 554db7f..037c37b 100644 --- a/src/tools/discoveries.ts +++ b/src/tools/discoveries.ts @@ -1,12 +1,12 @@ import type { components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; -export type createDiscoveryBody = +export type CreateDiscoveryBody = components["schemas"]["ExternalDiscoveryBody"]; export type DiscoveryResponse = components["schemas"]["DiscoveryResponse"]; export const createDiscovery = async ( - options: createDiscoveryBody & { json?: boolean; testTargetId: string }, + options: CreateDiscoveryBody & { testTargetId: string } & ListOptions, ): Promise => { const requestBody = { name: options.name, @@ -39,7 +39,7 @@ export const createDiscovery = async ( const response = data as DiscoveryResponse; if (options.json) { - outputResult(response); + logJson(response); return; } diff --git a/src/tools/environments.ts b/src/tools/environments.ts index a8d4d88..5732e8c 100644 --- a/src/tools/environments.ts +++ b/src/tools/environments.ts @@ -1,7 +1,7 @@ import type { paths, components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; -export type listEnvironmentsOptions = +export type GetEnvironmentsOptions = paths["/apiKey/v2/test-targets/{testTargetId}/environments"]["get"]["parameters"]["path"]; export type PostEnvironmentOptions = paths["/apiKey/v2/test-targets/{testTargetId}/environments"]["post"]["requestBody"]["content"]["application/json"] & { @@ -12,37 +12,26 @@ export type UpdateEnvironmentOptions = export type EnvironmentResponse = components["schemas"]["EnvironmentResponse"]; export const listEnvironments = async ( - options: listEnvironmentsOptions & { json?: boolean }, + options: GetEnvironmentsOptions & ListOptions, ): Promise => { - const { data, error } = await client.GET( - "/apiKey/v2/test-targets/{testTargetId}/environments", - { - params: { - path: { testTargetId: options.testTargetId }, - }, - }, - ); - - handleError(error); + const environments = await getEnvironments(options); if (options.json) { - outputResult(data); + logJson(environments); return; } console.log("Environments:"); - if (data) { - data.forEach((environment) => { - console.log(`- Name: ${environment.name}`); - console.log(` ID: ${environment.id}`); - console.log(` Discovery URL: ${environment.discoveryUrl}`); - console.log(` Updated At: ${environment.updatedAt}`); - }); - } + environments.forEach((environment) => { + console.log(`- Name: ${environment.name}`); + console.log(` ID: ${environment.id}`); + console.log(` Discovery URL: ${environment.discoveryUrl}`); + console.log(` Updated At: ${environment.updatedAt}`); + }); }; export const getEnvironments = async ( - options: listEnvironmentsOptions & { json?: boolean }, + options: GetEnvironmentsOptions, ): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/environments", @@ -59,23 +48,18 @@ export const getEnvironments = async ( throw new Error("no environments found"); } - if (options.json) { - outputResult(data); - } - return data; }; export const createEnvironment = async ( options: PostEnvironmentOptions & { - json?: boolean; testAccountUsername?: string; testAccountPassword?: string; basicAuthUsername?: string; basicAuthPassword?: string; privateLocationName?: string; testAccountOtpInitializerKey?: string; - }, + } & ListOptions, ): Promise => { const { data, error } = await client.POST( "/apiKey/v2/test-targets/{testTargetId}/environments", @@ -106,7 +90,7 @@ export const createEnvironment = async ( const response = data as EnvironmentResponse; if (options.json) { - outputResult(response); + logJson(response); return; } @@ -121,14 +105,13 @@ export const updateEnvironment = async ( options: UpdateEnvironmentOptions & { testTargetId: string; environmentId: string; - json?: boolean; testAccountUsername?: string; testAccountPassword?: string; basicAuthUsername?: string; basicAuthPassword?: string; privateLocationName?: string; testAccountOtpInitializerKey?: string; - }, + } & ListOptions, ): Promise => { const { data, error } = await client.PATCH( "/apiKey/v2/test-targets/{testTargetId}/environments/{environmentId}", @@ -161,7 +144,7 @@ export const updateEnvironment = async ( const response = data as EnvironmentResponse; if (options.json) { - outputResult(response); + logJson(response); return; } @@ -172,11 +155,12 @@ export const updateEnvironment = async ( console.log(` Updated At: ${response.updatedAt}`); }; -export const deleteEnvironment = async (options: { - testTargetId: string; - environmentId: string; - json?: boolean; -}): Promise => { +export const deleteEnvironment = async ( + options: { + testTargetId: string; + environmentId: string; + } & ListOptions, +): Promise => { const { error } = await client.DELETE( "/apiKey/v2/test-targets/{testTargetId}/environments/{environmentId}", { @@ -192,7 +176,7 @@ export const deleteEnvironment = async (options: { handleError(error); if (options.json) { - outputResult({ success: true }); + logJson({ success: true }); return; } diff --git a/src/tools/notifications.ts b/src/tools/notifications.ts index 171e1b4..193a2cc 100644 --- a/src/tools/notifications.ts +++ b/src/tools/notifications.ts @@ -1,12 +1,12 @@ import type { paths, components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; -export type getNotificationsParams = +export type GetNotificationsParams = paths["/apiKey/v2/test-targets/{testTargetId}/notifications"]["get"]["parameters"]["path"]; export type Notification = components["schemas"]["Notification"]; -export const getNotifications = async ( - options: getNotificationsParams & { json?: boolean }, +export const listNotifications = async ( + options: GetNotificationsParams & ListOptions, ): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/notifications", @@ -22,7 +22,7 @@ export const getNotifications = async ( handleError(error); const response = data as Notification[]; if (options.json) { - outputResult(response); + logJson(response); return; } diff --git a/src/tools/playwright.ts b/src/tools/playwright.ts index 1b68153..5a308ad 100644 --- a/src/tools/playwright.ts +++ b/src/tools/playwright.ts @@ -1,4 +1,4 @@ -import { client, handleError, outputResult } from "./client"; +import { client, handleError } from "./client"; export const getPlaywrightConfig = async (options: { testTargetId: string; @@ -6,7 +6,6 @@ export const getPlaywrightConfig = async (options: { url: string; outputDir: string; headless?: boolean; - json?: boolean; }): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/config", @@ -32,10 +31,6 @@ export const getPlaywrightConfig = async (options: { throw new Error("no config found"); } - if (options.json) { - outputResult(data); - } - return data; }; @@ -44,7 +39,6 @@ export const getPlaywrightCode = async (options: { testCaseId: string; environmentId?: string; executionUrl: string; - json?: boolean; }): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/test-cases/{testCaseId}/code", @@ -65,13 +59,8 @@ export const getPlaywrightCode = async (options: { handleError(error); if (!data) { - console.log({ data, error }); throw new Error("no test code found"); } - if (options.json) { - outputResult(data); - } - return data.testCode; }; diff --git a/src/tools/private-locations.ts b/src/tools/private-locations.ts index fa6db53..b91a414 100644 --- a/src/tools/private-locations.ts +++ b/src/tools/private-locations.ts @@ -1,16 +1,17 @@ import type { components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; export type SuccessResponse = components["schemas"]["SuccessResponse"]; export type PrivateLocationInfo = components["schemas"]["PrivateLocationInfo"]; -export const registerLocation = async (options: { - address: string; - name: string; - username: string; - password: string; - json?: boolean; -}): Promise => { +export const registerLocation = async ( + options: { + address: string; + name: string; + username: string; + password: string; + } & ListOptions, +): Promise => { const { data, error } = await client.PUT( "/apiKey/v1/private-location/register", { @@ -30,17 +31,18 @@ export const registerLocation = async (options: { const response = data as SuccessResponse; if (options.json) { - outputResult(response); + logJson(response); return; } console.log("Registration result:", response.success ? "Success" : "Failed"); }; -export const unregisterLocation = async (options: { - name: string; - json?: boolean; -}): Promise => { +export const unregisterLocation = async ( + options: { + name: string; + } & ListOptions, +): Promise => { const { data, error } = await client.PUT( "/apiKey/v1/private-location/unregister", { @@ -54,7 +56,7 @@ export const unregisterLocation = async (options: { const response = data as SuccessResponse; if (options.json) { - outputResult(response); + logJson(response); return; } @@ -64,16 +66,16 @@ export const unregisterLocation = async (options: { ); }; -export const listPrivateLocations = async (options: { - json?: boolean; -}): Promise => { +export const listPrivateLocations = async ( + options: ListOptions, +): Promise => { const { data, error } = await client.GET("/apiKey/v1/private-location"); handleError(error); const response = data as PrivateLocationInfo; if (options.json) { - outputResult(response); + logJson(response); return; } diff --git a/src/tools/test-cases.ts b/src/tools/test-cases.ts index 6d29999..857eec4 100644 --- a/src/tools/test-cases.ts +++ b/src/tools/test-cases.ts @@ -1,13 +1,13 @@ import type { paths, components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; export type TestCaseResponse = components["schemas"]["TestCaseResponse"]; export type TestCasesResponse = components["schemas"]["TestCasesResponse"]; -export type getTestCaseParams = +export type GetTestCaseParams = paths["/apiKey/v2/test-targets/{testTargetId}/test-cases/{testCaseId}"]["get"]["parameters"]["path"]; -export const getTestCase = async ( - options: getTestCaseParams & { json?: boolean }, +export const listTestCase = async ( + options: GetTestCaseParams & ListOptions, ): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/test-cases/{testCaseId}", @@ -26,7 +26,7 @@ export const getTestCase = async ( const response = data as TestCaseResponse; if (options.json) { - outputResult(response); + logJson(response); return; } @@ -65,11 +65,13 @@ export const getTestCase = async ( } }; -export const getTestCases = async (options: { +export type GetTestCasesOptions = { testTargetId: string; status?: string; - json?: boolean; -}): Promise => { +}; +export const getTestCases = async ( + options: GetTestCasesOptions, +): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/test-cases", { @@ -90,9 +92,27 @@ export const getTestCases = async (options: { throw new Error("no test cases found"); } + return data; +}; +export const listTestCases = async ( + options: GetTestCasesOptions & ListOptions, +): Promise => { + const testCases = await getTestCases(options); + if (options.json) { - outputResult(data); + logJson(testCases); + return; } - return data; + console.log("Test Cases:"); + testCases.forEach((testCase, idx) => { + const idxString = `${idx + 1}. `.padEnd( + testCases.length.toString().length + 2, + ); + const paddingString = " ".repeat(idxString.length); + console.log(`${idxString}Description: ${testCase.description}`); + console.log(`${paddingString}ID: ${testCase.id}`); + console.log(`${paddingString}Created At: ${testCase.createdAt}`); + console.log(`${paddingString}Updated At: ${testCase.updatedAt}`); + }); }; diff --git a/src/tools/test-reports.ts b/src/tools/test-reports.ts index b38211b..49436c1 100644 --- a/src/tools/test-reports.ts +++ b/src/tools/test-reports.ts @@ -1,14 +1,14 @@ import type { paths, components } from "../api"; // generated by openapi-typescript -import { client, handleError, outputResult } from "./client"; +import { client, handleError, ListOptions, logJson } from "./client"; -export type executeTestsBody = +export type ExecuteTestsBody = components["schemas"]["TestTargetExecutionRequest"]; -export type getTestReportParams = +export type GetTestReportParams = paths["/apiKey/v2/test-targets/{testTargetId}/test-reports/{testReportId}"]["get"]["parameters"]["path"]; export type TestReport = components["schemas"]["TestReport"]; export const executeTests = async ( - options: executeTestsBody & { json?: boolean; description?: string }, + options: ExecuteTestsBody & { description?: string } & ListOptions, ): Promise => { const { data, error } = await client.POST("/apiKey/v2/execute", { body: { @@ -31,7 +31,7 @@ export const executeTests = async ( handleError(error); if (options.json) { - outputResult(data); + logJson(data); return; } @@ -55,8 +55,8 @@ export const executeTests = async ( } }; -export const getTestReport = async ( - options: getTestReportParams & { json?: boolean }, +export const listTestReport = async ( + options: GetTestReportParams & ListOptions, ): Promise => { const { data, error } = await client.GET( "/apiKey/v2/test-targets/{testTargetId}/test-reports/{testReportId}", @@ -73,7 +73,7 @@ export const getTestReport = async ( handleError(error); if (options.json) { - outputResult(data); + logJson(data); return; }