alpic 0.0.0-dev.gd8b7aed → 0.0.0-dev.gd8deef5
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/README.md +18 -0
- package/bin/run.js +15 -1
- package/dist/__tests__/alpic-command.test.js +8 -4
- package/dist/__tests__/alpic-command.test.js.map +1 -1
- package/dist/__tests__/audit.e2e.test.js +17 -30
- package/dist/__tests__/audit.e2e.test.js.map +1 -1
- package/dist/__tests__/auth.e2e.test.js +9 -23
- package/dist/__tests__/auth.e2e.test.js.map +1 -1
- package/dist/__tests__/deploy-flags.e2e.test.js +6 -21
- package/dist/__tests__/deploy-flags.e2e.test.js.map +1 -1
- package/dist/__tests__/deploy.e2e.test.js +5 -21
- package/dist/__tests__/deploy.e2e.test.js.map +1 -1
- package/dist/__tests__/deployment-inspect.e2e.test.js +18 -31
- package/dist/__tests__/deployment-inspect.e2e.test.js.map +1 -1
- package/dist/__tests__/deployment-list.e2e.test.js +18 -31
- package/dist/__tests__/deployment-list.e2e.test.js.map +1 -1
- package/dist/__tests__/deployment-logs.e2e.test.js +15 -29
- package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -1
- package/dist/__tests__/environment-delete.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-delete.e2e.test.js +95 -0
- package/dist/__tests__/environment-delete.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-list.e2e.test.js +6 -22
- package/dist/__tests__/environment-list.e2e.test.js.map +1 -1
- package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js +19 -31
- package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js.map +1 -1
- package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js +19 -31
- package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js.map +1 -1
- package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js +18 -31
- package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js.map +1 -1
- package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js +18 -31
- package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js.map +1 -1
- package/dist/__tests__/git-flags.e2e.test.js +6 -22
- package/dist/__tests__/git-flags.e2e.test.js.map +1 -1
- package/dist/__tests__/git.e2e.test.js +7 -22
- package/dist/__tests__/git.e2e.test.js.map +1 -1
- package/dist/__tests__/insights-category.e2e.test.d.ts +1 -0
- package/dist/__tests__/insights-category.e2e.test.js +247 -0
- package/dist/__tests__/insights-category.e2e.test.js.map +1 -0
- package/dist/__tests__/insights.e2e.test.d.ts +1 -0
- package/dist/__tests__/insights.e2e.test.js +193 -0
- package/dist/__tests__/insights.e2e.test.js.map +1 -0
- package/dist/__tests__/logs.e2e.test.js +21 -35
- package/dist/__tests__/logs.e2e.test.js.map +1 -1
- package/dist/__tests__/mock-api.d.ts +26 -1
- package/dist/__tests__/mock-api.js +290 -41
- package/dist/__tests__/mock-api.js.map +1 -1
- package/dist/__tests__/playground/playground-configure.e2e.test.js +18 -26
- package/dist/__tests__/playground/playground-configure.e2e.test.js.map +1 -1
- package/dist/__tests__/playground/playground-enable-disable.e2e.test.js +18 -26
- package/dist/__tests__/playground/playground-enable-disable.e2e.test.js.map +1 -1
- package/dist/__tests__/playground/playground-example-prompt.e2e.test.js +18 -26
- package/dist/__tests__/playground/playground-example-prompt.e2e.test.js.map +1 -1
- package/dist/__tests__/playground/playground-headers.e2e.test.js +18 -26
- package/dist/__tests__/playground/playground-headers.e2e.test.js.map +1 -1
- package/dist/__tests__/playground/playground-status.e2e.test.js +18 -26
- package/dist/__tests__/playground/playground-status.e2e.test.js.map +1 -1
- package/dist/__tests__/project-list.e2e.test.js +5 -21
- package/dist/__tests__/project-list.e2e.test.js.map +1 -1
- package/dist/__tests__/publish.e2e.test.js +6 -24
- package/dist/__tests__/publish.e2e.test.js.map +1 -1
- package/dist/__tests__/submission.e2e.test.d.ts +1 -0
- package/dist/__tests__/submission.e2e.test.js +146 -0
- package/dist/__tests__/submission.e2e.test.js.map +1 -0
- package/dist/__tests__/team-inspect.e2e.test.js +26 -1
- package/dist/__tests__/team-inspect.e2e.test.js.map +1 -1
- package/dist/__tests__/team-list.e2e.test.js +5 -21
- package/dist/__tests__/team-list.e2e.test.js.map +1 -1
- package/dist/__tests__/tunnel.e2e.test.js +61 -23
- package/dist/__tests__/tunnel.e2e.test.js.map +1 -1
- package/dist/__tests__/utils.d.ts +17 -6
- package/dist/__tests__/utils.js +49 -20
- package/dist/__tests__/utils.js.map +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +2 -21
- package/dist/api.js.map +1 -1
- package/dist/commands/audit.js +3 -1
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/deploy.js +71 -54
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/deployment/list.js +3 -3
- package/dist/commands/deployment/list.js.map +1 -1
- package/dist/commands/environment/delete.d.ts +13 -0
- package/dist/commands/environment/delete.js +45 -0
- package/dist/commands/environment/delete.js.map +1 -0
- package/dist/commands/environment/inspect.js +3 -3
- package/dist/commands/environment/inspect.js.map +1 -1
- package/dist/commands/environment/list.js +3 -3
- package/dist/commands/environment/list.js.map +1 -1
- package/dist/commands/git/connect.js +2 -2
- package/dist/commands/git/connect.js.map +1 -1
- package/dist/commands/git/disconnect.js +2 -2
- package/dist/commands/git/disconnect.js.map +1 -1
- package/dist/commands/insights/category/create.d.ts +17 -0
- package/dist/commands/insights/category/create.js +63 -0
- package/dist/commands/insights/category/create.js.map +1 -0
- package/dist/commands/insights/category/delete.d.ts +13 -0
- package/dist/commands/insights/category/delete.js +40 -0
- package/dist/commands/insights/category/delete.js.map +1 -0
- package/dist/commands/insights/category/link.d.ts +14 -0
- package/dist/commands/insights/category/link.js +36 -0
- package/dist/commands/insights/category/link.js.map +1 -0
- package/dist/commands/insights/category/list.d.ts +13 -0
- package/dist/commands/insights/category/list.js +46 -0
- package/dist/commands/insights/category/list.js.map +1 -0
- package/dist/commands/insights/category/unlink.d.ts +14 -0
- package/dist/commands/insights/category/unlink.js +36 -0
- package/dist/commands/insights/category/unlink.js.map +1 -0
- package/dist/commands/insights/category/update.d.ts +16 -0
- package/dist/commands/insights/category/update.js +45 -0
- package/dist/commands/insights/category/update.js.map +1 -0
- package/dist/commands/insights/feedback/list.d.ts +19 -0
- package/dist/commands/insights/feedback/list.js +73 -0
- package/dist/commands/insights/feedback/list.js.map +1 -0
- package/dist/commands/insights/intent/list.d.ts +22 -0
- package/dist/commands/insights/intent/list.js +89 -0
- package/dist/commands/insights/intent/list.js.map +1 -0
- package/dist/commands/link.js +4 -3
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/login.js +7 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/logs.js +1 -9
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/project/inspect.js +3 -3
- package/dist/commands/project/inspect.js.map +1 -1
- package/dist/commands/project/list.js +3 -3
- package/dist/commands/project/list.js.map +1 -1
- package/dist/commands/submission/create.d.ts +15 -0
- package/dist/commands/submission/create.js +59 -0
- package/dist/commands/submission/create.js.map +1 -0
- package/dist/commands/submission/inspect.d.ts +10 -0
- package/dist/commands/submission/inspect.js +56 -0
- package/dist/commands/submission/inspect.js.map +1 -0
- package/dist/commands/submission/update.d.ts +12 -0
- package/dist/commands/submission/update.js +37 -0
- package/dist/commands/submission/update.js.map +1 -0
- package/dist/commands/team/inspect.js +25 -10
- package/dist/commands/team/inspect.js.map +1 -1
- package/dist/commands/team/list.js +3 -3
- package/dist/commands/team/list.js.map +1 -1
- package/dist/commands/tunnel.js +30 -66
- package/dist/commands/tunnel.js.map +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/lib/agent-mode.d.ts +8 -1
- package/dist/lib/agent-mode.js +25 -26
- package/dist/lib/agent-mode.js.map +1 -1
- package/dist/lib/alpic-command.d.ts +2 -1
- package/dist/lib/alpic-command.js +20 -8
- package/dist/lib/alpic-command.js.map +1 -1
- package/dist/lib/alpic-sdk.d.ts +2 -0
- package/dist/lib/alpic-sdk.js +8 -0
- package/dist/lib/alpic-sdk.js.map +1 -0
- package/dist/lib/audit.d.ts +1 -0
- package/dist/lib/audit.js +24 -15
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/base-workflow.d.ts +2 -1
- package/dist/lib/base-workflow.js +3 -3
- package/dist/lib/base-workflow.js.map +1 -1
- package/dist/lib/deployment.d.ts +0 -21
- package/dist/lib/deployment.js +20 -69
- package/dist/lib/deployment.js.map +1 -1
- package/dist/lib/environment-variable.js +14 -13
- package/dist/lib/environment-variable.js.map +1 -1
- package/dist/lib/insights.d.ts +19 -0
- package/dist/lib/insights.js +54 -0
- package/dist/lib/insights.js.map +1 -0
- package/dist/lib/link.d.ts +1 -2
- package/dist/lib/link.js +20 -75
- package/dist/lib/link.js.map +1 -1
- package/dist/lib/logs.js +4 -5
- package/dist/lib/logs.js.map +1 -1
- package/dist/lib/playground.js +25 -25
- package/dist/lib/playground.js.map +1 -1
- package/dist/lib/project-settings.d.ts +7 -0
- package/dist/lib/project-settings.js +140 -0
- package/dist/lib/project-settings.js.map +1 -0
- package/dist/lib/project-settings.test.d.ts +1 -0
- package/dist/lib/project-settings.test.js +56 -0
- package/dist/lib/project-settings.test.js.map +1 -0
- package/dist/lib/publish.js +3 -3
- package/dist/lib/publish.js.map +1 -1
- package/dist/lib/resolve.d.ts +7 -6
- package/dist/lib/resolve.js +27 -23
- package/dist/lib/resolve.js.map +1 -1
- package/dist/lib/submission.d.ts +13 -0
- package/dist/lib/submission.js +52 -0
- package/dist/lib/submission.js.map +1 -0
- package/dist/lib/telemetry.js +24 -17
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/utils.d.ts +9 -1
- package/dist/lib/utils.js +28 -2
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/utils.test.js +43 -5
- package/dist/lib/utils.test.js.map +1 -1
- package/dist/lib/whoami.js +17 -0
- package/dist/lib/whoami.js.map +1 -0
- package/dist/sentry.js +3 -6
- package/dist/sentry.js.map +1 -1
- package/package.json +28 -32
- package/dist/lib/archive.d.ts +0 -7
- package/dist/lib/archive.js +0 -57
- package/dist/lib/archive.js.map +0 -1
- package/dist/lib/auth/auth.d.ts +0 -5
- package/dist/lib/auth/auth.js +0 -50
- package/dist/lib/auth/auth.js.map +0 -1
- package/dist/lib/auth/oauth/client.d.ts +0 -28
- package/dist/lib/auth/oauth/client.js +0 -116
- package/dist/lib/auth/oauth/client.js.map +0 -1
- package/dist/lib/auth/oauth/constants.d.ts +0 -2
- package/dist/lib/auth/oauth/constants.js +0 -3
- package/dist/lib/auth/oauth/constants.js.map +0 -1
- package/dist/lib/auth/oauth/server/assets/alpic-mountain.png +0 -0
- package/dist/lib/auth/oauth/server/assets/authorize.html +0 -234
- package/dist/lib/auth/oauth/server/assets/callback.html +0 -88
- package/dist/lib/auth/oauth/server/index.d.ts +0 -9
- package/dist/lib/auth/oauth/server/index.js +0 -128
- package/dist/lib/auth/oauth/server/index.js.map +0 -1
- package/dist/lib/auth/whoami.js +0 -47
- package/dist/lib/auth/whoami.js.map +0 -1
- package/dist/lib/config.d.ts +0 -12
- package/dist/lib/config.js +0 -32
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/global-store.d.ts +0 -28
- package/dist/lib/global-store.js +0 -76
- package/dist/lib/global-store.js.map +0 -1
- package/dist/lib/upload.d.ts +0 -1
- package/dist/lib/upload.js +0 -13
- package/dist/lib/upload.js.map +0 -1
- package/dist/lib/vendor/pipenet.d.ts +0 -1
- package/dist/lib/vendor/pipenet.js +0 -16877
- package/dist/lib/vendor/pipenet.js.LEGAL.txt +0 -17
- package/dist/lib/vendor/pipenet.js.map +0 -7
- package/dist/types.d.ts +0 -8
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- /package/dist/lib/{auth/whoami.d.ts → whoami.d.ts} +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { cliSession, expectSuccessfulApiCall, registerCliE2ELifecycle } from "./utils.js";
|
|
5
|
+
const ENV_ID = "env-submission-test";
|
|
6
|
+
const PROJECT_ID = "prj-submission-test";
|
|
7
|
+
const TEAM_ID = "mock-team-id";
|
|
8
|
+
const SUBMISSION_ID = "sub-existing";
|
|
9
|
+
const PREFILLED_FORM_DATA = { appName: "Chess", developerName: "Alpic", tools: [] };
|
|
10
|
+
describe("alpic submission (E2E)", () => {
|
|
11
|
+
const context = registerCliE2ELifecycle({
|
|
12
|
+
projects: [
|
|
13
|
+
{
|
|
14
|
+
projectId: PROJECT_ID,
|
|
15
|
+
teamId: TEAM_ID,
|
|
16
|
+
projectName: "submission-project",
|
|
17
|
+
environmentId: ENV_ID,
|
|
18
|
+
environmentName: "production",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
let mockServer;
|
|
23
|
+
let serverUrl;
|
|
24
|
+
let cwd;
|
|
25
|
+
let binPath;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
({ mockServer, serverUrl, cwd, binPath } = context);
|
|
28
|
+
mockServer.setSubmissionPrefill("chatgpt", PREFILLED_FORM_DATA);
|
|
29
|
+
mockServer.addSubmission({
|
|
30
|
+
id: SUBMISSION_ID,
|
|
31
|
+
environmentId: ENV_ID,
|
|
32
|
+
platform: "chatgpt",
|
|
33
|
+
formData: PREFILLED_FORM_DATA,
|
|
34
|
+
prefillSnapshot: PREFILLED_FORM_DATA,
|
|
35
|
+
auditId: "audit-1",
|
|
36
|
+
urlVerification: null,
|
|
37
|
+
createdAt: new Date("2026-08-10T00:00:00.000Z"),
|
|
38
|
+
updatedAt: new Date("2026-08-10T00:00:00.000Z"),
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
const env = () => ({ ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" });
|
|
42
|
+
it("creates a submission package for an environment", async () => {
|
|
43
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "create", "--environment-id", ENV_ID, "--platform", "chatgpt"], { cwd, env: env() });
|
|
44
|
+
expect(exitCode).toBe(0);
|
|
45
|
+
expect(output).toContain("for ChatGPT");
|
|
46
|
+
const call = mockServer.getLastCall("POST", "/v1/submissions");
|
|
47
|
+
expectSuccessfulApiCall(call);
|
|
48
|
+
expect(call?.input).toMatchObject({ environmentId: ENV_ID, platform: "chatgpt" });
|
|
49
|
+
});
|
|
50
|
+
it("prints the created package as JSON", async () => {
|
|
51
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "create", "--environment-id", ENV_ID, "--platform", "chatgpt", "--json"], { cwd, env: env() });
|
|
52
|
+
expect(exitCode).toBe(0);
|
|
53
|
+
expect(output).toContain('"appName":"Chess"');
|
|
54
|
+
});
|
|
55
|
+
it("errors when no platform is given in non-interactive mode", async () => {
|
|
56
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "create", "--environment-id", ENV_ID, "--non-interactive"], { cwd, env: env() });
|
|
57
|
+
expect(exitCode).not.toBe(0);
|
|
58
|
+
expect(output).toContain("--platform is required in non-interactive mode.");
|
|
59
|
+
expect(mockServer.getCalls("POST", "/v1/submissions")).toHaveLength(0);
|
|
60
|
+
});
|
|
61
|
+
it("keeps status output off stdout in JSON mode, so the package can be piped", async () => {
|
|
62
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "inspect", "--submission-id", SUBMISSION_ID, "--json"], { cwd, env: env() });
|
|
63
|
+
expect(exitCode).toBe(0);
|
|
64
|
+
expect(JSON.parse(output.trim())).toMatchObject({ id: SUBMISSION_ID, platform: "chatgpt" });
|
|
65
|
+
});
|
|
66
|
+
it("keeps nested project resolution off stdout in JSON mode", async () => {
|
|
67
|
+
const { exitCode, output } = await cliSession(process.execPath, [
|
|
68
|
+
binPath,
|
|
69
|
+
"submission",
|
|
70
|
+
"create",
|
|
71
|
+
"--environment-name",
|
|
72
|
+
"production",
|
|
73
|
+
"--project-name",
|
|
74
|
+
"submission-project",
|
|
75
|
+
"--platform",
|
|
76
|
+
"chatgpt",
|
|
77
|
+
"--json",
|
|
78
|
+
], { cwd, env: env() });
|
|
79
|
+
expect(exitCode).toBe(0);
|
|
80
|
+
expect(JSON.parse(output.trim())).toMatchObject({ platform: "chatgpt" });
|
|
81
|
+
});
|
|
82
|
+
it("keeps environment resolution off stdout in JSON mode", async () => {
|
|
83
|
+
const { exitCode, output } = await cliSession(process.execPath, [
|
|
84
|
+
binPath,
|
|
85
|
+
"submission",
|
|
86
|
+
"create",
|
|
87
|
+
"--environment-name",
|
|
88
|
+
"production",
|
|
89
|
+
"--project-id",
|
|
90
|
+
PROJECT_ID,
|
|
91
|
+
"--platform",
|
|
92
|
+
"chatgpt",
|
|
93
|
+
"--json",
|
|
94
|
+
], { cwd, env: env() });
|
|
95
|
+
expect(exitCode).toBe(0);
|
|
96
|
+
expect(JSON.parse(output.trim())).toMatchObject({ platform: "chatgpt" });
|
|
97
|
+
});
|
|
98
|
+
it("rejects a form field the platform does not have, rather than dropping it", async () => {
|
|
99
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "update", "--submission-id", SUBMISSION_ID, "--form-data", '{"appNmae":"Chess"}'], { cwd, env: env() });
|
|
100
|
+
expect(exitCode).not.toBe(0);
|
|
101
|
+
expect(output).not.toContain("Updated");
|
|
102
|
+
expect(output).toContain("Input validation failed");
|
|
103
|
+
expect(mockServer.getLastCall("PUT", `/v1/submissions/${SUBMISSION_ID}`)?.responseStatus).toBeGreaterThanOrEqual(400);
|
|
104
|
+
});
|
|
105
|
+
it("inspects a submission package field by field", async () => {
|
|
106
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "inspect", "--submission-id", SUBMISSION_ID], { cwd, env: env() });
|
|
107
|
+
expect(exitCode).toBe(0);
|
|
108
|
+
expect(output).toContain("ChatGPT");
|
|
109
|
+
expect(output).toContain("appName");
|
|
110
|
+
expect(output).toContain("Chess");
|
|
111
|
+
expectSuccessfulApiCall(mockServer.getLastCall("GET", `/v1/submissions/${SUBMISSION_ID}`));
|
|
112
|
+
});
|
|
113
|
+
it("exits with an error when the submission does not exist", async () => {
|
|
114
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "inspect", "--submission-id", "sub-unknown"], { cwd, env: env() });
|
|
115
|
+
expect(exitCode).not.toBe(0);
|
|
116
|
+
expect(output).toContain("Submission not found");
|
|
117
|
+
});
|
|
118
|
+
it("sends the fields from inline JSON, reading the platform off the package", async () => {
|
|
119
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "update", "--submission-id", SUBMISSION_ID, "--form-data", '{"appName":"Chess Master"}'], { cwd, env: env() });
|
|
120
|
+
expect(exitCode).toBe(0);
|
|
121
|
+
expect(output).toContain(`Updated ${SUBMISSION_ID}.`);
|
|
122
|
+
const call = mockServer.getLastCall("PUT", `/v1/submissions/${SUBMISSION_ID}`);
|
|
123
|
+
expectSuccessfulApiCall(call);
|
|
124
|
+
expect(call?.input).toMatchObject({ platform: "chatgpt", formData: { appName: "Chess Master" } });
|
|
125
|
+
});
|
|
126
|
+
it("sends the fields from a JSON file", async () => {
|
|
127
|
+
const formDataPath = join(cwd, "submission.json");
|
|
128
|
+
await writeFile(formDataPath, JSON.stringify({ appName: "Chess Club" }));
|
|
129
|
+
const { exitCode } = await cliSession(process.execPath, [binPath, "submission", "update", "--submission-id", SUBMISSION_ID, "--form-data-file", formDataPath], { cwd, env: env() });
|
|
130
|
+
expect(exitCode).toBe(0);
|
|
131
|
+
const call = mockServer.getLastCall("PUT", `/v1/submissions/${SUBMISSION_ID}`);
|
|
132
|
+
expect(call?.input).toMatchObject({ formData: { appName: "Chess Club" } });
|
|
133
|
+
});
|
|
134
|
+
it("rejects form data that is not a JSON object without calling the API", async () => {
|
|
135
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "update", "--submission-id", SUBMISSION_ID, "--form-data", "[]"], { cwd, env: env() });
|
|
136
|
+
expect(exitCode).not.toBe(0);
|
|
137
|
+
expect(output).toContain("Form data must be a JSON object of submission fields.");
|
|
138
|
+
expect(mockServer.getCalls("PUT", `/v1/submissions/${SUBMISSION_ID}`)).toHaveLength(0);
|
|
139
|
+
});
|
|
140
|
+
it("rejects an update with no form data", async () => {
|
|
141
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "submission", "update", "--submission-id", SUBMISSION_ID], { cwd, env: env() });
|
|
142
|
+
expect(exitCode).not.toBe(0);
|
|
143
|
+
expect(output).toContain("No form data provided. Use --form-data or --form-data-file.");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=submission.e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/submission.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { rmSync } from "node:fs";
|
|
2
2
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
3
3
|
import { MockApiServer } from "./mock-api.js";
|
|
4
|
-
import { buildMockProject, cliSession, expectSuccessfulApiCall, setupTestDirectory } from "./utils.js";
|
|
4
|
+
import { buildMockProject, buildMockTeamUsage, cliSession, expectSuccessfulApiCall, setupTestDirectory, } from "./utils.js";
|
|
5
5
|
describe("alpic team inspect (E2E)", () => {
|
|
6
6
|
let mockServer;
|
|
7
7
|
let serverUrl;
|
|
@@ -29,6 +29,7 @@ describe("alpic team inspect (E2E)", () => {
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
it("displays team details and projects with --team-id", async () => {
|
|
32
|
+
mockServer.setTeamUsage(buildMockTeamUsage(teamId));
|
|
32
33
|
mockServer.addProject(buildMockProject({
|
|
33
34
|
projectId: "prj-1",
|
|
34
35
|
teamId,
|
|
@@ -49,6 +50,30 @@ describe("alpic team inspect (E2E)", () => {
|
|
|
49
50
|
const listCall = mockServer.getLastCall("GET", "/v1/teams");
|
|
50
51
|
expectSuccessfulApiCall(listCall);
|
|
51
52
|
});
|
|
53
|
+
it("reports the current window usage against the plan allowance", async () => {
|
|
54
|
+
mockServer.setTeamUsage(buildMockTeamUsage(teamId, { plan: "pro", requestCount: 4_231, includedRequests: 200_000 }));
|
|
55
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "team", "inspect", "--team-id", teamId], {
|
|
56
|
+
cwd,
|
|
57
|
+
env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
|
|
58
|
+
}, async (cli) => {
|
|
59
|
+
await cli.expect("Team found");
|
|
60
|
+
});
|
|
61
|
+
expect(exitCode).toBe(0);
|
|
62
|
+
expect(output).toContain("4,231 / 200,000 requests (resets in 12 days)");
|
|
63
|
+
const usageCall = mockServer.getLastCall("GET", `/v1/teams/${teamId}/usage`);
|
|
64
|
+
expectSuccessfulApiCall(usageCall);
|
|
65
|
+
});
|
|
66
|
+
it("still shows the team when the server has no usage route", async () => {
|
|
67
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "team", "inspect", "--team-id", teamId], {
|
|
68
|
+
cwd,
|
|
69
|
+
env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
|
|
70
|
+
}, async (cli) => {
|
|
71
|
+
await cli.expect("Team found");
|
|
72
|
+
});
|
|
73
|
+
expect(exitCode).toBe(0);
|
|
74
|
+
expect(output).toContain(teamName);
|
|
75
|
+
expect(output).not.toContain("Usage");
|
|
76
|
+
});
|
|
52
77
|
it("prompts to select a team when --team-id is not provided", async () => {
|
|
53
78
|
mockServer.setTeams([
|
|
54
79
|
{ id: teamId, name: teamName },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-inspect.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/team-inspect.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE1F,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"team-inspect.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/team-inspect.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { MockApiServer } from "./mock-api.js";
|
|
4
|
-
import { cliSession, expectSuccessfulApiCall, setupTestDirectory } from "./utils.js";
|
|
1
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { cliSession, expectSuccessfulApiCall, registerCliE2ELifecycle } from "./utils.js";
|
|
5
3
|
describe("alpic team list (E2E)", () => {
|
|
4
|
+
const context = registerCliE2ELifecycle();
|
|
6
5
|
let mockServer;
|
|
7
6
|
let serverUrl;
|
|
8
7
|
let cwd;
|
|
9
8
|
let binPath;
|
|
10
|
-
|
|
11
|
-
mockServer =
|
|
12
|
-
serverUrl = await mockServer.start();
|
|
13
|
-
});
|
|
14
|
-
afterAll(async () => {
|
|
15
|
-
await mockServer.stop();
|
|
16
|
-
});
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
mockServer.reset();
|
|
19
|
-
const setup = await setupTestDirectory();
|
|
20
|
-
cwd = setup.cwd;
|
|
21
|
-
binPath = setup.binPath;
|
|
22
|
-
});
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
if (cwd) {
|
|
25
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
26
|
-
}
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
({ mockServer, serverUrl, cwd, binPath } = context);
|
|
27
11
|
});
|
|
28
12
|
it("lists teams for the authenticated user", async () => {
|
|
29
13
|
mockServer.setTeams([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-list.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/team-list.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"team-list.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/team-list.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1F,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAC;IAE1C,IAAI,UAAyB,CAAC;IAC9B,IAAI,SAAiB,CAAC;IACtB,IAAI,GAAW,CAAC;IAChB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,GAAG,EAAE;QACd,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,UAAU,CAAC,QAAQ,CAAC;YAClB,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE;YACpC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE;SACpC,CAAC,CAAC;QAEH,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EACzB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACpC,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACjD,MAAM,CAAC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;QAEjD,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC5D,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAExB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EACzB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACrC,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { cliSession, createOAuthEnv,
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { createServer } from "pipenet/server";
|
|
3
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { cliSession, createOAuthEnv, registerCliE2ELifecycle } from "./utils.js";
|
|
5
|
+
function freePort() {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
const probe = http.createServer();
|
|
8
|
+
probe.on("error", reject);
|
|
9
|
+
probe.listen(0, "127.0.0.1", () => {
|
|
10
|
+
const { port } = probe.address();
|
|
11
|
+
probe.close(() => resolve(port));
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
}
|
|
5
15
|
describe("alpic tunnel (E2E)", () => {
|
|
16
|
+
const context = registerCliE2ELifecycle();
|
|
6
17
|
let mockServer;
|
|
7
18
|
let serverUrl;
|
|
8
19
|
let cwd;
|
|
9
20
|
let binPath;
|
|
10
|
-
|
|
11
|
-
mockServer =
|
|
12
|
-
serverUrl = await mockServer.start();
|
|
13
|
-
});
|
|
14
|
-
afterAll(async () => {
|
|
15
|
-
await mockServer.stop();
|
|
16
|
-
});
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
mockServer.reset();
|
|
19
|
-
const setup = await setupTestDirectory();
|
|
20
|
-
cwd = setup.cwd;
|
|
21
|
-
binPath = setup.binPath;
|
|
22
|
-
});
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
if (cwd) {
|
|
25
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
26
|
-
}
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
({ mockServer, serverUrl, cwd, binPath } = context);
|
|
27
23
|
});
|
|
28
24
|
it("triggers login when not authenticated", async () => {
|
|
29
25
|
const { output } = await cliSession(process.execPath, [binPath, "tunnel", "--port", "3000"], {
|
|
@@ -57,8 +53,7 @@ describe("alpic tunnel (E2E)", () => {
|
|
|
57
53
|
timeoutMs: 12000,
|
|
58
54
|
}, async (cli) => {
|
|
59
55
|
await cli.expect("Opening tunnel");
|
|
60
|
-
// "Opening tunnel"
|
|
61
|
-
// Wait for the request to reach the mock server before killing the process.
|
|
56
|
+
// "Opening tunnel" prints before the API request is sent, so wait for the request to reach the mock server before killing the process.
|
|
62
57
|
const deadline = Date.now() + 500;
|
|
63
58
|
while (Date.now() < deadline) {
|
|
64
59
|
if (mockServer.getCalls().some((call) => call.path.includes("tunnels"))) {
|
|
@@ -71,5 +66,48 @@ describe("alpic tunnel (E2E)", () => {
|
|
|
71
66
|
const ticketCall = mockServer.getCalls().find((call) => call.path.includes("tunnels"));
|
|
72
67
|
expect(ticketCall).toBeDefined();
|
|
73
68
|
});
|
|
69
|
+
it("closes the previous tunnel when a new one is opened for the same account", async () => {
|
|
70
|
+
// The patched pipenet enforces at-most-one tunnel per subdomain: opening a second closes the first and severs its sockets, so the displaced CLI detects the takeover and exits on its own.
|
|
71
|
+
const subdomain = "cool-mongoose-123";
|
|
72
|
+
const tunnelPort = await freePort();
|
|
73
|
+
const tunnelServer = createServer({
|
|
74
|
+
domains: ["localhost"],
|
|
75
|
+
tunnelPort,
|
|
76
|
+
maxTcpSockets: 10,
|
|
77
|
+
keepAliveDelayMs: 1_000,
|
|
78
|
+
});
|
|
79
|
+
// Bind on all interfaces so the CLI's `localhost` tunnel sockets connect whether it resolves to IPv4 or IPv6.
|
|
80
|
+
await tunnelServer.tunnelServer?.listen(tunnelPort);
|
|
81
|
+
const httpPort = await new Promise((resolve) => {
|
|
82
|
+
tunnelServer.listen(0, () => resolve(tunnelServer.address().port));
|
|
83
|
+
});
|
|
84
|
+
mockServer.setTunnelTicket({ subdomain, ticket: "mock-ticket", tunnelHost: `localhost:${httpPort}` });
|
|
85
|
+
const env = createOAuthEnv(cwd, serverUrl);
|
|
86
|
+
let startSecondTunnel = () => { };
|
|
87
|
+
const secondTunnelStarted = new Promise((resolve) => {
|
|
88
|
+
startSecondTunnel = resolve;
|
|
89
|
+
});
|
|
90
|
+
const firstSession = cliSession(process.execPath, [binPath, "tunnel", "--port", "4011"], { cwd, env, timeoutMs: 30_000 }, async (cli) => {
|
|
91
|
+
await cli.expect("Forwarding");
|
|
92
|
+
startSecondTunnel();
|
|
93
|
+
await cli.expect("a new tunnel was opened for this account", { timeoutMs: 20_000 });
|
|
94
|
+
});
|
|
95
|
+
await secondTunnelStarted;
|
|
96
|
+
const secondSession = cliSession(process.execPath, [binPath, "tunnel", "--port", "4012"], { cwd, env, timeoutMs: 30_000 }, async (cli) => {
|
|
97
|
+
await cli.expect("Forwarding");
|
|
98
|
+
// Keep the new tunnel alive until the old one has exited, then shut it down.
|
|
99
|
+
await firstSession;
|
|
100
|
+
cli.stop();
|
|
101
|
+
});
|
|
102
|
+
try {
|
|
103
|
+
const first = await firstSession;
|
|
104
|
+
await secondSession;
|
|
105
|
+
expect(first.output).toContain("a new tunnel was opened for this account");
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
tunnelServer.tunnelServer?.close();
|
|
109
|
+
await new Promise((resolve) => tunnelServer.close(() => resolve()));
|
|
110
|
+
}
|
|
111
|
+
}, 40_000);
|
|
74
112
|
});
|
|
75
113
|
//# sourceMappingURL=tunnel.e2e.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnel.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/tunnel.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"tunnel.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/tunnel.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { RouterOutput } from "@alpic-ai/api";
|
|
2
|
-
import type
|
|
2
|
+
import { type ApiCall, MockApiServer } from "./mock-api.js";
|
|
3
3
|
type Expectable = string | RegExp;
|
|
4
4
|
type ProjectGetV1 = RouterOutput["projects"]["get"]["v1"];
|
|
5
5
|
type DeploymentGetV1 = RouterOutput["deployments"]["get"]["v1"];
|
|
6
|
+
type TeamUsageGetV1 = RouterOutput["teams"]["getUsage"]["v1"];
|
|
6
7
|
type ProductionEnvironment = NonNullable<ProjectGetV1["productionEnvironment"]>;
|
|
7
8
|
type ProductionEnvironmentDomains = ProductionEnvironment["domains"];
|
|
8
9
|
export type CliSessionOptions = {
|
|
@@ -45,6 +46,8 @@ export type BuildMockProjectParams = {
|
|
|
45
46
|
};
|
|
46
47
|
export declare function buildMockProject(params: BuildMockProjectParams): ProjectGetV1;
|
|
47
48
|
export declare function buildMockDeployment(overrides?: Partial<DeploymentGetV1>): DeploymentGetV1;
|
|
49
|
+
/** Anchored on the run so the rendered "resets in 12 days" stays snapshot-stable. */
|
|
50
|
+
export declare function buildMockTeamUsage(teamId: string, overrides?: Partial<TeamUsageGetV1>): TeamUsageGetV1;
|
|
48
51
|
export type SetupTestDirectoryOptions = {
|
|
49
52
|
/** If true, run git init and add origin/upstream remotes */
|
|
50
53
|
initGit?: boolean;
|
|
@@ -53,14 +56,22 @@ export declare function setupTestDirectory(options?: SetupTestDirectoryOptions):
|
|
|
53
56
|
cwd: string;
|
|
54
57
|
binPath: string;
|
|
55
58
|
}>;
|
|
59
|
+
export type CliE2EContext = {
|
|
60
|
+
mockServer: MockApiServer;
|
|
61
|
+
serverUrl: string;
|
|
62
|
+
cwd: string;
|
|
63
|
+
binPath: string;
|
|
64
|
+
};
|
|
65
|
+
export type RegisterCliE2ELifecycleOptions = {
|
|
66
|
+
projects?: BuildMockProjectParams[];
|
|
67
|
+
testDirectory?: SetupTestDirectoryOptions;
|
|
68
|
+
};
|
|
69
|
+
/** Registers the standard e2e lifecycle (one mock API server per suite, fresh test directory and mock state per test); context fields are (re)assigned by the hooks, so read them inside tests or a `beforeEach`, never at `describe` scope. */
|
|
70
|
+
export declare function registerCliE2ELifecycle(options?: RegisterCliE2ELifecycleOptions): CliE2EContext;
|
|
56
71
|
export declare function createConfigFile(cwd: string, projectId: string, teamId: string, projectName: string, environmentId: string, environmentName: string, teamName?: string): void;
|
|
57
72
|
export declare function runGit(args: string[], cwd: string): void;
|
|
58
73
|
export declare function expectSuccessfulApiCall(call: ApiCall | undefined, customAssertions?: (call: ApiCall) => void): asserts call is ApiCall;
|
|
59
|
-
/**
|
|
60
|
-
* Create OAuth credentials in a temp config dir and return env for CLI subprocess.
|
|
61
|
-
* Use this to run commands with OAuth auth (no ALPIC_API_KEY).
|
|
62
|
-
* Caller must pass serverUrl so userinfo can be pointed at the mock server.
|
|
63
|
-
*/
|
|
74
|
+
/** Creates OAuth credentials in a temp config dir and returns env for running the CLI with OAuth auth (no ALPIC_API_KEY); serverUrl points userinfo at the mock server. */
|
|
64
75
|
export declare function createOAuthEnv(cwd: string, serverUrl: string): Record<string, string>;
|
|
65
76
|
export declare function verifyConfigFile(cwd: string, expected: {
|
|
66
77
|
projectName: string;
|
package/dist/__tests__/utils.js
CHANGED
|
@@ -7,8 +7,10 @@ import { dirname, join } from "node:path";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { stripVTControlCharacters } from "node:util";
|
|
9
9
|
import pty from "node-pty";
|
|
10
|
-
import { expect } from "vitest";
|
|
10
|
+
import { afterAll, afterEach, beforeAll, beforeEach, expect } from "vitest";
|
|
11
|
+
import { MockApiServer } from "./mock-api.js";
|
|
11
12
|
const DEFAULT_CLI_SESSION_TIMEOUT_MS = 10_000;
|
|
13
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
12
14
|
const __testDirname = dirname(fileURLToPath(import.meta.url));
|
|
13
15
|
export async function cliSession(cmd, args, options, fn = async () => { }) {
|
|
14
16
|
const { cwd, env, cols = 100, rows = 30, timeoutMs = DEFAULT_CLI_SESSION_TIMEOUT_MS } = options;
|
|
@@ -21,11 +23,9 @@ export async function cliSession(cmd, args, options, fn = async () => { }) {
|
|
|
21
23
|
ALPIC_POLL_INTERVAL_MS: "100",
|
|
22
24
|
// Prevent browser windows from opening during tests.
|
|
23
25
|
ALPIC_NO_OPEN: "1",
|
|
24
|
-
// Disable PostHog telemetry: every CLI invocation in CI/local tests would
|
|
25
|
-
// otherwise fire a real production event and drown out customer signal.
|
|
26
|
+
// Disable PostHog telemetry: every CLI invocation in CI/local tests would otherwise fire a real production event and drown out customer signal.
|
|
26
27
|
ALPIC_TELEMETRY_DISABLED: "1",
|
|
27
|
-
// Resolve @alpic-ai/api to TypeScript source via the "development" export condition,
|
|
28
|
-
// so e2e tests run without building the api package first.
|
|
28
|
+
// Resolve @alpic-ai/api to TypeScript source via the "development" export condition, so e2e tests run without building the api package first.
|
|
29
29
|
NODE_OPTIONS: [process.env.NODE_OPTIONS, "--conditions=development"].filter(Boolean).join(" "),
|
|
30
30
|
...Object.fromEntries(Object.entries(env ?? {}).filter(([, value]) => value !== undefined)),
|
|
31
31
|
};
|
|
@@ -59,10 +59,7 @@ export async function cliSession(cmd, args, options, fn = async () => { }) {
|
|
|
59
59
|
const controller = {
|
|
60
60
|
expect: (pattern, opts) => waitFor(() => matches(buf, pattern), opts?.timeoutMs ?? timeoutMs, () => buf, pattern),
|
|
61
61
|
send: async (line) => {
|
|
62
|
-
// Wait until PTY output has gone quiet
|
|
63
|
-
// This ensures the CLI has yielded its event loop and entered the I/O
|
|
64
|
-
// polling phase where it can receive keypresses — without a fixed
|
|
65
|
-
// overly-conservative delay.
|
|
62
|
+
// Wait until PTY output has gone quiet so the CLI has yielded its event loop and can receive keypresses, without a fixed overly-conservative delay.
|
|
66
63
|
const quietMs = 10;
|
|
67
64
|
while (Date.now() - lastDataAt < quietMs) {
|
|
68
65
|
await sleep(5);
|
|
@@ -78,9 +75,7 @@ export async function cliSession(cmd, args, options, fn = async () => { }) {
|
|
|
78
75
|
try {
|
|
79
76
|
term.kill();
|
|
80
77
|
}
|
|
81
|
-
catch {
|
|
82
|
-
// ignore
|
|
83
|
-
}
|
|
78
|
+
catch { }
|
|
84
79
|
},
|
|
85
80
|
};
|
|
86
81
|
try {
|
|
@@ -141,7 +136,7 @@ export function buildMockProject(params) {
|
|
|
141
136
|
name: environmentName,
|
|
142
137
|
sourceBranch,
|
|
143
138
|
mcpServerUrl,
|
|
144
|
-
createdAt: new Date(
|
|
139
|
+
createdAt: new Date(Date.now() - 2 * 365 * 24 * 60 * 60 * 1000),
|
|
145
140
|
projectId,
|
|
146
141
|
latestDeployment,
|
|
147
142
|
},
|
|
@@ -161,7 +156,7 @@ export function buildMockProject(params) {
|
|
|
161
156
|
buildOutputDir: null,
|
|
162
157
|
installCommand: null,
|
|
163
158
|
startCommand: null,
|
|
164
|
-
createdAt: new Date(
|
|
159
|
+
createdAt: new Date(Date.now() - 2 * 365 * 24 * 60 * 60 * 1000),
|
|
165
160
|
};
|
|
166
161
|
}
|
|
167
162
|
export function buildMockDeployment(overrides) {
|
|
@@ -181,6 +176,18 @@ export function buildMockDeployment(overrides) {
|
|
|
181
176
|
};
|
|
182
177
|
return { ...base, ...overrides };
|
|
183
178
|
}
|
|
179
|
+
/** Anchored on the run so the rendered "resets in 12 days" stays snapshot-stable. */
|
|
180
|
+
export function buildMockTeamUsage(teamId, overrides) {
|
|
181
|
+
const base = {
|
|
182
|
+
teamId,
|
|
183
|
+
plan: null,
|
|
184
|
+
periodStart: new Date(Date.now() - 18 * DAY_MS),
|
|
185
|
+
periodEnd: new Date(Date.now() + 12 * DAY_MS),
|
|
186
|
+
requestCount: 0,
|
|
187
|
+
includedRequests: 10_000,
|
|
188
|
+
};
|
|
189
|
+
return { ...base, ...overrides };
|
|
190
|
+
}
|
|
184
191
|
export async function setupTestDirectory(options = {}) {
|
|
185
192
|
const { initGit = false } = options;
|
|
186
193
|
const uniqueId = randomUUID();
|
|
@@ -195,6 +202,32 @@ export async function setupTestDirectory(options = {}) {
|
|
|
195
202
|
const binPath = join(process.cwd(), "bin", "dev.js");
|
|
196
203
|
return { cwd, binPath };
|
|
197
204
|
}
|
|
205
|
+
/** Registers the standard e2e lifecycle (one mock API server per suite, fresh test directory and mock state per test); context fields are (re)assigned by the hooks, so read them inside tests or a `beforeEach`, never at `describe` scope. */
|
|
206
|
+
export function registerCliE2ELifecycle(options = {}) {
|
|
207
|
+
const context = {};
|
|
208
|
+
beforeAll(async () => {
|
|
209
|
+
context.mockServer = new MockApiServer();
|
|
210
|
+
context.serverUrl = await context.mockServer.start();
|
|
211
|
+
});
|
|
212
|
+
afterAll(async () => {
|
|
213
|
+
await context.mockServer.stop();
|
|
214
|
+
});
|
|
215
|
+
beforeEach(async () => {
|
|
216
|
+
context.mockServer.reset();
|
|
217
|
+
const setup = await setupTestDirectory(options.testDirectory);
|
|
218
|
+
context.cwd = setup.cwd;
|
|
219
|
+
context.binPath = setup.binPath;
|
|
220
|
+
for (const project of options.projects ?? []) {
|
|
221
|
+
context.mockServer.addProject(buildMockProject(project));
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
afterEach(async () => {
|
|
225
|
+
if (context.cwd) {
|
|
226
|
+
await rm(context.cwd, { recursive: true, force: true });
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
return context;
|
|
230
|
+
}
|
|
198
231
|
export function createConfigFile(cwd, projectId, teamId, projectName, environmentId, environmentName, teamName) {
|
|
199
232
|
const configDir = join(cwd, ".alpic");
|
|
200
233
|
mkdirSync(configDir, { recursive: true });
|
|
@@ -224,16 +257,12 @@ export function expectSuccessfulApiCall(call, customAssertions) {
|
|
|
224
257
|
customAssertions(call);
|
|
225
258
|
}
|
|
226
259
|
}
|
|
227
|
-
/**
|
|
228
|
-
* Create OAuth credentials in a temp config dir and return env for CLI subprocess.
|
|
229
|
-
* Use this to run commands with OAuth auth (no ALPIC_API_KEY).
|
|
230
|
-
* Caller must pass serverUrl so userinfo can be pointed at the mock server.
|
|
231
|
-
*/
|
|
260
|
+
/** Creates OAuth credentials in a temp config dir and returns env for running the CLI with OAuth auth (no ALPIC_API_KEY); serverUrl points userinfo at the mock server. */
|
|
232
261
|
export function createOAuthEnv(cwd, serverUrl) {
|
|
233
262
|
const alpicConfigDir = join(cwd, ".config", "alpic");
|
|
234
263
|
mkdirSync(alpicConfigDir, { recursive: true });
|
|
235
264
|
const credentialsPath = join(alpicConfigDir, "credentials.json");
|
|
236
|
-
const expiresAt = Math.floor(Date.now() / 1000) + 3600;
|
|
265
|
+
const expiresAt = Math.floor(Date.now() / 1000) + 3600;
|
|
237
266
|
writeFileSync(credentialsPath, JSON.stringify({
|
|
238
267
|
access_token: "test-oauth-token",
|
|
239
268
|
refresh_token: "test-refresh-token",
|