@smooai/testing 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,172 @@
1
+ // src/lib/index.ts
2
+ import { readFileSync } from "fs";
3
+ var DEFAULT_API_URL = "https://api.production.smoo.ai";
4
+ var DEFAULT_AUTH_URL = "https://auth.production.smoo.ai/token";
5
+ var SmooTestingClient = class {
6
+ credentials;
7
+ token = null;
8
+ tokenExpiresAt = 0;
9
+ constructor(options) {
10
+ this.credentials = {
11
+ clientId: options.clientId,
12
+ clientSecret: options.clientSecret,
13
+ orgId: options.orgId,
14
+ apiUrl: (options.apiUrl ?? DEFAULT_API_URL).replace(/\/+$/, ""),
15
+ authUrl: options.authUrl ?? DEFAULT_AUTH_URL
16
+ };
17
+ }
18
+ // ── Auth ──
19
+ async authenticate() {
20
+ if (this.token && Date.now() < this.tokenExpiresAt - 6e4) {
21
+ return this.token;
22
+ }
23
+ const response = await fetch(this.credentials.authUrl, {
24
+ method: "POST",
25
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
26
+ body: new URLSearchParams({
27
+ grant_type: "client_credentials",
28
+ provider: "client_credentials",
29
+ client_id: this.credentials.clientId,
30
+ client_secret: this.credentials.clientSecret
31
+ })
32
+ });
33
+ if (!response.ok) {
34
+ const body = await response.text().catch(() => "");
35
+ throw new Error(`Authentication failed: HTTP ${response.status}${body ? ` \u2014 ${body}` : ""}`);
36
+ }
37
+ const data = await response.json();
38
+ if (!data.access_token) {
39
+ throw new Error("Authentication failed: no access_token in response");
40
+ }
41
+ this.token = data.access_token;
42
+ this.tokenExpiresAt = Date.now() + (data.expires_in || 3600) * 1e3;
43
+ return this.token;
44
+ }
45
+ async request(method, path, body, retry = true) {
46
+ const token = await this.authenticate();
47
+ const url = `${this.credentials.apiUrl}/organizations/${this.credentials.orgId}${path}`;
48
+ const response = await fetch(url, {
49
+ method,
50
+ headers: {
51
+ Authorization: `Bearer ${token}`,
52
+ "Content-Type": "application/json"
53
+ },
54
+ body: body != null ? JSON.stringify(body) : void 0
55
+ });
56
+ if (response.status === 401 && retry) {
57
+ this.token = null;
58
+ this.tokenExpiresAt = 0;
59
+ return this.request(method, path, body, false);
60
+ }
61
+ if (!response.ok) {
62
+ const errorBody = await response.text().catch(() => "");
63
+ throw new Error(`API error: HTTP ${response.status} ${response.statusText}${errorBody ? ` \u2014 ${errorBody}` : ""}`);
64
+ }
65
+ const text = await response.text();
66
+ if (!text) return void 0;
67
+ return JSON.parse(text);
68
+ }
69
+ buildQueryString(params) {
70
+ if (!params) return "";
71
+ const sp = new URLSearchParams();
72
+ for (const [key, value] of Object.entries(params)) {
73
+ if (value != null) sp.set(key, String(value));
74
+ }
75
+ const qs = sp.toString();
76
+ return qs ? `?${qs}` : "";
77
+ }
78
+ // ── Test Runs ──
79
+ async createRun(input) {
80
+ return this.request("POST", "/testing/runs", input);
81
+ }
82
+ async listRuns(filters) {
83
+ const qs = this.buildQueryString(filters);
84
+ return this.request("GET", `/testing/runs${qs}`);
85
+ }
86
+ async getRun(id) {
87
+ return this.request("GET", `/testing/runs/${id}`);
88
+ }
89
+ async updateRun(id, input) {
90
+ return this.request("PATCH", `/testing/runs/${id}`, input);
91
+ }
92
+ async submitResults(runId, ctrf) {
93
+ return this.request("POST", `/testing/runs/${runId}/results`, ctrf);
94
+ }
95
+ // ── Test Cases ──
96
+ async createCase(input) {
97
+ return this.request("POST", "/testing/cases", input);
98
+ }
99
+ async listCases(filters) {
100
+ const qs = this.buildQueryString(filters);
101
+ return this.request("GET", `/testing/cases${qs}`);
102
+ }
103
+ async getCase(id) {
104
+ return this.request("GET", `/testing/cases/${id}`);
105
+ }
106
+ async updateCase(id, input) {
107
+ return this.request("PATCH", `/testing/cases/${id}`, input);
108
+ }
109
+ async deleteCase(id) {
110
+ await this.request("DELETE", `/testing/cases/${id}`);
111
+ }
112
+ // ── Test Environments ──
113
+ async createEnvironment(input) {
114
+ return this.request("POST", "/testing/environments", input);
115
+ }
116
+ async listEnvironments() {
117
+ return this.request("GET", "/testing/environments");
118
+ }
119
+ async getEnvironment(id) {
120
+ return this.request("GET", `/testing/environments/${id}`);
121
+ }
122
+ async updateEnvironment(id, input) {
123
+ return this.request("PATCH", `/testing/environments/${id}`, input);
124
+ }
125
+ // ── Deployments ──
126
+ async createDeployment(input) {
127
+ return this.request("POST", "/testing/deployments", input);
128
+ }
129
+ async listDeployments(filters) {
130
+ const qs = this.buildQueryString(filters);
131
+ return this.request("GET", `/testing/deployments${qs}`);
132
+ }
133
+ async getDeployment(id) {
134
+ return this.request("GET", `/testing/deployments/${id}`);
135
+ }
136
+ async updateDeployment(id, input) {
137
+ return this.request("PATCH", `/testing/deployments/${id}`, input);
138
+ }
139
+ async deleteDeployment(id) {
140
+ await this.request("DELETE", `/testing/deployments/${id}`);
141
+ }
142
+ // ── High-Level: Report ──
143
+ /**
144
+ * High-level method that creates a test run, submits CTRF results, and returns the updated run.
145
+ */
146
+ async report(ctrfFilePath, options) {
147
+ const raw = readFileSync(ctrfFilePath, "utf-8");
148
+ const ctrf = JSON.parse(raw);
149
+ const run = await this.createRun({
150
+ name: options?.name ?? ctrfFilePath,
151
+ environment: options?.environment,
152
+ deploymentId: options?.deploymentId,
153
+ tool: options?.tool ?? ctrf.results.tool?.name,
154
+ buildName: options?.buildName,
155
+ buildUrl: options?.buildUrl
156
+ });
157
+ try {
158
+ await this.submitResults(run.id, ctrf);
159
+ } catch (err) {
160
+ await this.updateRun(run.id, {
161
+ status: "errored",
162
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
163
+ });
164
+ throw err;
165
+ }
166
+ return this.getRun(run.id);
167
+ }
168
+ };
169
+ export {
170
+ SmooTestingClient
171
+ };
172
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/index.ts"],"sourcesContent":["/**\n * SmooTestingClient — programmatic library for the Smoo AI Testing API.\n */\n\nimport { readFileSync } from 'fs';\nimport type {\n CtrfReport,\n CreateDeploymentInput,\n CreateTestCaseInput,\n CreateTestEnvironmentInput,\n CreateTestRunInput,\n Credentials,\n Deployment,\n ListDeploymentsFilters,\n ListTestCasesFilters,\n ListTestRunsFilters,\n PaginatedResponse,\n SmooTestingClientOptions,\n TestCase,\n TestEnvironment,\n TestRun,\n TokenResponse,\n UpdateDeploymentInput,\n UpdateTestCaseInput,\n UpdateTestEnvironmentInput,\n UpdateTestRunInput,\n} from './types';\n\nconst DEFAULT_API_URL = 'https://api.production.smoo.ai';\nconst DEFAULT_AUTH_URL = 'https://auth.production.smoo.ai/token';\n\nexport class SmooTestingClient {\n private credentials: Credentials;\n private token: string | null = null;\n private tokenExpiresAt = 0;\n\n constructor(options: SmooTestingClientOptions) {\n this.credentials = {\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n orgId: options.orgId,\n apiUrl: (options.apiUrl ?? DEFAULT_API_URL).replace(/\\/+$/, ''),\n authUrl: options.authUrl ?? DEFAULT_AUTH_URL,\n };\n }\n\n // ── Auth ──\n\n private async authenticate(): Promise<string> {\n if (this.token && Date.now() < this.tokenExpiresAt - 60_000) {\n return this.token;\n }\n\n const response = await fetch(this.credentials.authUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n provider: 'client_credentials',\n client_id: this.credentials.clientId,\n client_secret: this.credentials.clientSecret,\n }),\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n throw new Error(`Authentication failed: HTTP ${response.status}${body ? ` — ${body}` : ''}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n if (!data.access_token) {\n throw new Error('Authentication failed: no access_token in response');\n }\n\n this.token = data.access_token;\n this.tokenExpiresAt = Date.now() + (data.expires_in || 3600) * 1000;\n return this.token;\n }\n\n private async request<T>(method: string, path: string, body?: unknown, retry = true): Promise<T> {\n const token = await this.authenticate();\n const url = `${this.credentials.apiUrl}/organizations/${this.credentials.orgId}${path}`;\n\n const response = await fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: body != null ? JSON.stringify(body) : undefined,\n });\n\n if (response.status === 401 && retry) {\n this.token = null;\n this.tokenExpiresAt = 0;\n return this.request<T>(method, path, body, false);\n }\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => '');\n throw new Error(`API error: HTTP ${response.status} ${response.statusText}${errorBody ? ` — ${errorBody}` : ''}`);\n }\n\n const text = await response.text();\n if (!text) return undefined as T;\n return JSON.parse(text) as T;\n }\n\n private buildQueryString(params?: Record<string, string | number | undefined>): string {\n if (!params) return '';\n const sp = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value != null) sp.set(key, String(value));\n }\n const qs = sp.toString();\n return qs ? `?${qs}` : '';\n }\n\n // ── Test Runs ──\n\n async createRun(input: CreateTestRunInput): Promise<TestRun> {\n return this.request<TestRun>('POST', '/testing/runs', input);\n }\n\n async listRuns(filters?: ListTestRunsFilters): Promise<PaginatedResponse<TestRun>> {\n const qs = this.buildQueryString(filters as Record<string, string | number | undefined>);\n return this.request<PaginatedResponse<TestRun>>('GET', `/testing/runs${qs}`);\n }\n\n async getRun(id: string): Promise<TestRun> {\n return this.request<TestRun>('GET', `/testing/runs/${id}`);\n }\n\n async updateRun(id: string, input: UpdateTestRunInput): Promise<TestRun> {\n return this.request<TestRun>('PATCH', `/testing/runs/${id}`, input);\n }\n\n async submitResults(runId: string, ctrf: CtrfReport): Promise<{ count: number }> {\n return this.request<{ count: number }>('POST', `/testing/runs/${runId}/results`, ctrf);\n }\n\n // ── Test Cases ──\n\n async createCase(input: CreateTestCaseInput): Promise<TestCase> {\n return this.request<TestCase>('POST', '/testing/cases', input);\n }\n\n async listCases(filters?: ListTestCasesFilters): Promise<PaginatedResponse<TestCase>> {\n const qs = this.buildQueryString(filters as Record<string, string | number | undefined>);\n return this.request<PaginatedResponse<TestCase>>('GET', `/testing/cases${qs}`);\n }\n\n async getCase(id: string): Promise<TestCase> {\n return this.request<TestCase>('GET', `/testing/cases/${id}`);\n }\n\n async updateCase(id: string, input: UpdateTestCaseInput): Promise<TestCase> {\n return this.request<TestCase>('PATCH', `/testing/cases/${id}`, input);\n }\n\n async deleteCase(id: string): Promise<void> {\n await this.request<unknown>('DELETE', `/testing/cases/${id}`);\n }\n\n // ── Test Environments ──\n\n async createEnvironment(input: CreateTestEnvironmentInput): Promise<TestEnvironment> {\n return this.request<TestEnvironment>('POST', '/testing/environments', input);\n }\n\n async listEnvironments(): Promise<TestEnvironment[]> {\n return this.request<TestEnvironment[]>('GET', '/testing/environments');\n }\n\n async getEnvironment(id: string): Promise<TestEnvironment> {\n return this.request<TestEnvironment>('GET', `/testing/environments/${id}`);\n }\n\n async updateEnvironment(id: string, input: UpdateTestEnvironmentInput): Promise<TestEnvironment> {\n return this.request<TestEnvironment>('PATCH', `/testing/environments/${id}`, input);\n }\n\n // ── Deployments ──\n\n async createDeployment(input: CreateDeploymentInput): Promise<Deployment> {\n return this.request<Deployment>('POST', '/testing/deployments', input);\n }\n\n async listDeployments(filters?: ListDeploymentsFilters): Promise<PaginatedResponse<Deployment>> {\n const qs = this.buildQueryString(filters as Record<string, string | number | undefined>);\n return this.request<PaginatedResponse<Deployment>>('GET', `/testing/deployments${qs}`);\n }\n\n async getDeployment(id: string): Promise<Deployment> {\n return this.request<Deployment>('GET', `/testing/deployments/${id}`);\n }\n\n async updateDeployment(id: string, input: UpdateDeploymentInput): Promise<Deployment> {\n return this.request<Deployment>('PATCH', `/testing/deployments/${id}`, input);\n }\n\n async deleteDeployment(id: string): Promise<void> {\n await this.request<unknown>('DELETE', `/testing/deployments/${id}`);\n }\n\n // ── High-Level: Report ──\n\n /**\n * High-level method that creates a test run, submits CTRF results, and returns the updated run.\n */\n async report(\n ctrfFilePath: string,\n options?: {\n name?: string;\n environment?: string;\n deploymentId?: string;\n tool?: string;\n buildName?: string;\n buildUrl?: string;\n },\n ): Promise<TestRun> {\n const raw = readFileSync(ctrfFilePath, 'utf-8');\n const ctrf = JSON.parse(raw) as CtrfReport;\n\n const run = await this.createRun({\n name: options?.name ?? ctrfFilePath,\n environment: options?.environment,\n deploymentId: options?.deploymentId,\n tool: options?.tool ?? ctrf.results.tool?.name,\n buildName: options?.buildName,\n buildUrl: options?.buildUrl,\n });\n\n try {\n await this.submitResults(run.id, ctrf);\n } catch (err) {\n await this.updateRun(run.id, {\n status: 'errored',\n completedAt: new Date().toISOString(),\n });\n throw err;\n }\n\n return this.getRun(run.id);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * TypeScript types matching the Smoo AI Testing API schemas.
3
+ */
4
+ interface TestRunSummary {
5
+ total?: number;
6
+ passed?: number;
7
+ failed?: number;
8
+ skipped?: number;
9
+ pending?: number;
10
+ other?: number;
11
+ }
12
+ interface TestRunDeployment {
13
+ id: string;
14
+ name: string;
15
+ status: string;
16
+ source: string | null;
17
+ externalId: string | null;
18
+ externalUrl: string | null;
19
+ ref: string | null;
20
+ metadata: Record<string, unknown> | null;
21
+ }
22
+ interface TestRun {
23
+ id: string;
24
+ organizationId: string;
25
+ environmentId: string | null;
26
+ deploymentId: string | null;
27
+ name: string;
28
+ tool: string | null;
29
+ status: string;
30
+ summary: TestRunSummary | null;
31
+ durationMs: number | null;
32
+ runnerName: string | null;
33
+ runnerUrl: string | null;
34
+ startedAt: string | null;
35
+ completedAt: string | null;
36
+ metadata: Record<string, unknown> | null;
37
+ createdAt: string;
38
+ updatedAt: string;
39
+ deployment?: TestRunDeployment | null;
40
+ results?: TestResult[];
41
+ }
42
+ interface CreateTestRunInput {
43
+ name: string;
44
+ environment?: string;
45
+ environmentId?: string;
46
+ deploymentId?: string;
47
+ tool?: string;
48
+ buildName?: string;
49
+ buildUrl?: string;
50
+ runnerName?: string;
51
+ runnerUrl?: string;
52
+ metadata?: Record<string, unknown>;
53
+ }
54
+ interface UpdateTestRunInput {
55
+ status?: string;
56
+ summary?: TestRunSummary;
57
+ completedAt?: string;
58
+ startedAt?: string;
59
+ tool?: string;
60
+ metadata?: Record<string, unknown>;
61
+ }
62
+ interface ListTestRunsFilters {
63
+ limit?: number;
64
+ offset?: number;
65
+ status?: string;
66
+ environmentId?: string;
67
+ tool?: string;
68
+ runnerName?: string;
69
+ startDate?: string;
70
+ endDate?: string;
71
+ }
72
+ interface TestResult {
73
+ id?: string;
74
+ name: string;
75
+ suite?: string;
76
+ status: string;
77
+ durationMs?: number;
78
+ message?: string;
79
+ trace?: string;
80
+ retryCount?: number;
81
+ flaky?: boolean;
82
+ browser?: string;
83
+ tags?: string[];
84
+ metadata?: Record<string, unknown>;
85
+ }
86
+ interface TestCaseStep {
87
+ id?: string;
88
+ stepNumber: number;
89
+ action: string;
90
+ expectedResult?: string;
91
+ data?: string;
92
+ }
93
+ interface TestCase {
94
+ id: string;
95
+ organizationId: string;
96
+ title: string;
97
+ description: string | null;
98
+ preconditions: string | null;
99
+ expectedResult: string | null;
100
+ priority: string | null;
101
+ automationStatus: string | null;
102
+ automationId: string | null;
103
+ tags: string[] | null;
104
+ estimatedDurationMs: number | null;
105
+ metadata: Record<string, unknown> | null;
106
+ createdAt: string;
107
+ updatedAt: string;
108
+ steps?: TestCaseStep[];
109
+ recentResults?: TestResult[];
110
+ }
111
+ interface CreateTestCaseInput {
112
+ title: string;
113
+ description?: string;
114
+ preconditions?: string;
115
+ expectedResult?: string;
116
+ priority?: string;
117
+ automationStatus?: string;
118
+ automationId?: string;
119
+ tags?: string[];
120
+ estimatedDurationMs?: number;
121
+ metadata?: Record<string, unknown>;
122
+ steps?: Omit<TestCaseStep, 'id'>[];
123
+ }
124
+ interface UpdateTestCaseInput {
125
+ title?: string;
126
+ description?: string;
127
+ preconditions?: string;
128
+ expectedResult?: string;
129
+ priority?: string;
130
+ automationStatus?: string;
131
+ automationId?: string;
132
+ tags?: string[];
133
+ estimatedDurationMs?: number;
134
+ metadata?: Record<string, unknown>;
135
+ steps?: TestCaseStep[];
136
+ }
137
+ interface ListTestCasesFilters {
138
+ limit?: number;
139
+ offset?: number;
140
+ tags?: string;
141
+ priority?: string;
142
+ automationStatus?: string;
143
+ }
144
+ interface TestEnvironment {
145
+ id: string;
146
+ organizationId: string;
147
+ name: string;
148
+ description: string | null;
149
+ baseUrl: string | null;
150
+ metadata: Record<string, unknown> | null;
151
+ createdAt: string;
152
+ updatedAt: string;
153
+ }
154
+ interface CreateTestEnvironmentInput {
155
+ name: string;
156
+ description?: string;
157
+ baseUrl?: string;
158
+ metadata?: Record<string, unknown>;
159
+ }
160
+ interface UpdateTestEnvironmentInput {
161
+ name?: string;
162
+ description?: string;
163
+ baseUrl?: string;
164
+ metadata?: Record<string, unknown>;
165
+ }
166
+ type DeploymentStatus = 'pending' | 'in_progress' | 'success' | 'failure' | 'cancelled';
167
+ interface Deployment {
168
+ id: string;
169
+ organizationId: string;
170
+ environmentId: string | null;
171
+ name: string;
172
+ status: DeploymentStatus;
173
+ source: string | null;
174
+ externalId: string | null;
175
+ externalUrl: string | null;
176
+ ref: string | null;
177
+ metadata: Record<string, unknown> | null;
178
+ startedAt: string | null;
179
+ completedAt: string | null;
180
+ createdAt: string;
181
+ updatedAt: string;
182
+ }
183
+ interface CreateDeploymentInput {
184
+ name: string;
185
+ environmentId?: string;
186
+ status?: DeploymentStatus;
187
+ source?: string;
188
+ externalId?: string;
189
+ externalUrl?: string;
190
+ ref?: string;
191
+ metadata?: Record<string, unknown>;
192
+ startedAt?: string;
193
+ }
194
+ interface UpdateDeploymentInput {
195
+ name?: string;
196
+ status?: DeploymentStatus;
197
+ source?: string;
198
+ externalId?: string;
199
+ externalUrl?: string;
200
+ ref?: string;
201
+ metadata?: Record<string, unknown>;
202
+ startedAt?: string;
203
+ completedAt?: string;
204
+ }
205
+ interface ListDeploymentsFilters {
206
+ limit?: number;
207
+ offset?: number;
208
+ status?: string;
209
+ environmentId?: string;
210
+ source?: string;
211
+ startDate?: string;
212
+ endDate?: string;
213
+ }
214
+ interface PaginatedResponse<T> {
215
+ data: T[];
216
+ pagination: {
217
+ limit: number;
218
+ offset: number;
219
+ total: number;
220
+ hasMore: boolean;
221
+ };
222
+ }
223
+ interface CtrfReport {
224
+ results: {
225
+ tool?: {
226
+ name?: string;
227
+ version?: string;
228
+ };
229
+ summary?: {
230
+ tests?: number;
231
+ passed?: number;
232
+ failed?: number;
233
+ skipped?: number;
234
+ pending?: number;
235
+ other?: number;
236
+ start?: number;
237
+ stop?: number;
238
+ };
239
+ tests?: CtrfTest[];
240
+ environment?: {
241
+ reportName?: string;
242
+ [key: string]: unknown;
243
+ };
244
+ };
245
+ }
246
+ interface CtrfTest {
247
+ name: string;
248
+ status: 'passed' | 'failed' | 'skipped' | 'pending' | 'other';
249
+ duration?: number;
250
+ suite?: string;
251
+ filePath?: string;
252
+ message?: string;
253
+ trace?: string;
254
+ retries?: number;
255
+ flaky?: boolean;
256
+ browser?: string;
257
+ tags?: string[];
258
+ extra?: Record<string, unknown>;
259
+ }
260
+ interface Credentials {
261
+ clientId: string;
262
+ clientSecret: string;
263
+ orgId: string;
264
+ apiUrl: string;
265
+ authUrl: string;
266
+ }
267
+ interface TokenResponse {
268
+ access_token: string;
269
+ token_type: string;
270
+ expires_in?: number;
271
+ }
272
+ interface SmooTestingClientOptions {
273
+ clientId: string;
274
+ clientSecret: string;
275
+ orgId: string;
276
+ apiUrl?: string;
277
+ authUrl?: string;
278
+ }
279
+
280
+ export type { CreateDeploymentInput, CreateTestCaseInput, CreateTestEnvironmentInput, CreateTestRunInput, Credentials, CtrfReport, CtrfTest, Deployment, DeploymentStatus, ListDeploymentsFilters, ListTestCasesFilters, ListTestRunsFilters, PaginatedResponse, SmooTestingClientOptions, TestCase, TestCaseStep, TestEnvironment, TestResult, TestRun, TestRunDeployment, TestRunSummary, TokenResponse, UpdateDeploymentInput, UpdateTestCaseInput, UpdateTestEnvironmentInput, UpdateTestRunInput };