@dk/jolly 0.1.5 → 0.1.7
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/bun.lock +59 -1
- package/dist/bootstrap.js +42 -19
- package/dist/index.js +91 -68
- package/package.json +6 -6
- package/src/api/auth.ts +1 -1
- package/src/api/client.ts +93 -20
- package/src/commands/app.ts +26 -26
- package/src/commands/store.ts +23 -23
- package/src/test/command-handlers.test.ts +34 -29
- package/src/test/e2e-flows.test.ts +50 -31
- package/src/test/entry-points.test.ts +4 -1
- package/src/test/error-handling.test.ts +8 -8
- package/src/test/mocks.ts +55 -15
|
@@ -50,7 +50,10 @@ describe('Entry Points', () => {
|
|
|
50
50
|
When('bootstrap calls createStore', () => {
|
|
51
51
|
Then('it should pass project name and default region', async () => {
|
|
52
52
|
withToken();
|
|
53
|
-
mockFetch({
|
|
53
|
+
mockFetch({
|
|
54
|
+
'/organizations': { organizations: [fixtures.organization] },
|
|
55
|
+
'/organizations/my-org/projects': { project: fixtures.project },
|
|
56
|
+
});
|
|
54
57
|
|
|
55
58
|
const { createStore } = await import('../commands/store');
|
|
56
59
|
await createStore('my-project', 'us-east-1');
|
|
@@ -76,7 +76,7 @@ describe('Error Handling', () => {
|
|
|
76
76
|
const { SaleorCloudClient } = await import('../api/client');
|
|
77
77
|
const client = new SaleorCloudClient(fixtures.token);
|
|
78
78
|
|
|
79
|
-
await expect(client.
|
|
79
|
+
await expect(client.getOrganizations()).rejects.toThrow('401');
|
|
80
80
|
});
|
|
81
81
|
});
|
|
82
82
|
|
|
@@ -87,7 +87,7 @@ describe('Error Handling', () => {
|
|
|
87
87
|
const { SaleorCloudClient } = await import('../api/client');
|
|
88
88
|
const client = new SaleorCloudClient(fixtures.token);
|
|
89
89
|
|
|
90
|
-
await expect(client.
|
|
90
|
+
await expect(client.createProject('test-org', 'test', 'us-east-1')).rejects.toThrow('403');
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
|
|
@@ -98,7 +98,7 @@ describe('Error Handling', () => {
|
|
|
98
98
|
const { SaleorCloudClient } = await import('../api/client');
|
|
99
99
|
const client = new SaleorCloudClient(fixtures.token);
|
|
100
100
|
|
|
101
|
-
await expect(client.getEnvironments('
|
|
101
|
+
await expect(client.getEnvironments('test-org', 'test-project')).rejects.toThrow('500');
|
|
102
102
|
});
|
|
103
103
|
});
|
|
104
104
|
|
|
@@ -109,7 +109,7 @@ describe('Error Handling', () => {
|
|
|
109
109
|
const { SaleorCloudClient } = await import('../api/client');
|
|
110
110
|
const client = new SaleorCloudClient(fixtures.token);
|
|
111
111
|
|
|
112
|
-
await expect(client.createEnvironment('bad-
|
|
112
|
+
await expect(client.createEnvironment('bad-org', 'bad-project', 'staging', 'us-east-1')).rejects.toThrow('404');
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
});
|
|
@@ -118,17 +118,17 @@ describe('Error Handling', () => {
|
|
|
118
118
|
describe('API Request Headers', () => {
|
|
119
119
|
Given('a SaleorCloudClient with a token', () => {
|
|
120
120
|
When('making any request', () => {
|
|
121
|
-
Then('it should include Authorization
|
|
121
|
+
Then('it should include Authorization Token header', async () => {
|
|
122
122
|
const fetchMock = mockFetch({
|
|
123
|
-
'/
|
|
123
|
+
'/organizations': { organizations: [] },
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
const { SaleorCloudClient } = await import('../api/client');
|
|
127
127
|
const client = new SaleorCloudClient(fixtures.token);
|
|
128
|
-
await client.
|
|
128
|
+
await client.getOrganizations();
|
|
129
129
|
|
|
130
130
|
const [, opts] = fetchMock.mock.calls[0];
|
|
131
|
-
expect(opts.headers.Authorization).toBe(`
|
|
131
|
+
expect(opts.headers.Authorization).toBe(`Token ${fixtures.token}`);
|
|
132
132
|
expect(opts.headers['Content-Type']).toBe('application/json');
|
|
133
133
|
});
|
|
134
134
|
});
|
package/src/test/mocks.ts
CHANGED
|
@@ -1,44 +1,84 @@
|
|
|
1
1
|
import { mock, spyOn } from 'bun:test';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Organization, Project, Environment, App } from '../api/client';
|
|
3
3
|
|
|
4
4
|
export const fixtures = {
|
|
5
5
|
token: 'test-token-abc123',
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// New API structure: Organizations → Projects → Environments
|
|
8
|
+
organization: {
|
|
9
|
+
slug: 'my-org',
|
|
10
|
+
name: 'My Organization',
|
|
11
|
+
created: '2025-01-01T00:00:00Z',
|
|
12
|
+
owner_email: 'owner@example.com',
|
|
13
|
+
company_name: 'My Company',
|
|
14
|
+
} satisfies Organization,
|
|
15
|
+
|
|
16
|
+
organization2: {
|
|
17
|
+
slug: 'other-org',
|
|
18
|
+
name: 'Other Organization',
|
|
19
|
+
created: '2025-06-15T00:00:00Z',
|
|
20
|
+
owner_email: 'other@example.com',
|
|
21
|
+
} satisfies Organization,
|
|
22
|
+
|
|
23
|
+
project: {
|
|
24
|
+
slug: 'my-store',
|
|
9
25
|
name: 'my-store',
|
|
10
26
|
region: 'us-east-1',
|
|
11
|
-
|
|
12
|
-
|
|
27
|
+
created: '2025-01-01T00:00:00Z',
|
|
28
|
+
sandboxes: { count: 2 },
|
|
29
|
+
} satisfies Project,
|
|
13
30
|
|
|
14
|
-
|
|
15
|
-
|
|
31
|
+
project2: {
|
|
32
|
+
slug: 'other-store',
|
|
16
33
|
name: 'other-store',
|
|
17
34
|
region: 'eu-west-1',
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
created: '2025-06-15T00:00:00Z',
|
|
36
|
+
sandboxes: { count: 1 },
|
|
37
|
+
} satisfies Project,
|
|
20
38
|
|
|
21
39
|
environment: {
|
|
22
|
-
|
|
40
|
+
key: 'staging',
|
|
23
41
|
name: 'staging',
|
|
24
|
-
|
|
25
|
-
|
|
42
|
+
domain: 'staging-my-store.saleor.cloud',
|
|
43
|
+
service: {
|
|
44
|
+
version: '3.15.0',
|
|
45
|
+
type: 'main',
|
|
46
|
+
region: 'us-east-1',
|
|
47
|
+
},
|
|
48
|
+
created: '2025-01-02T00:00:00Z',
|
|
49
|
+
project: { name: 'my-store', slug: 'my-store' },
|
|
26
50
|
} satisfies Environment,
|
|
27
51
|
|
|
28
52
|
app: {
|
|
29
53
|
id: 'app-1',
|
|
30
54
|
name: 'my-app',
|
|
31
55
|
type: 'payment',
|
|
32
|
-
environment_id: '
|
|
56
|
+
environment_id: 'staging',
|
|
33
57
|
} satisfies App,
|
|
58
|
+
|
|
59
|
+
// Backward compat aliases (for tests that haven't been migrated yet)
|
|
60
|
+
store: {
|
|
61
|
+
id: 'my-org',
|
|
62
|
+
name: 'My Organization',
|
|
63
|
+
region: 'us-east-1',
|
|
64
|
+
created_at: '2025-01-01T00:00:00Z',
|
|
65
|
+
},
|
|
66
|
+
store2: {
|
|
67
|
+
id: 'other-org',
|
|
68
|
+
name: 'Other Organization',
|
|
69
|
+
region: 'eu-west-1',
|
|
70
|
+
created_at: '2025-06-15T00:00:00Z',
|
|
71
|
+
},
|
|
34
72
|
};
|
|
35
73
|
|
|
36
74
|
export function mockFetch(routes: Record<string, unknown>): ReturnType<typeof mock> {
|
|
37
75
|
const handler = mock((url: string | URL | Request, init?: RequestInit) => {
|
|
38
76
|
const urlStr = typeof url === 'string' ? url : url instanceof URL ? url.toString() : url.url;
|
|
39
77
|
|
|
40
|
-
|
|
41
|
-
|
|
78
|
+
const sortedEntries = Object.entries(routes).sort((a, b) => b[0].length - a[0].length);
|
|
79
|
+
|
|
80
|
+
for (const [pattern, body] of sortedEntries) {
|
|
81
|
+
if (urlStr.endsWith(pattern)) {
|
|
42
82
|
return Promise.resolve(new Response(JSON.stringify(body), {
|
|
43
83
|
status: 200,
|
|
44
84
|
headers: { 'Content-Type': 'application/json' },
|