Skip to content

Commit 8eb7fa1

Browse files
committed
Add tests for customer list
1 parent 816a5e7 commit 8eb7fa1

File tree

3 files changed

+168
-24
lines changed

3 files changed

+168
-24
lines changed

src/channels.spec.ts

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,18 @@ describe("ChannelsService", () => {
8484
});
8585

8686
describe("pollForAirgapReleaseStatus", () => {
87-
const mockServer = mockttp.getLocal();
87+
let mockServer: mockttp.Mockttp;
8888
const apiClient = new VendorPortalApi();
8989
apiClient.apiToken = "abcd1234";
90-
apiClient.endpoint = "http://localhost:8080";
91-
// Start your mock server
92-
beforeEach(() => {
93-
mockServer.start(8080);
90+
91+
beforeEach(async () => {
92+
mockServer = mockttp.getLocal();
93+
await mockServer.start();
94+
apiClient.endpoint = "http://localhost:" + mockServer.port;
95+
});
96+
afterEach(async () => {
97+
await mockServer.stop();
9498
});
95-
afterEach(() => mockServer.stop());
9699

97100
it("should poll for airgapped release status until it reaches the expected status", async () => {
98101
const releaseData = {
@@ -105,23 +108,29 @@ describe("pollForAirgapReleaseStatus", () => {
105108
]
106109
};
107110

108-
await mockServer.forGet("/app/1234abcd/channel/1/releases").thenReply(200, JSON.stringify(releaseData));
111+
await mockServer.forGet("/app/1234abcd/channel/1/releases").once().thenReply(200, JSON.stringify(releaseData));
109112

110113
const releaseResult = await pollForAirgapReleaseStatus(apiClient, "1234abcd", "1", 0, "built");
111114
expect(releaseResult).toEqual("built");
112115
});
113116
});
114117

115118
describe("getDownloadUrlAirgapBuildRelease", () => {
116-
const mockServer = mockttp.getLocal();
117-
const apiClient = new VendorPortalApi();
118-
apiClient.apiToken = "abcd1234";
119-
apiClient.endpoint = "http://localhost:8081";
120-
// Start your mock server
121-
beforeEach(() => {
122-
mockServer.start(8081);
119+
let mockServer: mockttp.Mockttp;
120+
let apiClient: VendorPortalApi;
121+
122+
beforeEach(async () => {
123+
mockServer = mockttp.getLocal();
124+
await mockServer.start();
125+
// Ensure server is fully ready
126+
await new Promise(resolve => setTimeout(resolve, 5));
127+
apiClient = new VendorPortalApi();
128+
apiClient.apiToken = "abcd1234";
129+
apiClient.endpoint = "http://localhost:" + mockServer.port;
130+
});
131+
afterEach(async () => {
132+
await mockServer.stop();
123133
});
124-
afterEach(() => mockServer.stop());
125134

126135
it("should get the download URL for an airgap build release", async () => {
127136
const releaseData = {
@@ -137,8 +146,12 @@ describe("getDownloadUrlAirgapBuildRelease", () => {
137146
url: "https://s3.amazonaws.com/airgap.replicated.com/xxxxxxxxx/7.airgap?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=xxxxxx%2F20250317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date="
138147
};
139148

140-
await mockServer.forGet("/app/1234abcd/channel/1/releases").thenReply(200, JSON.stringify(releaseData));
141-
await mockServer.forGet("/app/1234abcd/channel/1/airgap/download-url").withQuery({ channelSequence: 1 }).thenReply(200, JSON.stringify(downloadUrlData));
149+
const releasesMock = mockServer.forGet("/app/1234abcd/channel/1/releases").once().thenReply(200, JSON.stringify(releaseData));
150+
const downloadUrlMock = mockServer.forGet("/app/1234abcd/channel/1/airgap/download-url").withQuery({ channelSequence: 1 }).once().thenReply(200, JSON.stringify(downloadUrlData));
151+
152+
// Ensure mocks are set up before making requests
153+
await releasesMock;
154+
await downloadUrlMock;
142155

143156
const downloadUrlResult = await getDownloadUrlAirgapBuildRelease(apiClient, "1234abcd", "1", 0);
144157
expect(downloadUrlResult).toEqual("https://s3.amazonaws.com/airgap.replicated.com/xxxxxxxxx/7.airgap?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=xxxxxx%2F20250317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=");

src/customers.spec.ts

Lines changed: 138 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { VendorPortalApi } from "./configuration";
2-
import { Customer, archiveCustomer, createCustomer } from "./customers";
2+
import { Customer, CustomerSummary, archiveCustomer, createCustomer, listCustomersByName } from "./customers";
33
import * as mockttp from "mockttp";
44

55
describe("Archive Customer", () => {
@@ -36,17 +36,18 @@ describe("Archive Customer", () => {
3636
});
3737

3838
describe("Create Customer", () => {
39-
const mockServer = mockttp.getLocal();
39+
let mockServer: mockttp.Mockttp;
4040
const apiClient = new VendorPortalApi();
4141
apiClient.apiToken = "abcd1234";
4242

4343
beforeEach(async () => {
44+
mockServer = mockttp.getLocal();
4445
await mockServer.start();
4546
apiClient.endpoint = "http://localhost:" + mockServer.port;
4647
});
4748

4849
afterEach(async () => {
49-
mockServer.stop();
50+
await mockServer.stop();
5051
});
5152

5253
it("create a new customer for testing", async () => {
@@ -62,13 +63,144 @@ describe("Create Customer", () => {
6263
installationId: "1234abcd"
6364
}
6465
};
65-
await mockServer.forGet("/apps").thenReply(200, JSON.stringify(expectedApplications));
66-
await mockServer.forPost("/customer").thenReply(201, JSON.stringify(customerResponse));
67-
await mockServer.forGet("/app/1234abcd/customer/5678efgh/license-download").thenReply(403);
66+
await mockServer.forGet("/apps").once().thenReply(200, JSON.stringify(expectedApplications));
67+
await mockServer.forPost("/customer").once().thenReply(201, JSON.stringify(customerResponse));
68+
await mockServer.forGet("/app/1234abcd/customer/5678efgh/license-download").once().thenReply(403);
6869

6970
const customer: Customer = await createCustomer(apiClient, "app-1", "testing", "[email protected]", "test", "", 0);
7071
expect(customer.name).toEqual("testing");
7172
expect(customer.customerId).toEqual("5678efgh");
7273
expect(customer.licenseId).toEqual("1234abcd");
7374
});
7475
});
76+
77+
describe("List Customers By Name", () => {
78+
let mockServer: mockttp.Mockttp;
79+
let apiClient: VendorPortalApi;
80+
81+
beforeEach(async () => {
82+
mockServer = mockttp.getLocal();
83+
await mockServer.start();
84+
// Ensure server is fully ready
85+
await new Promise(resolve => setTimeout(resolve, 5));
86+
apiClient = new VendorPortalApi();
87+
apiClient.apiToken = "abcd1234";
88+
apiClient.endpoint = "http://localhost:" + mockServer.port;
89+
});
90+
91+
afterEach(async () => {
92+
await mockServer.stop();
93+
});
94+
95+
it("should return customers matching the name", async () => {
96+
const appId = "test-app-1";
97+
const appSlug = "test-app-1";
98+
const customerName = "UniqueCustomerName123";
99+
const expectedApplications = {
100+
apps: [
101+
{ id: appId, name: "Test App 1", slug: appSlug },
102+
{ id: "5678efgh", name: "App 2", slug: "app-2" }
103+
]
104+
};
105+
const customersResponse = {
106+
customers: [
107+
{ id: "customer-1", name: customerName },
108+
{ id: "customer-2", name: customerName + " Two" }
109+
]
110+
};
111+
112+
const appsMock = mockServer.forGet("/apps").thenReply(200, JSON.stringify(expectedApplications));
113+
const customersMock = mockServer.forGet(`/app/${appId}/customers`)
114+
.withQuery({ name: customerName })
115+
.once()
116+
.thenReply(200, JSON.stringify(customersResponse));
117+
118+
await appsMock;
119+
await customersMock;
120+
121+
const customers: CustomerSummary[] = await listCustomersByName(apiClient, appSlug, customerName);
122+
expect(customers).toHaveLength(2);
123+
expect(customers[0].name).toEqual(customerName);
124+
expect(customers[0].customerId).toEqual("customer-1");
125+
expect(customers[1].name).toEqual(customerName + " Two");
126+
expect(customers[1].customerId).toEqual("customer-2");
127+
});
128+
129+
it("should return empty array when no customers match", async () => {
130+
const appId = "test-app-empty";
131+
const appSlug = "test-app-empty";
132+
const expectedApplications = {
133+
apps: [{ id: appId, name: "Test App Empty", slug: appSlug }]
134+
};
135+
const customersResponse = {
136+
customers: []
137+
};
138+
139+
await mockServer.forGet("/apps").once().thenReply(200, JSON.stringify(expectedApplications));
140+
await mockServer.forGet(`/app/${appId}/customers`).withQuery({ name: "NonExistent" }).once().thenReply(200, JSON.stringify(customersResponse));
141+
142+
const customers: CustomerSummary[] = await listCustomersByName(apiClient, appSlug, "NonExistent");
143+
expect(customers).toHaveLength(0);
144+
});
145+
146+
it("should return empty array when customers field is undefined", async () => {
147+
const appId = "test-app-2";
148+
const appSlug = "test-app-2";
149+
const customerName = "UndefinedFieldTest456";
150+
const expectedApplications = {
151+
apps: [{ id: appId, name: "Test App 2", slug: appSlug }]
152+
};
153+
const customersResponse = {};
154+
155+
const appsMock = mockServer.forGet("/apps").thenReply(200, JSON.stringify(expectedApplications));
156+
const customersMock = mockServer.forGet(`/app/${appId}/customers`)
157+
.withQuery({ name: customerName })
158+
.once()
159+
.thenReply(200, JSON.stringify(customersResponse));
160+
161+
await appsMock;
162+
await customersMock;
163+
164+
const customers: CustomerSummary[] = await listCustomersByName(apiClient, appSlug, customerName);
165+
expect(customers).toHaveLength(0);
166+
});
167+
168+
it("should properly URL encode customer name", async () => {
169+
const appId = "test-app-encode";
170+
const appSlug = "test-app-encode";
171+
const expectedApplications = {
172+
apps: [{ id: appId, name: "Test App Encode", slug: appSlug }]
173+
};
174+
const customersResponse = {
175+
customers: [{ id: "customer-1", name: "Customer & Co" }]
176+
};
177+
178+
await mockServer.forGet("/apps").once().thenReply(200, JSON.stringify(expectedApplications));
179+
await mockServer.forGet(`/app/${appId}/customers`).withQuery({ name: "Customer & Co" }).once().thenReply(200, JSON.stringify(customersResponse));
180+
181+
const customers: CustomerSummary[] = await listCustomersByName(apiClient, appSlug, "Customer & Co");
182+
expect(customers).toHaveLength(1);
183+
expect(customers[0].name).toEqual("Customer & Co");
184+
expect(customers[0].customerId).toEqual("customer-1");
185+
});
186+
187+
it("should throw error when API returns non-200 status", async () => {
188+
const appId = "test-app-3";
189+
const appSlug = "test-app-3";
190+
const customerName = "ErrorTest789";
191+
const expectedApplications = {
192+
apps: [{ id: appId, name: "Test App 3", slug: appSlug }]
193+
};
194+
195+
const appsMock = mockServer.forGet("/apps").thenReply(200, JSON.stringify(expectedApplications));
196+
const customersMock = mockServer.forGet(`/app/${appId}/customers`)
197+
.withQuery({ name: customerName })
198+
.once()
199+
.thenReply(500, JSON.stringify({ error: "Internal Server Error" }));
200+
201+
await appsMock;
202+
await customersMock;
203+
204+
await expect(listCustomersByName(apiClient, appSlug, customerName)).rejects.toThrow("Failed to list customers: Server responded with 500");
205+
});
206+
});

src/customers.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ export async function archiveCustomer(vendorPortalApi: VendorPortalApi, customer
113113
}
114114
}
115115

116-
117116
export async function getUsedKubernetesDistributions(vendorPortalApi: VendorPortalApi, appSlug: string): Promise<KubernetesDistribution[]> {
118117
const http = await vendorPortalApi.client();
119118

0 commit comments

Comments
 (0)