@zuplo/cli 6.69.2 → 6.69.4
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/__tests__/integration/confirm-linked-config.integration.test.d.ts +2 -0
- package/dist/__tests__/integration/confirm-linked-config.integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/confirm-linked-config.integration.test.js +202 -0
- package/dist/__tests__/integration/confirm-linked-config.integration.test.js.map +1 -0
- package/dist/__tests__/integration/info.integration.test.js +49 -2
- package/dist/__tests__/integration/info.integration.test.js.map +1 -1
- package/dist/__tests__/integration/linked-config-cascade.integration.test.js +36 -0
- package/dist/__tests__/integration/linked-config-cascade.integration.test.js.map +1 -1
- package/dist/cmds/delete.d.ts.map +1 -1
- package/dist/cmds/delete.js +2 -0
- package/dist/cmds/delete.js.map +1 -1
- package/dist/cmds/deploy.d.ts.map +1 -1
- package/dist/cmds/deploy.js +2 -0
- package/dist/cmds/deploy.js.map +1 -1
- package/dist/cmds/link.d.ts.map +1 -1
- package/dist/cmds/link.js +2 -0
- package/dist/cmds/link.js.map +1 -1
- package/dist/cmds/list.d.ts.map +1 -1
- package/dist/cmds/list.js +2 -0
- package/dist/cmds/list.js.map +1 -1
- package/dist/cmds/mtls-certificates/create.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/create.js +2 -0
- package/dist/cmds/mtls-certificates/create.js.map +1 -1
- package/dist/cmds/mtls-certificates/delete.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/delete.js +2 -0
- package/dist/cmds/mtls-certificates/delete.js.map +1 -1
- package/dist/cmds/mtls-certificates/describe.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/describe.js +2 -0
- package/dist/cmds/mtls-certificates/describe.js.map +1 -1
- package/dist/cmds/mtls-certificates/disable.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/disable.js +2 -0
- package/dist/cmds/mtls-certificates/disable.js.map +1 -1
- package/dist/cmds/mtls-certificates/list.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/list.js +2 -0
- package/dist/cmds/mtls-certificates/list.js.map +1 -1
- package/dist/cmds/mtls-certificates/update.d.ts.map +1 -1
- package/dist/cmds/mtls-certificates/update.js +2 -0
- package/dist/cmds/mtls-certificates/update.js.map +1 -1
- package/dist/cmds/variable/create.d.ts.map +1 -1
- package/dist/cmds/variable/create.js +2 -0
- package/dist/cmds/variable/create.js.map +1 -1
- package/dist/cmds/variable/update.d.ts.map +1 -1
- package/dist/cmds/variable/update.js +2 -0
- package/dist/cmds/variable/update.js.map +1 -1
- package/dist/common/middleware/confirm-linked-config.d.ts +4 -0
- package/dist/common/middleware/confirm-linked-config.d.ts.map +1 -0
- package/dist/common/middleware/confirm-linked-config.js +30 -0
- package/dist/common/middleware/confirm-linked-config.js.map +1 -0
- package/dist/common/utils/format-environment-type.d.ts +2 -0
- package/dist/common/utils/format-environment-type.d.ts.map +1 -0
- package/dist/common/utils/format-environment-type.js +12 -0
- package/dist/common/utils/format-environment-type.js.map +1 -0
- package/dist/common/utils/format-environment-type.test.d.ts +2 -0
- package/dist/common/utils/format-environment-type.test.d.ts.map +1 -0
- package/dist/common/utils/format-environment-type.test.js +32 -0
- package/dist/common/utils/format-environment-type.test.js.map +1 -0
- package/dist/common/utils/pretty-print-environment-prompt.d.ts.map +1 -1
- package/dist/common/utils/pretty-print-environment-prompt.js +7 -10
- package/dist/common/utils/pretty-print-environment-prompt.js.map +1 -1
- package/dist/project/info/handler.d.ts.map +1 -1
- package/dist/project/info/handler.js +5 -1
- package/dist/project/info/handler.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +0 -1
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm-linked-config.integration.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/confirm-linked-config.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { confirmLinkedConfig } from "../../common/middleware/confirm-linked-config.js";
|
|
2
|
+
import { confirmLinkedValue, readLinkedConfig, USE_LINKED_DETAILS, } from "../../common/read-linked-config.js";
|
|
3
|
+
import { isInteractiveTerminal } from "../../common/terminal.js";
|
|
4
|
+
import { cleanupTest, setupTestEnvironment, TEST_ACCOUNT_NAME, TEST_AUTH_TOKEN, TEST_PROJECT_NAME, } from "./test-utils.js";
|
|
5
|
+
jest.mock("../../common/read-linked-config.js", () => ({
|
|
6
|
+
__esModule: true,
|
|
7
|
+
confirmLinkedValue: jest.fn().mockResolvedValue(true),
|
|
8
|
+
readLinkedConfig: jest.fn().mockResolvedValue({}),
|
|
9
|
+
USE_LINKED_DETAILS: "useLinkedDetails",
|
|
10
|
+
ignoreLinkedDetails: jest
|
|
11
|
+
.fn()
|
|
12
|
+
.mockImplementation((argv) => {
|
|
13
|
+
argv["useLinkedDetails"] = false;
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
16
|
+
jest.mock("../../common/terminal.js", () => ({
|
|
17
|
+
__esModule: true,
|
|
18
|
+
isInteractiveTerminal: jest.fn().mockReturnValue(true),
|
|
19
|
+
}));
|
|
20
|
+
describe("confirmLinkedConfig middleware", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
setupTestEnvironment();
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
jest.mocked(isInteractiveTerminal).mockReturnValue(true);
|
|
25
|
+
jest.mocked(confirmLinkedValue).mockResolvedValue(true);
|
|
26
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({});
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
cleanupTest();
|
|
30
|
+
});
|
|
31
|
+
describe("when both account and project are linked and the terminal is interactive", () => {
|
|
32
|
+
it("asks a single combined Y/n prompt and sets both values on accept", async () => {
|
|
33
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
34
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
35
|
+
projectName: TEST_PROJECT_NAME,
|
|
36
|
+
});
|
|
37
|
+
jest.mocked(confirmLinkedValue).mockResolvedValue(true);
|
|
38
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
39
|
+
await confirmLinkedConfig(argv);
|
|
40
|
+
expect(confirmLinkedValue).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(confirmLinkedValue).toHaveBeenCalledWith(`Use linked project '${TEST_PROJECT_NAME}' in account '${TEST_ACCOUNT_NAME}'?`);
|
|
42
|
+
expect(argv.account).toBe(TEST_ACCOUNT_NAME);
|
|
43
|
+
expect(argv.project).toBe(TEST_PROJECT_NAME);
|
|
44
|
+
expect(argv[USE_LINKED_DETAILS]).not.toBe(false);
|
|
45
|
+
});
|
|
46
|
+
it("sets useLinkedDetails=false on decline so downstream pickers run", async () => {
|
|
47
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
48
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
49
|
+
projectName: TEST_PROJECT_NAME,
|
|
50
|
+
});
|
|
51
|
+
jest.mocked(confirmLinkedValue).mockResolvedValue(false);
|
|
52
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
53
|
+
await confirmLinkedConfig(argv);
|
|
54
|
+
expect(confirmLinkedValue).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(argv[USE_LINKED_DETAILS]).toBe(false);
|
|
56
|
+
expect(argv.account).toBeUndefined();
|
|
57
|
+
expect(argv.project).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("when the terminal is non-interactive (CI/CD)", () => {
|
|
61
|
+
it("silently uses both linked values without prompting", async () => {
|
|
62
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
63
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
64
|
+
projectName: TEST_PROJECT_NAME,
|
|
65
|
+
});
|
|
66
|
+
jest.mocked(isInteractiveTerminal).mockReturnValue(false);
|
|
67
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
68
|
+
await confirmLinkedConfig(argv);
|
|
69
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
70
|
+
expect(argv.account).toBe(TEST_ACCOUNT_NAME);
|
|
71
|
+
expect(argv.project).toBe(TEST_PROJECT_NAME);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("when one of --account or --project is already supplied", () => {
|
|
75
|
+
it("skips entirely when --account is supplied (defers to fetchProject)", async () => {
|
|
76
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
77
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
78
|
+
projectName: TEST_PROJECT_NAME,
|
|
79
|
+
});
|
|
80
|
+
const argv = {
|
|
81
|
+
authToken: TEST_AUTH_TOKEN,
|
|
82
|
+
account: "explicit-account",
|
|
83
|
+
};
|
|
84
|
+
await confirmLinkedConfig(argv);
|
|
85
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
86
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
87
|
+
expect(argv.account).toBe("explicit-account");
|
|
88
|
+
expect(argv.project).toBeUndefined();
|
|
89
|
+
});
|
|
90
|
+
it("skips entirely when --project is supplied (defers to fetchAccount)", async () => {
|
|
91
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
92
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
93
|
+
projectName: TEST_PROJECT_NAME,
|
|
94
|
+
});
|
|
95
|
+
const argv = {
|
|
96
|
+
authToken: TEST_AUTH_TOKEN,
|
|
97
|
+
project: "explicit-project",
|
|
98
|
+
};
|
|
99
|
+
await confirmLinkedConfig(argv);
|
|
100
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
101
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
102
|
+
expect(argv.project).toBe("explicit-project");
|
|
103
|
+
expect(argv.account).toBeUndefined();
|
|
104
|
+
});
|
|
105
|
+
it("skips entirely when both flags are supplied", async () => {
|
|
106
|
+
const argv = {
|
|
107
|
+
authToken: TEST_AUTH_TOKEN,
|
|
108
|
+
account: "explicit-account",
|
|
109
|
+
project: "explicit-project",
|
|
110
|
+
};
|
|
111
|
+
await confirmLinkedConfig(argv);
|
|
112
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
113
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
114
|
+
});
|
|
115
|
+
it("skips entirely when --account is supplied as an array (repeated flag)", async () => {
|
|
116
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
117
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
118
|
+
projectName: TEST_PROJECT_NAME,
|
|
119
|
+
});
|
|
120
|
+
const argv = {
|
|
121
|
+
authToken: TEST_AUTH_TOKEN,
|
|
122
|
+
account: ["a", "b"],
|
|
123
|
+
};
|
|
124
|
+
await confirmLinkedConfig(argv);
|
|
125
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
126
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
127
|
+
expect(argv.account).toEqual(["a", "b"]);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("when --no-prompt is set (argv.prompt === false)", () => {
|
|
131
|
+
it("auto-accepts both linked values without prompting", async () => {
|
|
132
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
133
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
134
|
+
projectName: TEST_PROJECT_NAME,
|
|
135
|
+
});
|
|
136
|
+
const argv = {
|
|
137
|
+
authToken: TEST_AUTH_TOKEN,
|
|
138
|
+
prompt: false,
|
|
139
|
+
};
|
|
140
|
+
await confirmLinkedConfig(argv);
|
|
141
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
142
|
+
expect(argv.account).toBe(TEST_ACCOUNT_NAME);
|
|
143
|
+
expect(argv.project).toBe(TEST_PROJECT_NAME);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("when the linked config is partial", () => {
|
|
147
|
+
it("skips when only the account is linked (defers to fetchAccount's single prompt)", async () => {
|
|
148
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
149
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
150
|
+
});
|
|
151
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
152
|
+
await confirmLinkedConfig(argv);
|
|
153
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
154
|
+
expect(argv.account).toBeUndefined();
|
|
155
|
+
expect(argv.project).toBeUndefined();
|
|
156
|
+
});
|
|
157
|
+
it("skips when only the project is linked", async () => {
|
|
158
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
159
|
+
projectName: TEST_PROJECT_NAME,
|
|
160
|
+
});
|
|
161
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
162
|
+
await confirmLinkedConfig(argv);
|
|
163
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
164
|
+
expect(argv.account).toBeUndefined();
|
|
165
|
+
expect(argv.project).toBeUndefined();
|
|
166
|
+
});
|
|
167
|
+
it("skips when no linked config exists", async () => {
|
|
168
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({});
|
|
169
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
170
|
+
await confirmLinkedConfig(argv);
|
|
171
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
describe("when useLinkedDetails is already false (link command path)", () => {
|
|
175
|
+
it("skips entirely without reading linked config", async () => {
|
|
176
|
+
const argv = {
|
|
177
|
+
authToken: TEST_AUTH_TOKEN,
|
|
178
|
+
[USE_LINKED_DETAILS]: false,
|
|
179
|
+
};
|
|
180
|
+
await confirmLinkedConfig(argv);
|
|
181
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
182
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
183
|
+
expect(argv[USE_LINKED_DETAILS]).toBe(false);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe("when an api-key is supplied", () => {
|
|
187
|
+
it("skips entirely (account is resolved via the api-key)", async () => {
|
|
188
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
189
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
190
|
+
projectName: TEST_PROJECT_NAME,
|
|
191
|
+
});
|
|
192
|
+
const argv = {
|
|
193
|
+
authToken: TEST_AUTH_TOKEN,
|
|
194
|
+
"api-key": "zpka_some_key",
|
|
195
|
+
};
|
|
196
|
+
await confirmLinkedConfig(argv);
|
|
197
|
+
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
198
|
+
expect(readLinkedConfig).not.toHaveBeenCalled();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=confirm-linked-config.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm-linked-config.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/confirm-linked-config.integration.test.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,IAAI,CAAC,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrD,UAAU,EAAE,IAAI;IAChB,kBAAkB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrD,gBAAgB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACjD,kBAAkB,EAAE,kBAAkB;IACtC,mBAAmB,EAAE,IAAI;SACtB,EAAE,EAAE;SACJ,kBAAkB,CAAC,CAAC,IAA6B,EAAE,EAAE;QACpD,IAAI,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC;IACnC,CAAC,CAAC;CACL,CAAC,CAAC,CAAC;AAEJ,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,UAAU,EAAE,IAAI;IAChB,qBAAqB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;CACvD,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,UAAU,CAAC,GAAG,EAAE;QACd,oBAAoB,EAAE,CAAC;QACvB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,0EAA0E,EAAE,GAAG,EAAE;QACxF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAExD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAC7C,uBAAuB,iBAAiB,iBAAiB,iBAAiB,IAAI,CAC/E,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAEzD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;QAC5D,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAE1D,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wDAAwD,EAAE,GAAG,EAAE;QACtE,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,OAAO,EAAE,kBAAkB;aAC5B,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,OAAO,EAAE,kBAAkB;aAC5B,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,OAAO,EAAE,kBAAkB;gBAC3B,OAAO,EAAE,kBAAkB;aAC5B,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;YACrF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;aACpB,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC/D,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,MAAM,EAAE,KAAK;aACd,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;QACjD,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;YAC9F,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;YAEpD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;YACrE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4DAA4D,EAAE,GAAG,EAAE;QAC1E,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,CAAC,kBAAkB,CAAC,EAAE,KAAK;aAC5B,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAChD,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;YACpE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;gBAC9C,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,iBAAiB;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAA4B;gBACpC,SAAS,EAAE,eAAe;gBAC1B,SAAS,EAAE,eAAe;aAC3B,CAAC;YACF,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAClD,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Integration tests for the confirmLinkedConfig middleware.\n *\n * The middleware merges the two legacy \"Use linked account?\" / \"Use linked\n * project?\" prompts into a single combined Y/n. CI/CD safety is delegated to\n * the existing isInteractiveTerminal() check used elsewhere in the CLI — these\n * tests verify both the interactive UX and that non-interactive runs skip the\n * prompt entirely.\n */\n/// <reference types=\"jest\" />\nimport { confirmLinkedConfig } from \"../../common/middleware/confirm-linked-config.js\";\nimport {\n confirmLinkedValue,\n readLinkedConfig,\n USE_LINKED_DETAILS,\n} from \"../../common/read-linked-config.js\";\nimport { isInteractiveTerminal } from \"../../common/terminal.js\";\nimport {\n cleanupTest,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest\n .fn()\n .mockImplementation((argv: Record<string, unknown>) => {\n argv[\"useLinkedDetails\"] = false;\n }),\n}));\n\njest.mock(\"../../common/terminal.js\", () => ({\n __esModule: true,\n isInteractiveTerminal: jest.fn().mockReturnValue(true),\n}));\n\ndescribe(\"confirmLinkedConfig middleware\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n jest.clearAllMocks();\n jest.mocked(isInteractiveTerminal).mockReturnValue(true);\n jest.mocked(confirmLinkedValue).mockResolvedValue(true);\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n describe(\"when both account and project are linked and the terminal is interactive\", () => {\n it(\"asks a single combined Y/n prompt and sets both values on accept\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(confirmLinkedValue).mockResolvedValue(true);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(confirmLinkedValue).toHaveBeenCalledWith(\n `Use linked project '${TEST_PROJECT_NAME}' in account '${TEST_ACCOUNT_NAME}'?`\n );\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n expect(argv[USE_LINKED_DETAILS]).not.toBe(false);\n });\n\n it(\"sets useLinkedDetails=false on decline so downstream pickers run\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(confirmLinkedValue).mockResolvedValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n expect(argv.account).toBeUndefined();\n expect(argv.project).toBeUndefined();\n });\n });\n\n describe(\"when the terminal is non-interactive (CI/CD)\", () => {\n it(\"silently uses both linked values without prompting\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n });\n\n describe(\"when one of --account or --project is already supplied\", () => {\n it(\"skips entirely when --account is supplied (defers to fetchProject)\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: \"explicit-account\",\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(readLinkedConfig).not.toHaveBeenCalled();\n expect(argv.account).toBe(\"explicit-account\");\n expect(argv.project).toBeUndefined();\n });\n\n it(\"skips entirely when --project is supplied (defers to fetchAccount)\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n project: \"explicit-project\",\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(readLinkedConfig).not.toHaveBeenCalled();\n expect(argv.project).toBe(\"explicit-project\");\n expect(argv.account).toBeUndefined();\n });\n\n it(\"skips entirely when both flags are supplied\", async () => {\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: \"explicit-account\",\n project: \"explicit-project\",\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(readLinkedConfig).not.toHaveBeenCalled();\n });\n\n it(\"skips entirely when --account is supplied as an array (repeated flag)\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: [\"a\", \"b\"],\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(readLinkedConfig).not.toHaveBeenCalled();\n expect(argv.account).toEqual([\"a\", \"b\"]);\n });\n });\n\n describe(\"when --no-prompt is set (argv.prompt === false)\", () => {\n it(\"auto-accepts both linked values without prompting\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n prompt: false,\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n });\n\n describe(\"when the linked config is partial\", () => {\n it(\"skips when only the account is linked (defers to fetchAccount's single prompt)\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBeUndefined();\n expect(argv.project).toBeUndefined();\n });\n\n it(\"skips when only the project is linked\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBeUndefined();\n expect(argv.project).toBeUndefined();\n });\n\n it(\"skips when no linked config exists\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n });\n });\n\n describe(\"when useLinkedDetails is already false (link command path)\", () => {\n it(\"skips entirely without reading linked config\", async () => {\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n [USE_LINKED_DETAILS]: false,\n };\n await confirmLinkedConfig(argv);\n\n expect(readLinkedConfig).not.toHaveBeenCalled();\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n });\n });\n\n describe(\"when an api-key is supplied\", () => {\n it(\"skips entirely (account is resolved via the api-key)\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n \"api-key\": \"zpka_some_key\",\n };\n await confirmLinkedConfig(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(readLinkedConfig).not.toHaveBeenCalled();\n });\n });\n});\n"]}
|
|
@@ -57,7 +57,7 @@ describe("Info Command Integration Tests", () => {
|
|
|
57
57
|
readLinkedConfig.mockResolvedValue({
|
|
58
58
|
accountName: TEST_ACCOUNT,
|
|
59
59
|
projectName: TEST_PROJECT,
|
|
60
|
-
environmentType: "
|
|
60
|
+
environmentType: "development",
|
|
61
61
|
});
|
|
62
62
|
setupAuthenticatedNock(nock(TEST_API_BASE))
|
|
63
63
|
.get(`/v1/projects`)
|
|
@@ -77,9 +77,56 @@ describe("Info Command Integration Tests", () => {
|
|
|
77
77
|
expect(output).toContain(`Project: ${TEST_PROJECT}`);
|
|
78
78
|
expect(output).toContain(`Account: ${TEST_ACCOUNT}`);
|
|
79
79
|
expect(output).toContain(`Portal: https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}`);
|
|
80
|
-
expect(output).toContain("Environment Type:
|
|
80
|
+
expect(output).toContain("Environment Type: working-copy");
|
|
81
|
+
expect(output).not.toContain("Environment Type: development");
|
|
81
82
|
expect(output).toContain("Source Control: https://github.com/josh-twist/josh-poc");
|
|
82
83
|
});
|
|
84
|
+
it.each(["development", "working_copy", "working-copy"])("should display 'working-copy' label for ZUPLO_ENVIRONMENT_TYPE=%s", async (envType) => {
|
|
85
|
+
readLinkedConfig.mockResolvedValue({
|
|
86
|
+
accountName: TEST_ACCOUNT,
|
|
87
|
+
projectName: TEST_PROJECT,
|
|
88
|
+
environmentType: envType,
|
|
89
|
+
});
|
|
90
|
+
setupAuthenticatedNock(nock(TEST_API_BASE))
|
|
91
|
+
.get(`/v1/projects`)
|
|
92
|
+
.query({ accountName: TEST_ACCOUNT })
|
|
93
|
+
.reply(200, {
|
|
94
|
+
data: [
|
|
95
|
+
{
|
|
96
|
+
name: TEST_PROJECT,
|
|
97
|
+
sourceRepoUrl: null,
|
|
98
|
+
sourceControlProvider: "NONE",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
|
|
103
|
+
expect(mockPrintResult).toHaveBeenCalledTimes(1);
|
|
104
|
+
const output = mockPrintResult.mock.calls[0][0];
|
|
105
|
+
expect(output).toContain("Environment Type: working-copy");
|
|
106
|
+
});
|
|
107
|
+
it("should omit environment type when the linked value is whitespace-only", async () => {
|
|
108
|
+
readLinkedConfig.mockResolvedValue({
|
|
109
|
+
accountName: TEST_ACCOUNT,
|
|
110
|
+
projectName: TEST_PROJECT,
|
|
111
|
+
environmentType: " ",
|
|
112
|
+
});
|
|
113
|
+
setupAuthenticatedNock(nock(TEST_API_BASE))
|
|
114
|
+
.get(`/v1/projects`)
|
|
115
|
+
.query({ accountName: TEST_ACCOUNT })
|
|
116
|
+
.reply(200, {
|
|
117
|
+
data: [
|
|
118
|
+
{
|
|
119
|
+
name: TEST_PROJECT,
|
|
120
|
+
sourceRepoUrl: null,
|
|
121
|
+
sourceControlProvider: "NONE",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
await executeInfoCommand({ "api-key": TEST_AUTH_TOKEN });
|
|
126
|
+
expect(mockPrintResult).toHaveBeenCalledTimes(1);
|
|
127
|
+
const output = mockPrintResult.mock.calls[0][0];
|
|
128
|
+
expect(output).not.toContain("Environment Type:");
|
|
129
|
+
});
|
|
83
130
|
it("should show source control deep link when no repo is connected", async () => {
|
|
84
131
|
readLinkedConfig.mockResolvedValue({
|
|
85
132
|
accountName: TEST_ACCOUNT,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/info.integration.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Integration tests for the info command\n */\n/// <reference types=\"jest\" />\nimport nock from \"nock\";\nimport yargs from \"yargs/yargs\";\nimport infoCommand from \"../../cmds/info.js\";\nimport {\n cleanupTest,\n setupAuthenticatedNock,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_API_BASE,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\nconst TEST_ACCOUNT = TEST_ACCOUNT_NAME;\nconst TEST_PROJECT = TEST_PROJECT_NAME;\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest.fn(),\n}));\n\nconst { readLinkedConfig } = jest.requireMock(\n \"../../common/read-linked-config.js\"\n) as { readLinkedConfig: jest.Mock };\n\nasync function executeInfoCommand(args: { \"api-key\"?: string }) {\n const yargsInstance = yargs([])\n .command(infoCommand)\n .help(false)\n .version(false)\n .exitProcess(false);\n\n const commandArgs = [\"info\"];\n\n if (args[\"api-key\"]) {\n commandArgs.push(\"--api-key\", args[\"api-key\"]);\n }\n\n return await yargsInstance.parse(commandArgs);\n}\n\nconst mockPrintResult = jest.mocked(\n require(\"../../common/output.js\").printResultToConsoleAndExitGracefully\n);\nconst mockPrintCriticalFailure = jest.mocked(\n require(\"../../common/output.js\").printCriticalFailureToConsoleAndExit\n);\nconst mockPrintWarning = jest.mocked(\n require(\"../../common/output.js\").printWarningToConsole\n);\n\ndescribe(\"Info Command Integration Tests\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n nock.cleanAll();\n nock.disableNetConnect();\n jest.clearAllMocks();\n readLinkedConfig.mockResolvedValue({});\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n it(\"should show 'no project linked' when .env.zuplo is missing\", async () => {\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n });\n\n it(\"should show 'no project linked' when unauthenticated and not linked\", async () => {\n await executeInfoCommand({});\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n expect(mockPrintCriticalFailure).not.toHaveBeenCalled();\n });\n\n it(\"should show full project info when linked\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"working_copy\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: \"https://github.com/josh-twist/josh-poc\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).toContain(\n `Portal: https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}`\n );\n expect(output).toContain(\"Environment Type: working_copy\");\n expect(output).toContain(\n \"Source Control: https://github.com/josh-twist/josh-poc\"\n );\n });\n\n it(\"should show source control deep link when no repo is connected\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"production\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\n `Source Control: none, connect at https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}/settings/source-control-settings`\n );\n });\n\n it(\"should omit environment type when not in linked config\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).not.toContain(\"Environment Type:\");\n });\n\n it(\"should exit with error when API returns 401 and --api-key was used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"The provided --api-key was rejected. Check that it is valid and not expired, or run `zuplo login` to authenticate interactively.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should exit with error when API returns 401 and saved credentials were used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(executeInfoCommand({})).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"Your saved credentials were rejected. They may be expired — run `zuplo login` to re-authenticate, or pass a valid --api-key.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning when API returns a server error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(500, { error: \"Internal Server Error\" });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should exit with error when API returns a non-401 4xx\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(403, { error: \"Forbidden\" });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n `The Zuplo API returned 403 Forbidden. Verify the account \"${TEST_ACCOUNT}\" and your credentials.`\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning on network error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .replyWithError(\"ECONNREFUSED\");\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should warn and omit source control when linked project is not in API response\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"working_copy\",\n });\n\n // API returns projects but none match the linked project name (stale .env.zuplo)\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: \"some-other-project\",\n sourceRepoUrl: \"https://github.com/josh-twist/other\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n `Project \"${TEST_PROJECT}\" was not found in account \"${TEST_ACCOUNT}\". Run \\`zuplo link\\` to link a project.`\n );\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"info.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/info.integration.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Integration tests for the info command\n */\n/// <reference types=\"jest\" />\nimport nock from \"nock\";\nimport yargs from \"yargs/yargs\";\nimport infoCommand from \"../../cmds/info.js\";\nimport {\n cleanupTest,\n setupAuthenticatedNock,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_API_BASE,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\nconst TEST_ACCOUNT = TEST_ACCOUNT_NAME;\nconst TEST_PROJECT = TEST_PROJECT_NAME;\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest.fn(),\n}));\n\nconst { readLinkedConfig } = jest.requireMock(\n \"../../common/read-linked-config.js\"\n) as { readLinkedConfig: jest.Mock };\n\nasync function executeInfoCommand(args: { \"api-key\"?: string }) {\n const yargsInstance = yargs([])\n .command(infoCommand)\n .help(false)\n .version(false)\n .exitProcess(false);\n\n const commandArgs = [\"info\"];\n\n if (args[\"api-key\"]) {\n commandArgs.push(\"--api-key\", args[\"api-key\"]);\n }\n\n return await yargsInstance.parse(commandArgs);\n}\n\nconst mockPrintResult = jest.mocked(\n require(\"../../common/output.js\").printResultToConsoleAndExitGracefully\n);\nconst mockPrintCriticalFailure = jest.mocked(\n require(\"../../common/output.js\").printCriticalFailureToConsoleAndExit\n);\nconst mockPrintWarning = jest.mocked(\n require(\"../../common/output.js\").printWarningToConsole\n);\n\ndescribe(\"Info Command Integration Tests\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n nock.cleanAll();\n nock.disableNetConnect();\n jest.clearAllMocks();\n readLinkedConfig.mockResolvedValue({});\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n it(\"should show 'no project linked' when .env.zuplo is missing\", async () => {\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n });\n\n it(\"should show 'no project linked' when unauthenticated and not linked\", async () => {\n await executeInfoCommand({});\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"No project linked\");\n expect(output).toContain(\"zuplo link\");\n expect(mockPrintCriticalFailure).not.toHaveBeenCalled();\n });\n\n it(\"should show full project info when linked\", async () => {\n // The tenant API emits \"development\" for working-copy environments, which\n // is what gets written into .env.zuplo. The CLI must display this as\n // \"working-copy\".\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: \"https://github.com/josh-twist/josh-poc\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).toContain(\n `Portal: https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}`\n );\n expect(output).toContain(\"Environment Type: working-copy\");\n expect(output).not.toContain(\"Environment Type: development\");\n expect(output).toContain(\n \"Source Control: https://github.com/josh-twist/josh-poc\"\n );\n });\n\n it.each([\"development\", \"working_copy\", \"working-copy\"])(\n \"should display 'working-copy' label for ZUPLO_ENVIRONMENT_TYPE=%s\",\n async (envType) => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: envType,\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\"Environment Type: working-copy\");\n }\n );\n\n it(\"should omit environment type when the linked value is whitespace-only\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \" \",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).not.toContain(\"Environment Type:\");\n });\n\n it(\"should show source control deep link when no repo is connected\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"production\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(\n `Source Control: none, connect at https://portal.zuplo.com/${TEST_ACCOUNT}/${TEST_PROJECT}/settings/source-control-settings`\n );\n });\n\n it(\"should omit environment type when not in linked config\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: TEST_PROJECT,\n sourceRepoUrl: null,\n sourceControlProvider: \"NONE\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).not.toContain(\"Environment Type:\");\n });\n\n it(\"should exit with error when API returns 401 and --api-key was used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"The provided --api-key was rejected. Check that it is valid and not expired, or run `zuplo login` to authenticate interactively.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should exit with error when API returns 401 and saved credentials were used\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(401, {\n type: \"https://httpproblems.com/http-status/401\",\n title: \"Unauthorized\",\n status: 401,\n detail: \"Invalid token\",\n });\n\n await expect(executeInfoCommand({})).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n \"Your saved credentials were rejected. They may be expired — run `zuplo login` to re-authenticate, or pass a valid --api-key.\"\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning when API returns a server error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(500, { error: \"Internal Server Error\" });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should exit with error when API returns a non-401 4xx\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(403, { error: \"Forbidden\" });\n\n await expect(\n executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN })\n ).rejects.toThrow(\"Process would exit\");\n\n expect(mockPrintCriticalFailure).toHaveBeenCalledWith(\n `The Zuplo API returned 403 Forbidden. Verify the account \"${TEST_ACCOUNT}\" and your credentials.`\n );\n expect(mockPrintResult).not.toHaveBeenCalled();\n expect(mockPrintWarning).not.toHaveBeenCalled();\n });\n\n it(\"should show local info with warning on network error\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"development\",\n });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .replyWithError(\"ECONNREFUSED\");\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n \"Unable to fetch project details, some information may be missing\"\n );\n });\n\n it(\"should warn and omit source control when linked project is not in API response\", async () => {\n readLinkedConfig.mockResolvedValue({\n accountName: TEST_ACCOUNT,\n projectName: TEST_PROJECT,\n environmentType: \"working_copy\",\n });\n\n // API returns projects but none match the linked project name (stale .env.zuplo)\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(`/v1/projects`)\n .query({ accountName: TEST_ACCOUNT })\n .reply(200, {\n data: [\n {\n name: \"some-other-project\",\n sourceRepoUrl: \"https://github.com/josh-twist/other\",\n sourceControlProvider: \"GITHUB\",\n },\n ],\n });\n\n await executeInfoCommand({ \"api-key\": TEST_AUTH_TOKEN });\n\n expect(mockPrintResult).toHaveBeenCalledTimes(1);\n const output = mockPrintResult.mock.calls[0][0] as string;\n expect(output).toContain(`Project: ${TEST_PROJECT}`);\n expect(output).toContain(`Account: ${TEST_ACCOUNT}`);\n expect(output).not.toContain(\"Source Control:\");\n expect(mockPrintWarning).toHaveBeenCalledWith(\n `Project \"${TEST_PROJECT}\" was not found in account \"${TEST_ACCOUNT}\". Run \\`zuplo link\\` to link a project.`\n );\n });\n});\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import nock from "nock";
|
|
2
|
+
import { confirmLinkedConfig } from "../../common/middleware/confirm-linked-config.js";
|
|
2
3
|
import { fetchAccount } from "../../common/middleware/get-account-param.js";
|
|
3
4
|
import { fetchEnvironment } from "../../common/middleware/get-environment-param.js";
|
|
4
5
|
import { fetchProject } from "../../common/middleware/get-project-param.js";
|
|
@@ -109,6 +110,41 @@ describe("Linked-config cascade decline", () => {
|
|
|
109
110
|
expect(confirmLinkedValue).not.toHaveBeenCalled();
|
|
110
111
|
expect(argv.project).toBe(TEST_PROJECT_NAME);
|
|
111
112
|
});
|
|
113
|
+
it("combined prompt accepted: full chain calls confirmLinkedValue exactly once", async () => {
|
|
114
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
115
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
116
|
+
projectName: TEST_PROJECT_NAME,
|
|
117
|
+
});
|
|
118
|
+
jest.mocked(confirmLinkedValue).mockResolvedValue(true);
|
|
119
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
120
|
+
await confirmLinkedConfig(argv);
|
|
121
|
+
await fetchAccount(argv);
|
|
122
|
+
await fetchProject(argv);
|
|
123
|
+
expect(confirmLinkedValue).toHaveBeenCalledTimes(1);
|
|
124
|
+
expect(confirmLinkedValue).toHaveBeenCalledWith(`Use linked project '${TEST_PROJECT_NAME}' in account '${TEST_ACCOUNT_NAME}'?`);
|
|
125
|
+
expect(argv.account).toBe(TEST_ACCOUNT_NAME);
|
|
126
|
+
expect(argv.project).toBe(TEST_PROJECT_NAME);
|
|
127
|
+
});
|
|
128
|
+
it("combined prompt declined: full chain falls through to API pickers without further linked prompts", async () => {
|
|
129
|
+
jest.mocked(readLinkedConfig).mockResolvedValue({
|
|
130
|
+
accountName: TEST_ACCOUNT_NAME,
|
|
131
|
+
projectName: TEST_PROJECT_NAME,
|
|
132
|
+
});
|
|
133
|
+
jest.mocked(confirmLinkedValue).mockResolvedValue(false);
|
|
134
|
+
setupAuthenticatedNock(nock(TEST_API_BASE))
|
|
135
|
+
.get("/v1/accounts")
|
|
136
|
+
.reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });
|
|
137
|
+
setupAuthenticatedNock(nock(TEST_API_BASE))
|
|
138
|
+
.get("/v1/projects")
|
|
139
|
+
.query({ accountName: TEST_ACCOUNT_NAME })
|
|
140
|
+
.reply(200, { data: [{ name: TEST_PROJECT_NAME }] });
|
|
141
|
+
const argv = { authToken: TEST_AUTH_TOKEN };
|
|
142
|
+
await confirmLinkedConfig(argv);
|
|
143
|
+
await fetchAccount(argv);
|
|
144
|
+
await fetchProject(argv);
|
|
145
|
+
expect(confirmLinkedValue).toHaveBeenCalledTimes(1);
|
|
146
|
+
expect(argv[USE_LINKED_DETAILS]).toBe(false);
|
|
147
|
+
});
|
|
112
148
|
it("fails loudly when --project is omitted in non-interactive environments without linked config", async () => {
|
|
113
149
|
jest.mocked(readLinkedConfig).mockResolvedValue({});
|
|
114
150
|
jest.mocked(isInteractiveTerminal).mockReturnValue(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linked-config-cascade.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/linked-config-cascade.integration.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Integration tests for the linked-config cascade decline behaviour.\n *\n * When a user is prompted \"Use linked account 'X'?\" and answers No, the\n * useLinkedDetails flag is set to false on argv. Every downstream middleware\n * (fetchProject) must respect that flag and skip their own linked-value prompts —\n * so a manually selected account can never be accidentally paired with a stale\n * linked project.\n */\n/// <reference types=\"jest\" />\nimport nock from \"nock\";\nimport { fetchAccount } from \"../../common/middleware/get-account-param.js\";\nimport { fetchEnvironment } from \"../../common/middleware/get-environment-param.js\";\nimport { fetchProject } from \"../../common/middleware/get-project-param.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"../../common/output.js\";\nimport {\n confirmLinkedValue,\n readLinkedConfig,\n USE_LINKED_DETAILS,\n} from \"../../common/read-linked-config.js\";\nimport { isInteractiveTerminal } from \"../../common/terminal.js\";\nimport {\n cleanupTest,\n setupAuthenticatedNock,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_API_BASE,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest\n .fn()\n .mockImplementation((argv: Record<string, unknown>) => {\n argv[\"useLinkedDetails\"] = false;\n }),\n}));\n\njest.mock(\"../../common/terminal.js\", () => ({\n __esModule: true,\n isInteractiveTerminal: jest.fn().mockReturnValue(true),\n}));\n\ndescribe(\"Linked-config cascade decline\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n nock.disableNetConnect();\n jest.clearAllMocks();\n jest.mocked(isInteractiveTerminal).mockReturnValue(true);\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n it(\"sets useLinkedDetails to false when user declines linked account\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n });\n // User says No to the linked account prompt\n jest.mocked(confirmLinkedValue).mockResolvedValue(false);\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/accounts\")\n .reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await fetchAccount(argv);\n\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n // account was resolved via the API selection path, not from linked config\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n });\n\n it(\"skips linked project prompt when useLinkedDetails is false\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n // confirmLinkedValue should never be reached for the project step\n jest\n .mocked(confirmLinkedValue)\n .mockRejectedValue(\n new Error(\"fetchProject must not call confirmLinkedValue after decline\")\n );\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/projects\")\n .query({ accountName: TEST_ACCOUNT_NAME })\n .reply(200, { data: [{ name: TEST_PROJECT_NAME }] });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n [USE_LINKED_DETAILS]: false,\n };\n await fetchProject(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n\n it(\"full cascade: declining account prevents linked project prompt\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n // Only the first call (account) returns false — if project middleware calls\n // confirmLinkedValue, the mock will return false again and it'll fall through\n // to the API. The real test is the call count.\n jest.mocked(confirmLinkedValue).mockResolvedValueOnce(false);\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/accounts\")\n .reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/projects\")\n .query({ accountName: TEST_ACCOUNT_NAME })\n .reply(200, { data: [{ name: TEST_PROJECT_NAME }] });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n await fetchAccount(argv);\n await fetchProject(argv);\n\n // confirmLinkedValue must only have been called once (for the account prompt).\n // The cascade flag prevented the project prompt.\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n });\n\n it(\"uses linked account silently when terminal is non-interactive\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n });\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await fetchAccount(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n });\n\n it(\"uses linked project silently when terminal is non-interactive\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n };\n await fetchProject(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n\n it(\"fails loudly when --project is omitted in non-interactive environments without linked config\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n };\n\n // The guard fires before any API call, so no nock interceptor is needed.\n await expect(fetchProject(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--project is required\")\n );\n expect(argv.project).toBeUndefined();\n });\n\n it(\"fails loudly when --account is omitted in non-interactive environments without linked config\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n // The guard fires before any API call, so no nock interceptor is needed.\n await expect(fetchAccount(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--account is required\")\n );\n expect(argv.account).toBeUndefined();\n });\n\n it(\"fails loudly when --environment is omitted in non-interactive environments\", async () => {\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n // No argv.dir means getGitBranch returns undefined, falling through to the\n // non-interactive guard before any API call is made.\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n project: TEST_PROJECT_NAME,\n };\n\n await expect(fetchEnvironment(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--environment is required\")\n );\n expect(argv.environment).toBeUndefined();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"linked-config-cascade.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/linked-config-cascade.integration.test.ts"],"names":[],"mappings":"AAUA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAC5E,OAAO,EAAE,oCAAoC,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,IAAI,CAAC,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrD,UAAU,EAAE,IAAI;IAChB,kBAAkB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;IACrD,gBAAgB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACjD,kBAAkB,EAAE,kBAAkB;IACtC,mBAAmB,EAAE,IAAI;SACtB,EAAE,EAAE;SACJ,kBAAkB,CAAC,CAAC,IAA6B,EAAE,EAAE;QACpD,IAAI,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC;IACnC,CAAC,CAAC;CACL,CAAC,CAAC,CAAC;AAEJ,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,UAAU,EAAE,IAAI;IAChB,qBAAqB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;CACvD,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,UAAU,CAAC,GAAG,EAAE;QACd,oBAAoB,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEzD,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QACrE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QAEH,IAAI;aACD,MAAM,CAAC,kBAAkB,CAAC;aAC1B,iBAAiB,CAChB,IAAI,KAAK,CAAC,6DAA6D,CAAC,CACzE,CAAC;QAEJ,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;aACzC,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAA4B;YACpC,SAAS,EAAE,eAAe;YAC1B,OAAO,EAAE,iBAAiB;YAC1B,CAAC,kBAAkB,CAAC,EAAE,KAAK;SAC5B,CAAC;QACF,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QAKH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAE7D,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;aACzC,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAErE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAIzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QACrE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,IAAI,GAA4B;YACpC,SAAS,EAAE,eAAe;YAC1B,OAAO,EAAE,iBAAiB;SAC3B,CAAC;QACF,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAExD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAErE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAC7C,uBAAuB,iBAAiB,iBAAiB,iBAAiB,IAAI,CAC/E,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kGAAkG,EAAE,KAAK,IAAI,EAAE;QAChH,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC;YAC9C,WAAW,EAAE,iBAAiB;YAC9B,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEzD,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,sBAAsB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;aACxC,GAAG,CAAC,cAAc,CAAC;aACnB,KAAK,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;aACzC,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAErE,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAIzB,MAAM,CAAC,kBAAkB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;QAC5G,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,IAAI,GAA4B;YACpC,SAAS,EAAE,eAAe;YAC1B,OAAO,EAAE,iBAAiB;SAC3B,CAAC;QAGF,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAEvE,MAAM,CAAC,oCAAoC,CAAC,CAAC,oBAAoB,CAC/D,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CACjD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;QAC5G,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,IAAI,GAA4B,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;QAGrE,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAEvE,MAAM,CAAC,oCAAoC,CAAC,CAAC,oBAAoB,CAC/D,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CACjD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAI1D,MAAM,IAAI,GAA4B;YACpC,SAAS,EAAE,eAAe;YAC1B,OAAO,EAAE,iBAAiB;YAC1B,OAAO,EAAE,iBAAiB;SAC3B,CAAC;QAEF,MAAM,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAE3E,MAAM,CAAC,oCAAoC,CAAC,CAAC,oBAAoB,CAC/D,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,CACrD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Integration tests for the linked-config cascade decline behaviour.\n *\n * When a user is prompted \"Use linked account 'X'?\" and answers No, the\n * useLinkedDetails flag is set to false on argv. Every downstream middleware\n * (fetchProject) must respect that flag and skip their own linked-value prompts —\n * so a manually selected account can never be accidentally paired with a stale\n * linked project.\n */\n/// <reference types=\"jest\" />\nimport nock from \"nock\";\nimport { confirmLinkedConfig } from \"../../common/middleware/confirm-linked-config.js\";\nimport { fetchAccount } from \"../../common/middleware/get-account-param.js\";\nimport { fetchEnvironment } from \"../../common/middleware/get-environment-param.js\";\nimport { fetchProject } from \"../../common/middleware/get-project-param.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"../../common/output.js\";\nimport {\n confirmLinkedValue,\n readLinkedConfig,\n USE_LINKED_DETAILS,\n} from \"../../common/read-linked-config.js\";\nimport { isInteractiveTerminal } from \"../../common/terminal.js\";\nimport {\n cleanupTest,\n setupAuthenticatedNock,\n setupTestEnvironment,\n TEST_ACCOUNT_NAME,\n TEST_API_BASE,\n TEST_AUTH_TOKEN,\n TEST_PROJECT_NAME,\n} from \"./test-utils.js\";\n\njest.mock(\"../../common/read-linked-config.js\", () => ({\n __esModule: true,\n confirmLinkedValue: jest.fn().mockResolvedValue(true),\n readLinkedConfig: jest.fn().mockResolvedValue({}),\n USE_LINKED_DETAILS: \"useLinkedDetails\",\n ignoreLinkedDetails: jest\n .fn()\n .mockImplementation((argv: Record<string, unknown>) => {\n argv[\"useLinkedDetails\"] = false;\n }),\n}));\n\njest.mock(\"../../common/terminal.js\", () => ({\n __esModule: true,\n isInteractiveTerminal: jest.fn().mockReturnValue(true),\n}));\n\ndescribe(\"Linked-config cascade decline\", () => {\n beforeEach(() => {\n setupTestEnvironment();\n nock.disableNetConnect();\n jest.clearAllMocks();\n jest.mocked(isInteractiveTerminal).mockReturnValue(true);\n });\n\n afterEach(() => {\n cleanupTest();\n });\n\n it(\"sets useLinkedDetails to false when user declines linked account\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n });\n // User says No to the linked account prompt\n jest.mocked(confirmLinkedValue).mockResolvedValue(false);\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/accounts\")\n .reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await fetchAccount(argv);\n\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n // account was resolved via the API selection path, not from linked config\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n });\n\n it(\"skips linked project prompt when useLinkedDetails is false\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n // confirmLinkedValue should never be reached for the project step\n jest\n .mocked(confirmLinkedValue)\n .mockRejectedValue(\n new Error(\"fetchProject must not call confirmLinkedValue after decline\")\n );\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/projects\")\n .query({ accountName: TEST_ACCOUNT_NAME })\n .reply(200, { data: [{ name: TEST_PROJECT_NAME }] });\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n [USE_LINKED_DETAILS]: false,\n };\n await fetchProject(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n\n it(\"full cascade: declining account prevents linked project prompt\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n\n // Only the first call (account) returns false — if project middleware calls\n // confirmLinkedValue, the mock will return false again and it'll fall through\n // to the API. The real test is the call count.\n jest.mocked(confirmLinkedValue).mockResolvedValueOnce(false);\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/accounts\")\n .reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/projects\")\n .query({ accountName: TEST_ACCOUNT_NAME })\n .reply(200, { data: [{ name: TEST_PROJECT_NAME }] });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n await fetchAccount(argv);\n await fetchProject(argv);\n\n // confirmLinkedValue must only have been called once (for the account prompt).\n // The cascade flag prevented the project prompt.\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n });\n\n it(\"uses linked account silently when terminal is non-interactive\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n });\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n await fetchAccount(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n });\n\n it(\"uses linked project silently when terminal is non-interactive\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n };\n await fetchProject(argv);\n\n expect(confirmLinkedValue).not.toHaveBeenCalled();\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n\n it(\"combined prompt accepted: full chain calls confirmLinkedValue exactly once\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(confirmLinkedValue).mockResolvedValue(true);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n await confirmLinkedConfig(argv);\n await fetchAccount(argv);\n await fetchProject(argv);\n\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(confirmLinkedValue).toHaveBeenCalledWith(\n `Use linked project '${TEST_PROJECT_NAME}' in account '${TEST_ACCOUNT_NAME}'?`\n );\n expect(argv.account).toBe(TEST_ACCOUNT_NAME);\n expect(argv.project).toBe(TEST_PROJECT_NAME);\n });\n\n it(\"combined prompt declined: full chain falls through to API pickers without further linked prompts\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({\n accountName: TEST_ACCOUNT_NAME,\n projectName: TEST_PROJECT_NAME,\n });\n jest.mocked(confirmLinkedValue).mockResolvedValue(false);\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/accounts\")\n .reply(200, { data: [{ name: TEST_ACCOUNT_NAME }] });\n\n setupAuthenticatedNock(nock(TEST_API_BASE))\n .get(\"/v1/projects\")\n .query({ accountName: TEST_ACCOUNT_NAME })\n .reply(200, { data: [{ name: TEST_PROJECT_NAME }] });\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n await confirmLinkedConfig(argv);\n await fetchAccount(argv);\n await fetchProject(argv);\n\n // The combined prompt fired once. Downstream middlewares must not re-prompt\n // because USE_LINKED_DETAILS was set to false on decline.\n expect(confirmLinkedValue).toHaveBeenCalledTimes(1);\n expect(argv[USE_LINKED_DETAILS]).toBe(false);\n });\n\n it(\"fails loudly when --project is omitted in non-interactive environments without linked config\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n };\n\n // The guard fires before any API call, so no nock interceptor is needed.\n await expect(fetchProject(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--project is required\")\n );\n expect(argv.project).toBeUndefined();\n });\n\n it(\"fails loudly when --account is omitted in non-interactive environments without linked config\", async () => {\n jest.mocked(readLinkedConfig).mockResolvedValue({});\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n const argv: Record<string, unknown> = { authToken: TEST_AUTH_TOKEN };\n\n // The guard fires before any API call, so no nock interceptor is needed.\n await expect(fetchAccount(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--account is required\")\n );\n expect(argv.account).toBeUndefined();\n });\n\n it(\"fails loudly when --environment is omitted in non-interactive environments\", async () => {\n jest.mocked(isInteractiveTerminal).mockReturnValue(false);\n\n // No argv.dir means getGitBranch returns undefined, falling through to the\n // non-interactive guard before any API call is made.\n const argv: Record<string, unknown> = {\n authToken: TEST_AUTH_TOKEN,\n account: TEST_ACCOUNT_NAME,\n project: TEST_PROJECT_NAME,\n };\n\n await expect(fetchEnvironment(argv)).rejects.toThrow(\"Process would exit\");\n\n expect(printCriticalFailureToConsoleAndExit).toHaveBeenCalledWith(\n expect.stringContaining(\"--environment is required\")\n );\n expect(argv.environment).toBeUndefined();\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/cmds/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/cmds/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAcV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAiEf,OAAO;;AApE/B,wBAwEE"}
|
package/dist/cmds/delete.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { captureEvent } from "../common/analytics/lib.js";
|
|
2
2
|
import { authenticate } from "../common/middleware/authentication.js";
|
|
3
|
+
import { confirmLinkedConfig } from "../common/middleware/confirm-linked-config.js";
|
|
3
4
|
import { fetchAccount } from "../common/middleware/get-account-param.js";
|
|
4
5
|
import { fetchProject } from "../common/middleware/get-project-param.js";
|
|
5
6
|
import { configure } from "../common/middleware/user-configuration.js";
|
|
@@ -67,6 +68,7 @@ export default {
|
|
|
67
68
|
setBlocking,
|
|
68
69
|
authenticate,
|
|
69
70
|
configure,
|
|
71
|
+
confirmLinkedConfig,
|
|
70
72
|
fetchAccount,
|
|
71
73
|
fetchProject,
|
|
72
74
|
identify,
|
package/dist/cmds/delete.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/cmds/delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,WAAW,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAa,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,eAAe;IACb,IAAI,EAAE,8BAA8B;IACpC,OAAO,EAAE,QAAQ;IACjB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,iCAAiC,CAAC;aACxC,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,wBAAwB;YAClC,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,QAAQ;SAChB,CAAC;aACD,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,oCAAoC;SAC/C,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,2CAA2C;YACrD,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,kBAAkB;SAC7B,CAAC;aACD,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,kBAAkB;SAC7B,CAAC;aACD,MAAM,CAAC,MAAM,EAAE;YACd,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,oDAAoD;SAC/D,CAAC;aACD,MAAM,CAAC,sBAAsB,EAAE;YAC9B,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,uDAAuD;SAClE,CAAC;aACD,OAAO,CAAC,MAAM,CAAC;aACf,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;YAEd,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;aACD,OAAO,CAAC;YACP;gBACE,qDAAqD;gBACrD,0CAA0C;aAC3C;YACD;gBACE,4DAA4D;gBAC5D,+DAA+D;aAChE;SACF,CAAC;aACD,UAAU,CAAC;YACV,WAAW;YACX,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,YAAY;YACZ,QAAQ;SACT,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,IAAiB,CAAC,CAAC;IACrC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { authenticate } from \"../common/middleware/authentication.js\";\nimport { fetchAccount } from \"../common/middleware/get-account-param.js\";\nimport { fetchProject } from \"../common/middleware/get-project-param.js\";\nimport { configure } from \"../common/middleware/user-configuration.js\";\nimport { identify } from \"../common/middleware/user-identification.js\";\nimport setBlocking from \"../common/output.js\";\nimport { Arguments, deleteZup } from \"../delete/handler.js\";\n\nexport default {\n desc: \"Deletes the Zuplo API by URL\",\n command: \"delete\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 delete --url <url> [options]\")\n .option(\"api-key\", {\n type: \"string\",\n describe: \"The API Key from Zuplo\",\n envVar: \"API_KEY\",\n alias: \"apikey\",\n })\n .option(\"url\", {\n type: \"string\",\n describe: \"The URL of the Zuplo API to delete\",\n })\n .option(\"branch\", {\n type: \"string\",\n describe: \"The branch name to delete deployments for\",\n hidden: true,\n })\n .option(\"project\", {\n type: \"string\",\n describe: \"The project name\",\n })\n .option(\"account\", {\n type: \"string\",\n describe: \"The account name\",\n })\n .option(\"wait\", {\n type: \"boolean\",\n describe: \"Should the CLI wait until the Zuplo API is deleted\",\n })\n .option(\"self-hosted-endpoint\", {\n type: \"string\",\n describe: \"The endpoint of your self-hosted service to deploy to\",\n })\n .boolean(\"wait\")\n .check((argv) => {\n // Branch option is hidden for testing, but still works internally\n if (!argv.url && !argv.branch) {\n throw new Error(\"--url is required\");\n }\n if (argv.url && argv.branch) {\n throw new Error(\"Cannot specify both --url and --branch\");\n }\n return true;\n })\n .example([\n [\n \"$0 delete --url https://my-api-dev-123abc.zuplo.app\",\n \"Delete a deployed environment by its URL\",\n ],\n [\n \"$0 delete --url https://my-api-dev-123abc.zuplo.app --wait\",\n \"Delete an environment and wait until the deletion is complete\",\n ],\n ])\n .middleware([\n setBlocking,\n authenticate,\n configure,\n fetchAccount,\n fetchProject,\n identify,\n ]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo delete\" });\n await deleteZup(argv as Arguments);\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/cmds/delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,WAAW,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAa,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,eAAe;IACb,IAAI,EAAE,8BAA8B;IACpC,OAAO,EAAE,QAAQ;IACjB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,iCAAiC,CAAC;aACxC,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,wBAAwB;YAClC,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,QAAQ;SAChB,CAAC;aACD,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,oCAAoC;SAC/C,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,2CAA2C;YACrD,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,kBAAkB;SAC7B,CAAC;aACD,MAAM,CAAC,SAAS,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,kBAAkB;SAC7B,CAAC;aACD,MAAM,CAAC,MAAM,EAAE;YACd,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,oDAAoD;SAC/D,CAAC;aACD,MAAM,CAAC,sBAAsB,EAAE;YAC9B,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,uDAAuD;SAClE,CAAC;aACD,OAAO,CAAC,MAAM,CAAC;aACf,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;YAEd,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;aACD,OAAO,CAAC;YACP;gBACE,qDAAqD;gBACrD,0CAA0C;aAC3C;YACD;gBACE,4DAA4D;gBAC5D,+DAA+D;aAChE;SACF,CAAC;aACD,UAAU,CAAC;YACV,WAAW;YACX,YAAY;YACZ,SAAS;YACT,mBAAmB;YACnB,YAAY;YACZ,YAAY;YACZ,QAAQ;SACT,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QACpD,MAAM,SAAS,CAAC,IAAiB,CAAC,CAAC;IACrC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { authenticate } from \"../common/middleware/authentication.js\";\nimport { confirmLinkedConfig } from \"../common/middleware/confirm-linked-config.js\";\nimport { fetchAccount } from \"../common/middleware/get-account-param.js\";\nimport { fetchProject } from \"../common/middleware/get-project-param.js\";\nimport { configure } from \"../common/middleware/user-configuration.js\";\nimport { identify } from \"../common/middleware/user-identification.js\";\nimport setBlocking from \"../common/output.js\";\nimport { Arguments, deleteZup } from \"../delete/handler.js\";\n\nexport default {\n desc: \"Deletes the Zuplo API by URL\",\n command: \"delete\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 delete --url <url> [options]\")\n .option(\"api-key\", {\n type: \"string\",\n describe: \"The API Key from Zuplo\",\n envVar: \"API_KEY\",\n alias: \"apikey\",\n })\n .option(\"url\", {\n type: \"string\",\n describe: \"The URL of the Zuplo API to delete\",\n })\n .option(\"branch\", {\n type: \"string\",\n describe: \"The branch name to delete deployments for\",\n hidden: true,\n })\n .option(\"project\", {\n type: \"string\",\n describe: \"The project name\",\n })\n .option(\"account\", {\n type: \"string\",\n describe: \"The account name\",\n })\n .option(\"wait\", {\n type: \"boolean\",\n describe: \"Should the CLI wait until the Zuplo API is deleted\",\n })\n .option(\"self-hosted-endpoint\", {\n type: \"string\",\n describe: \"The endpoint of your self-hosted service to deploy to\",\n })\n .boolean(\"wait\")\n .check((argv) => {\n // Branch option is hidden for testing, but still works internally\n if (!argv.url && !argv.branch) {\n throw new Error(\"--url is required\");\n }\n if (argv.url && argv.branch) {\n throw new Error(\"Cannot specify both --url and --branch\");\n }\n return true;\n })\n .example([\n [\n \"$0 delete --url https://my-api-dev-123abc.zuplo.app\",\n \"Delete a deployed environment by its URL\",\n ],\n [\n \"$0 delete --url https://my-api-dev-123abc.zuplo.app --wait\",\n \"Delete an environment and wait until the deletion is complete\",\n ],\n ])\n .middleware([\n setBlocking,\n authenticate,\n configure,\n confirmLinkedConfig,\n fetchAccount,\n fetchProject,\n identify,\n ]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo delete\" });\n await deleteZup(argv as Arguments);\n },\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/cmds/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/cmds/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAeV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAsFf,OAAO;;AAzF/B,wBA6FE"}
|