quickbase-js 0.1.0-beta.13 → 0.1.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/esm/quickbase.d.ts +2 -1
- package/package.json +9 -4
- package/CHANGELOG.md +0 -239
- package/build-common.js +0 -131
- package/build-esm.js +0 -71
- package/build-umd.js +0 -69
- package/docs/.vitepress/cache/deps/@theme_index.js +0 -275
- package/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
- package/docs/.vitepress/cache/deps/_metadata.json +0 -40
- package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js +0 -12542
- package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js.map +0 -7
- package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js +0 -9719
- package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js.map +0 -7
- package/docs/.vitepress/cache/deps/package.json +0 -3
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4504
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -583
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
- package/docs/.vitepress/cache/deps/vue.js +0 -343
- package/docs/.vitepress/cache/deps/vue.js.map +0 -7
- package/docs/.vitepress/config.mts +0 -26
- package/docs/api-examples.md +0 -49
- package/docs/index.md +0 -59
- package/docs/markdown-examples.md +0 -85
- package/docs-data/api-docs.json +0 -4143
- package/examples/quicbase-jsCDN.html +0 -36
- package/examples/react.js +0 -48
- package/examples/vanillajs.html +0 -47
- package/index.md +0 -25
- package/open-api/fix-spec-main.ts +0 -133
- package/open-api/generate-unified-interface.ts +0 -104
- package/open-api/generateDocsJson.ts +0 -24
- package/open-api/output/quickbase-fixed.json +0 -11191
- package/open-api/post-process-generated.ts +0 -226
- package/open-api/regenerate-client.ts +0 -117
- package/open-api/schema/enhance-general.ts +0 -111
- package/open-api/schema/fix-arrays.ts +0 -68
- package/open-api/schema/tags/apps.ts +0 -90
- package/open-api/schema/tags/fields.ts +0 -471
- package/open-api/schema/tags/groups.ts +0 -51
- package/open-api/schema/tags/index.ts +0 -66
- package/open-api/schema/tags/records.ts +0 -115
- package/open-api/schema/tags/tables.ts +0 -211
- package/open-api/schema/tags/users.ts +0 -47
- package/open-api/types/spec.ts +0 -42
- package/open-api/utils/common.ts +0 -29
- package/open-api/utils/generateJsDoc.ts +0 -74
- package/open-api/utils/infer-schema.ts +0 -40
- package/open-api/utils/naming.ts +0 -10
- package/open-api/utils/sharedUtils.ts +0 -352
- package/playwright.config.ts +0 -37
- package/rollup.config.js +0 -114
- package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
- package/specs/split/apps.json +0 -1315
- package/specs/split/auth.json +0 -191
- package/specs/split/fields.json +0 -3869
- package/specs/split/records.json +0 -754
- package/specs/split/reports.json +0 -619
- package/specs/split/tables.json +0 -1605
- package/src/BurstAwareThrottleBucket.ts +0 -57
- package/src/FlowThrottleBucket.ts +0 -47
- package/src/RateLimitError.ts +0 -12
- package/src/RateThrottleBucket.ts +0 -5
- package/src/Semaphore.ts +0 -33
- package/src/authorizationStrategy.ts +0 -321
- package/src/generated-unified/QuickbaseClient.ts +0 -1135
- package/src/generated-unified/missing-types-report.json +0 -3
- package/src/index.ts +0 -1
- package/src/invokeMethod.ts +0 -290
- package/src/pagination.ts +0 -429
- package/src/quickbaseClient.ts +0 -227
- package/src/rateLimiter.ts +0 -30
- package/src/tokenCache.ts +0 -39
- package/src/utils.ts +0 -50
- package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -159
- package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -219
- package/tests/playwright/qb/auth/getAppWithTempToken.test.ts +0 -162
- package/tests/playwright/qb/auth/getAppWithTempTokenConcurrency.test.ts +0 -208
- package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -153
- package/tests/playwright/qb/auth/getTempToken.test.ts +0 -152
- package/tests/playwright/qb/auth/tempTokenPrefetch.test.ts +0 -179
- package/tests/playwright/qb/auth/tempTokenRenewal.test.ts +0 -133
- package/tests/setup.ts +0 -53
- package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
- package/tests/vitest/qb/apps/createApp.test.ts +0 -64
- package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
- package/tests/vitest/qb/apps/getApp.test.ts +0 -44
- package/tests/vitest/qb/apps/getAppEvents.test.ts +0 -67
- package/tests/vitest/qb/apps/updateApp.test.ts +0 -58
- package/tests/vitest/qb/auth/mockQuickbaseServer.ts +0 -60
- package/tests/vitest/qb/auth/retryUserToken401.test.ts +0 -73
- package/tests/vitest/qb/auth/ssoTokenConcurrency.test.ts +0 -68
- package/tests/vitest/qb/auth/ssoTokenIntegrationWithServer.test.ts +0 -65
- package/tests/vitest/qb/auth/userTokenConcurrency.test.ts +0 -63
- package/tests/vitest/qb/fields/createField.test.ts +0 -77
- package/tests/vitest/qb/fields/deleteFields.test.ts +0 -83
- package/tests/vitest/qb/fields/getField.test.ts +0 -85
- package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -82
- package/tests/vitest/qb/fields/getFields.test.ts +0 -232
- package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
- package/tests/vitest/qb/fields/updateField.test.ts +0 -93
- package/tests/vitest/qb/formulas/runFormula.test.ts +0 -96
- package/tests/vitest/qb/index.ts +0 -29
- package/tests/vitest/qb/quickbase-js/BurstAwareThrottleBucket.test.ts +0 -125
- package/tests/vitest/qb/quickbase-js/FlowBucket.test.ts +0 -77
- package/tests/vitest/qb/quickbase-js/paginationSkip.test.ts +0 -111
- package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
- package/tests/vitest/qb/records/runQuery.test.ts +0 -145
- package/tests/vitest/qb/records/upsert.test.ts +0 -102
- package/tests/vitest/qb/tables/createRelationship.test.ts +0 -102
- package/tests/vitest/qb/tables/createTable.test.ts +0 -55
- package/tests/vitest/qb/tables/deleteRelationship.test.ts +0 -143
- package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
- package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
- package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
- package/tests/vitest/qb/tables/getTable.test.ts +0 -26
- package/tests/vitest/qb/tables/updateRelationship.test.ts +0 -250
- package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
- package/tests/vitest/unit/apps/copyApp.test.ts +0 -581
- package/tests/vitest/unit/apps/createApp.test.ts +0 -186
- package/tests/vitest/unit/apps/deleteApp.test.ts +0 -216
- package/tests/vitest/unit/apps/getApp.test.ts +0 -128
- package/tests/vitest/unit/apps/getAppConcurrency.test.ts +0 -151
- package/tests/vitest/unit/apps/getAppEvents.test.ts +0 -193
- package/tests/vitest/unit/apps/updateApp.test.ts +0 -412
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -81
- package/tests/vitest/unit/auth/getTempToken.test.ts +0 -119
- package/tests/vitest/unit/auth/retryTempToken401.test.ts +0 -95
- package/tests/vitest/unit/auth/retryTempTokenMaxRetries.test.ts +0 -206
- package/tests/vitest/unit/auth/retryUserToken401.test.ts +0 -66
- package/tests/vitest/unit/auth/ssoTokenRefresh.test.ts +0 -325
- package/tests/vitest/unit/auth/userTokenConcurrency.test.ts +0 -62
- package/tests/vitest/unit/fields/createField.test.ts +0 -451
- package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
- package/tests/vitest/unit/fields/getField.test.ts +0 -189
- package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -180
- package/tests/vitest/unit/fields/getFields.test.ts +0 -122
- package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
- package/tests/vitest/unit/fields/updateField.test.ts +0 -285
- package/tests/vitest/unit/formulas/runFormula.test.ts +0 -205
- package/tests/vitest/unit/index.ts +0 -34
- package/tests/vitest/unit/quickbase-js/BurstAwareThrottleBucket.test.ts +0 -108
- package/tests/vitest/unit/quickbase-js/FlowBucket.test.ts +0 -101
- package/tests/vitest/unit/quickbase-js/pagination.test.ts +0 -251
- package/tests/vitest/unit/quickbase-js/quickbaseClientHttpMethods.test.ts +0 -141
- package/tests/vitest/unit/quickbase-js/rateLimit.test.ts +0 -191
- package/tests/vitest/unit/quickbase-js/tokenLifespan.test.ts +0 -204
- package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
- package/tests/vitest/unit/records/runQuery.test.ts +0 -101
- package/tests/vitest/unit/records/upsert.test.ts +0 -234
- package/tests/vitest/unit/tables/createRelationship.test.ts +0 -212
- package/tests/vitest/unit/tables/createTable.test.ts +0 -70
- package/tests/vitest/unit/tables/deleteRelationship.test.ts +0 -97
- package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
- package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
- package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
- package/tests/vitest/unit/tables/getTable.test.ts +0 -233
- package/tests/vitest/unit/tables/updateRelationship.test.ts +0 -307
- package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
- package/tools/log-gen.ts +0 -251
- package/tools/log-gen.yaml +0 -4829
- package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
- package/tsconfig.build.json +0 -17
- package/tsconfig.json +0 -32
- package/versionrc.json +0 -9
- package/vitest.config.ts +0 -27
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
// tests/vitest/unit/apps/createApp.test.ts
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
createClient,
|
|
6
|
-
mockFetch,
|
|
7
|
-
QB_REALM,
|
|
8
|
-
QB_USER_TOKEN,
|
|
9
|
-
} from "@tests/setup.ts";
|
|
10
|
-
import { CreateAppRequest, CreateApp200Response } from "@/generated/models";
|
|
11
|
-
|
|
12
|
-
describe("QuickbaseClient Unit - createApp", () => {
|
|
13
|
-
console.log(
|
|
14
|
-
"Running updated createApp.test.ts - Version with full request expectation"
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
let client: ReturnType<typeof createClient>;
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
mockFetch.mockClear();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("initializes without errors", () => {
|
|
24
|
-
client = createClient(mockFetch, { debug: true });
|
|
25
|
-
expect(client).toBeDefined();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("has createApp method", () => {
|
|
29
|
-
client = createClient(mockFetch, { debug: true });
|
|
30
|
-
expect(typeof client.createApp).toBe("function");
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("calls createApp successfully with user token and dates as Date objects", async () => {
|
|
34
|
-
client = createClient(mockFetch, { debug: true });
|
|
35
|
-
|
|
36
|
-
const request: CreateAppRequest = {
|
|
37
|
-
name: "New App",
|
|
38
|
-
description: "A new app for testing",
|
|
39
|
-
assignToken: true,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const mockResponse: CreateApp200Response = {
|
|
43
|
-
id: "new-app-id",
|
|
44
|
-
name: "New App",
|
|
45
|
-
description: "A new app for testing",
|
|
46
|
-
created: new Date("2025-03-11T10:00:00Z"),
|
|
47
|
-
updated: new Date("2025-03-11T10:00:00Z"),
|
|
48
|
-
dateFormat: "MM-DD-YYYY",
|
|
49
|
-
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
50
|
-
hasEveryoneOnTheInternet: false,
|
|
51
|
-
variables: [],
|
|
52
|
-
dataClassification: "None",
|
|
53
|
-
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
54
|
-
securityProperties: {
|
|
55
|
-
allowClone: false,
|
|
56
|
-
allowExport: true,
|
|
57
|
-
enableAppTokens: true,
|
|
58
|
-
hideFromPublic: false,
|
|
59
|
-
mustBeRealmApproved: false,
|
|
60
|
-
useIPFilter: false,
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
mockFetch.mockResolvedValueOnce({
|
|
65
|
-
ok: true,
|
|
66
|
-
status: 200,
|
|
67
|
-
json: () => Promise.resolve(mockResponse),
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const result = await client.createApp({ body: request });
|
|
71
|
-
|
|
72
|
-
expect(result).toEqual(mockResponse);
|
|
73
|
-
const callArgs = mockFetch.mock.calls[0];
|
|
74
|
-
const body = JSON.parse(callArgs[1].body as string);
|
|
75
|
-
console.log("Date objects test - Expected request:", request);
|
|
76
|
-
console.log("Date objects test - Actual body:", body);
|
|
77
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
78
|
-
`https://api.quickbase.com/v1/apps`,
|
|
79
|
-
expect.objectContaining({
|
|
80
|
-
method: "POST",
|
|
81
|
-
headers: expect.objectContaining({
|
|
82
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
83
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
84
|
-
"Content-Type": "application/json",
|
|
85
|
-
}),
|
|
86
|
-
body: expect.any(String), // Ensure it’s a string, we’ll check content below
|
|
87
|
-
credentials: "omit",
|
|
88
|
-
})
|
|
89
|
-
);
|
|
90
|
-
expect(body).toEqual(request); // Moved outside toHaveBeenCalledWith
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("calls createApp successfully with user token and dates as strings", async () => {
|
|
94
|
-
client = createClient(mockFetch, { debug: true, convertDates: false });
|
|
95
|
-
|
|
96
|
-
const request: CreateAppRequest = {
|
|
97
|
-
name: "New App",
|
|
98
|
-
description: "A new app for testing",
|
|
99
|
-
assignToken: true,
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const mockResponse = {
|
|
103
|
-
id: "new-app-id",
|
|
104
|
-
name: "New App",
|
|
105
|
-
description: "A new app for testing",
|
|
106
|
-
created: "2025-03-11T10:00:00Z",
|
|
107
|
-
updated: "2025-03-11T10:00:00Z",
|
|
108
|
-
dateFormat: "MM-DD-YYYY",
|
|
109
|
-
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
110
|
-
hasEveryoneOnTheInternet: false,
|
|
111
|
-
variables: [],
|
|
112
|
-
dataClassification: "None",
|
|
113
|
-
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
114
|
-
securityProperties: {
|
|
115
|
-
allowClone: false,
|
|
116
|
-
allowExport: true,
|
|
117
|
-
enableAppTokens: true,
|
|
118
|
-
hideFromPublic: false,
|
|
119
|
-
mustBeRealmApproved: false,
|
|
120
|
-
useIPFilter: false,
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
mockFetch.mockResolvedValueOnce({
|
|
125
|
-
ok: true,
|
|
126
|
-
status: 200,
|
|
127
|
-
json: () => Promise.resolve(mockResponse),
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const result = await client.createApp({ body: request });
|
|
131
|
-
|
|
132
|
-
expect(result).toEqual(mockResponse);
|
|
133
|
-
const callArgs = mockFetch.mock.calls[0];
|
|
134
|
-
const body = JSON.parse(callArgs[1].body as string);
|
|
135
|
-
console.log("Strings test - Expected request:", request);
|
|
136
|
-
console.log("Strings test - Actual body:", body);
|
|
137
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
138
|
-
`https://api.quickbase.com/v1/apps`,
|
|
139
|
-
expect.objectContaining({
|
|
140
|
-
method: "POST",
|
|
141
|
-
headers: expect.objectContaining({
|
|
142
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
143
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
144
|
-
"Content-Type": "application/json",
|
|
145
|
-
}),
|
|
146
|
-
body: expect.any(String), // Ensure it’s a string, we’ll check content below
|
|
147
|
-
credentials: "omit",
|
|
148
|
-
})
|
|
149
|
-
);
|
|
150
|
-
expect(body).toEqual(request); // Moved outside toHaveBeenCalledWith
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("handles 400 error for invalid request", async () => {
|
|
154
|
-
client = createClient(mockFetch, { debug: true });
|
|
155
|
-
|
|
156
|
-
const request: CreateAppRequest = {
|
|
157
|
-
name: "",
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
mockFetch.mockImplementationOnce(() =>
|
|
161
|
-
Promise.resolve({
|
|
162
|
-
ok: false,
|
|
163
|
-
status: 400,
|
|
164
|
-
json: () => Promise.resolve({ message: "Name is required" }),
|
|
165
|
-
})
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
await expect(client.createApp({ body: request })).rejects.toThrow(
|
|
169
|
-
"API Error: Name is required (Status: 400)"
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
173
|
-
`https://api.quickbase.com/v1/apps`,
|
|
174
|
-
expect.objectContaining({
|
|
175
|
-
method: "POST",
|
|
176
|
-
headers: expect.objectContaining({
|
|
177
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
178
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
179
|
-
"Content-Type": "application/json",
|
|
180
|
-
}),
|
|
181
|
-
body: JSON.stringify(request),
|
|
182
|
-
credentials: "omit",
|
|
183
|
-
})
|
|
184
|
-
);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
// tests/vitest/unit/apps/deleteApp.test.ts
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
createClient,
|
|
6
|
-
mockFetch,
|
|
7
|
-
QB_APP_ID,
|
|
8
|
-
QB_REALM,
|
|
9
|
-
QB_USER_TOKEN,
|
|
10
|
-
} from "@tests/setup.ts";
|
|
11
|
-
import { DeleteAppRequest, DeleteApp200Response } from "@/generated/models";
|
|
12
|
-
|
|
13
|
-
describe("QuickbaseClient Unit - deleteApp", () => {
|
|
14
|
-
let client: ReturnType<typeof createClient>;
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
mockFetch.mockClear();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("initializes without errors", () => {
|
|
21
|
-
client = createClient(mockFetch, { debug: true });
|
|
22
|
-
expect(client).toBeDefined();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("has deleteApp method", () => {
|
|
26
|
-
client = createClient(mockFetch, { debug: true });
|
|
27
|
-
expect(typeof client.deleteApp).toBe("function");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("calls deleteApp successfully with user token", async () => {
|
|
31
|
-
client = createClient(mockFetch, { debug: true });
|
|
32
|
-
|
|
33
|
-
const request: DeleteAppRequest = {
|
|
34
|
-
name: "App to Delete",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const mockResponse: DeleteApp200Response = {
|
|
38
|
-
deletedAppId: QB_APP_ID,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
mockFetch.mockResolvedValueOnce({
|
|
42
|
-
ok: true,
|
|
43
|
-
status: 200,
|
|
44
|
-
json: () => Promise.resolve(mockResponse),
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
|
|
48
|
-
|
|
49
|
-
expect(result).toEqual(mockResponse);
|
|
50
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
51
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
52
|
-
expect.objectContaining({
|
|
53
|
-
method: "DELETE",
|
|
54
|
-
headers: expect.objectContaining({
|
|
55
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
56
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
57
|
-
"Content-Type": "application/json",
|
|
58
|
-
}),
|
|
59
|
-
body: JSON.stringify(request),
|
|
60
|
-
})
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("calls deleteApp successfully with temp token", async () => {
|
|
65
|
-
client = createClient(mockFetch, { useTempTokens: true, debug: true });
|
|
66
|
-
|
|
67
|
-
const request: DeleteAppRequest = {
|
|
68
|
-
name: "App to Delete with Temp Token",
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const mockResponse: DeleteApp200Response = {
|
|
72
|
-
deletedAppId: QB_APP_ID,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
mockFetch
|
|
76
|
-
.mockResolvedValueOnce({
|
|
77
|
-
ok: true,
|
|
78
|
-
status: 200,
|
|
79
|
-
json: () => Promise.resolve({ temporaryAuthorization: "temp_token" }),
|
|
80
|
-
})
|
|
81
|
-
.mockResolvedValueOnce({
|
|
82
|
-
ok: true,
|
|
83
|
-
status: 200,
|
|
84
|
-
json: () => Promise.resolve(mockResponse),
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
|
|
88
|
-
|
|
89
|
-
expect(result).toEqual(mockResponse);
|
|
90
|
-
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
91
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
92
|
-
1,
|
|
93
|
-
`https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
|
|
94
|
-
expect.objectContaining({
|
|
95
|
-
method: "GET",
|
|
96
|
-
headers: expect.objectContaining({
|
|
97
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
98
|
-
"Content-Type": "application/json",
|
|
99
|
-
}),
|
|
100
|
-
credentials: "include",
|
|
101
|
-
})
|
|
102
|
-
);
|
|
103
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
104
|
-
2,
|
|
105
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
106
|
-
expect.objectContaining({
|
|
107
|
-
method: "DELETE",
|
|
108
|
-
headers: expect.objectContaining({
|
|
109
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
110
|
-
Authorization: "QB-TEMP-TOKEN temp_token",
|
|
111
|
-
"Content-Type": "application/json",
|
|
112
|
-
}),
|
|
113
|
-
body: JSON.stringify(request),
|
|
114
|
-
})
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("retries successfully after 401 with temp token", async () => {
|
|
119
|
-
client = createClient(mockFetch, { useTempTokens: true, debug: true });
|
|
120
|
-
|
|
121
|
-
const request: DeleteAppRequest = {
|
|
122
|
-
name: "Retry Delete App",
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const mockResponse: DeleteApp200Response = {
|
|
126
|
-
deletedAppId: QB_APP_ID,
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
mockFetch
|
|
130
|
-
.mockResolvedValueOnce({
|
|
131
|
-
ok: true,
|
|
132
|
-
status: 200,
|
|
133
|
-
json: () =>
|
|
134
|
-
Promise.resolve({ temporaryAuthorization: "initial_token" }),
|
|
135
|
-
})
|
|
136
|
-
.mockResolvedValueOnce({
|
|
137
|
-
ok: false,
|
|
138
|
-
status: 401,
|
|
139
|
-
json: () => Promise.resolve({ message: "Unauthorized" }),
|
|
140
|
-
})
|
|
141
|
-
.mockResolvedValueOnce({
|
|
142
|
-
ok: true,
|
|
143
|
-
status: 200,
|
|
144
|
-
json: () => Promise.resolve({ temporaryAuthorization: "new_token" }),
|
|
145
|
-
})
|
|
146
|
-
.mockResolvedValueOnce({
|
|
147
|
-
ok: true,
|
|
148
|
-
status: 200,
|
|
149
|
-
json: () => Promise.resolve(mockResponse),
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
|
|
153
|
-
|
|
154
|
-
expect(result).toEqual(mockResponse);
|
|
155
|
-
expect(mockFetch).toHaveBeenCalledTimes(4);
|
|
156
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
157
|
-
1,
|
|
158
|
-
`https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
|
|
159
|
-
expect.any(Object)
|
|
160
|
-
);
|
|
161
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
162
|
-
2,
|
|
163
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
164
|
-
expect.objectContaining({
|
|
165
|
-
headers: expect.objectContaining({
|
|
166
|
-
Authorization: "QB-TEMP-TOKEN initial_token",
|
|
167
|
-
}),
|
|
168
|
-
})
|
|
169
|
-
);
|
|
170
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
171
|
-
3,
|
|
172
|
-
`https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
|
|
173
|
-
expect.any(Object)
|
|
174
|
-
);
|
|
175
|
-
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
176
|
-
4,
|
|
177
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
178
|
-
expect.objectContaining({
|
|
179
|
-
headers: expect.objectContaining({
|
|
180
|
-
Authorization: "QB-TEMP-TOKEN new_token",
|
|
181
|
-
}),
|
|
182
|
-
})
|
|
183
|
-
);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it("handles 400 error for invalid request", async () => {
|
|
187
|
-
client = createClient(mockFetch, { debug: true });
|
|
188
|
-
|
|
189
|
-
const request: DeleteAppRequest = {
|
|
190
|
-
name: "Wrong Name",
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
mockFetch.mockResolvedValueOnce({
|
|
194
|
-
ok: false,
|
|
195
|
-
status: 400,
|
|
196
|
-
json: () => Promise.resolve({ message: "Invalid application name" }),
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
await expect(
|
|
200
|
-
client.deleteApp({ appId: QB_APP_ID, body: request })
|
|
201
|
-
).rejects.toThrow("API Error: Invalid application name (Status: 400)");
|
|
202
|
-
|
|
203
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
204
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
205
|
-
expect.objectContaining({
|
|
206
|
-
method: "DELETE",
|
|
207
|
-
headers: expect.objectContaining({
|
|
208
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
209
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
210
|
-
"Content-Type": "application/json",
|
|
211
|
-
}),
|
|
212
|
-
body: JSON.stringify(request),
|
|
213
|
-
})
|
|
214
|
-
);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// tests/vitest/unit/apps/getApp.test.ts
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
createClient,
|
|
6
|
-
mockFetch,
|
|
7
|
-
QB_APP_ID,
|
|
8
|
-
QB_REALM,
|
|
9
|
-
QB_USER_TOKEN,
|
|
10
|
-
} from "@tests/setup.ts";
|
|
11
|
-
|
|
12
|
-
describe("QuickbaseClient Unit - getApp", () => {
|
|
13
|
-
let client: ReturnType<typeof createClient>;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mockFetch.mockClear();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("initializes without errors", () => {
|
|
20
|
-
client = createClient(mockFetch, { debug: true });
|
|
21
|
-
expect(client).toBeDefined();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("has getApp method", () => {
|
|
25
|
-
client = createClient(mockFetch, { debug: true });
|
|
26
|
-
expect(typeof client.getApp).toBe("function");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("calls getApp successfully with dates as Date objects", async () => {
|
|
30
|
-
client = createClient(mockFetch, { debug: true });
|
|
31
|
-
|
|
32
|
-
const mockResponse = {
|
|
33
|
-
id: QB_APP_ID,
|
|
34
|
-
name: "qb-copy",
|
|
35
|
-
created: new Date("2025-02-13T18:22:33Z"), // Expect Date object
|
|
36
|
-
updated: new Date("2025-03-04T04:25:51Z"), // Expect Date object
|
|
37
|
-
description: "",
|
|
38
|
-
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
39
|
-
dateFormat: "MM-DD-YYYY",
|
|
40
|
-
hasEveryoneOnTheInternet: false,
|
|
41
|
-
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
42
|
-
securityProperties: {
|
|
43
|
-
allowClone: false,
|
|
44
|
-
allowExport: true,
|
|
45
|
-
enableAppTokens: true,
|
|
46
|
-
hideFromPublic: false,
|
|
47
|
-
mustBeRealmApproved: false,
|
|
48
|
-
useIPFilter: false,
|
|
49
|
-
},
|
|
50
|
-
ancestorId: undefined,
|
|
51
|
-
variables: undefined,
|
|
52
|
-
dataClassification: undefined,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
mockFetch.mockResolvedValueOnce({
|
|
56
|
-
ok: true,
|
|
57
|
-
status: 200,
|
|
58
|
-
json: () => Promise.resolve(mockResponse),
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const result = await client.getApp({ appId: QB_APP_ID });
|
|
62
|
-
|
|
63
|
-
expect(result).toEqual(mockResponse);
|
|
64
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
65
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
66
|
-
expect.objectContaining({
|
|
67
|
-
method: "GET",
|
|
68
|
-
headers: expect.objectContaining({
|
|
69
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
70
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
71
|
-
"Content-Type": "application/json",
|
|
72
|
-
}),
|
|
73
|
-
body: undefined,
|
|
74
|
-
credentials: "omit",
|
|
75
|
-
})
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("calls getApp successfully with dates as strings", async () => {
|
|
80
|
-
client = createClient(mockFetch, { debug: true, convertDates: false });
|
|
81
|
-
|
|
82
|
-
const mockResponse = {
|
|
83
|
-
id: QB_APP_ID,
|
|
84
|
-
name: "qb-copy",
|
|
85
|
-
created: "2025-02-13T18:22:33Z", // Expect string
|
|
86
|
-
updated: "2025-03-04T04:25:51Z", // Expect string
|
|
87
|
-
description: "",
|
|
88
|
-
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
89
|
-
dateFormat: "MM-DD-YYYY",
|
|
90
|
-
hasEveryoneOnTheInternet: false,
|
|
91
|
-
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
92
|
-
securityProperties: {
|
|
93
|
-
allowClone: false,
|
|
94
|
-
allowExport: true,
|
|
95
|
-
enableAppTokens: true,
|
|
96
|
-
hideFromPublic: false,
|
|
97
|
-
mustBeRealmApproved: false,
|
|
98
|
-
useIPFilter: false,
|
|
99
|
-
},
|
|
100
|
-
ancestorId: undefined,
|
|
101
|
-
variables: undefined,
|
|
102
|
-
dataClassification: undefined,
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
mockFetch.mockResolvedValueOnce({
|
|
106
|
-
ok: true,
|
|
107
|
-
status: 200,
|
|
108
|
-
json: () => Promise.resolve(mockResponse),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
const result = await client.getApp({ appId: QB_APP_ID });
|
|
112
|
-
|
|
113
|
-
expect(result).toEqual(mockResponse);
|
|
114
|
-
expect(mockFetch).toHaveBeenCalledWith(
|
|
115
|
-
`https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
|
|
116
|
-
expect.objectContaining({
|
|
117
|
-
method: "GET",
|
|
118
|
-
headers: expect.objectContaining({
|
|
119
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
120
|
-
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
121
|
-
"Content-Type": "application/json",
|
|
122
|
-
}),
|
|
123
|
-
body: undefined,
|
|
124
|
-
credentials: "omit",
|
|
125
|
-
})
|
|
126
|
-
);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
// tests/vitest/unit/apps/getAppConcurrency.test.ts
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
4
|
-
import { createClient, mockFetch, QB_APP_ID, QB_REALM } from "@tests/setup.ts";
|
|
5
|
-
|
|
6
|
-
describe("QuickbaseClient Unit - getApp Concurrency with Temp Tokens", () => {
|
|
7
|
-
let client: ReturnType<typeof createClient>;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
mockFetch.mockClear();
|
|
11
|
-
// Reset client before each test
|
|
12
|
-
client = createClient(mockFetch, {
|
|
13
|
-
realm: QB_REALM,
|
|
14
|
-
useTempTokens: true, // Use TempTokenStrategy
|
|
15
|
-
debug: true,
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("handles concurrent getApp requests with a single token fetch", async () => {
|
|
20
|
-
// Mock the token fetch response
|
|
21
|
-
const tempTokenResponse = {
|
|
22
|
-
temporaryAuthorization: "temp-token-123",
|
|
23
|
-
};
|
|
24
|
-
mockFetch.mockImplementation((url: string, options: RequestInit) => {
|
|
25
|
-
if (url.includes(`/auth/temporary/${QB_APP_ID}`)) {
|
|
26
|
-
return Promise.resolve({
|
|
27
|
-
ok: true,
|
|
28
|
-
status: 200,
|
|
29
|
-
json: () => Promise.resolve(tempTokenResponse),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
// Mock the getApp response
|
|
33
|
-
return Promise.resolve({
|
|
34
|
-
ok: true,
|
|
35
|
-
status: 200,
|
|
36
|
-
json: () =>
|
|
37
|
-
Promise.resolve({
|
|
38
|
-
id: QB_APP_ID,
|
|
39
|
-
name: "test-app",
|
|
40
|
-
created: "2025-02-13T18:22:33Z",
|
|
41
|
-
updated: "2025-03-04T04:25:51Z",
|
|
42
|
-
}),
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// Simulate concurrent getApp requests
|
|
47
|
-
const concurrentRequests = [
|
|
48
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
49
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
50
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
const results = await Promise.all(concurrentRequests);
|
|
54
|
-
|
|
55
|
-
// Assertions
|
|
56
|
-
expect(results).toHaveLength(3); // All requests completed
|
|
57
|
-
results.forEach((result) => {
|
|
58
|
-
expect(result).toEqual({
|
|
59
|
-
id: QB_APP_ID,
|
|
60
|
-
name: "test-app",
|
|
61
|
-
created: expect.any(Date), // Assuming convertDates is true
|
|
62
|
-
updated: expect.any(Date),
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Verify token fetch was called exactly once
|
|
67
|
-
const tokenFetchCalls = mockFetch.mock.calls.filter((call) =>
|
|
68
|
-
call[0].includes(`/auth/temporary/${QB_APP_ID}`)
|
|
69
|
-
);
|
|
70
|
-
expect(tokenFetchCalls).toHaveLength(1); // Only one token fetch despite 3 requests
|
|
71
|
-
|
|
72
|
-
// Verify getApp calls were made with the temp token
|
|
73
|
-
const getAppCalls = mockFetch.mock.calls.filter((call) =>
|
|
74
|
-
call[0].includes(`/apps/${QB_APP_ID}`)
|
|
75
|
-
);
|
|
76
|
-
expect(getAppCalls).toHaveLength(3); // Three getApp requests
|
|
77
|
-
getAppCalls.forEach((call) => {
|
|
78
|
-
expect(call[1].headers).toMatchObject({
|
|
79
|
-
Authorization: `QB-TEMP-TOKEN ${tempTokenResponse.temporaryAuthorization}`,
|
|
80
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
81
|
-
"Content-Type": "application/json",
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("handles concurrent getApp requests with cached token", async () => {
|
|
87
|
-
// Pre-populate the token cache by making an initial request
|
|
88
|
-
mockFetch.mockResolvedValueOnce({
|
|
89
|
-
ok: true,
|
|
90
|
-
status: 200,
|
|
91
|
-
json: () =>
|
|
92
|
-
Promise.resolve({ temporaryAuthorization: "cached-token-456" }),
|
|
93
|
-
});
|
|
94
|
-
await client.getApp({ appId: QB_APP_ID }); // This caches the token
|
|
95
|
-
|
|
96
|
-
// Reset mock to clear initial call tracking
|
|
97
|
-
mockFetch.mockClear();
|
|
98
|
-
|
|
99
|
-
// Mock only the getApp response now (no token fetch needed)
|
|
100
|
-
mockFetch.mockResolvedValue({
|
|
101
|
-
ok: true,
|
|
102
|
-
status: 200,
|
|
103
|
-
json: () =>
|
|
104
|
-
Promise.resolve({
|
|
105
|
-
id: QB_APP_ID,
|
|
106
|
-
name: "test-app",
|
|
107
|
-
created: "2025-02-13T18:22:33Z",
|
|
108
|
-
updated: "2025-03-04T04:25:51Z",
|
|
109
|
-
}),
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Simulate concurrent getApp requests with cached token
|
|
113
|
-
const concurrentRequests = [
|
|
114
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
115
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
116
|
-
client.getApp({ appId: QB_APP_ID }),
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
const results = await Promise.all(concurrentRequests);
|
|
120
|
-
|
|
121
|
-
// Assertions
|
|
122
|
-
expect(results).toHaveLength(3); // All requests completed
|
|
123
|
-
results.forEach((result) => {
|
|
124
|
-
expect(result).toEqual({
|
|
125
|
-
id: QB_APP_ID,
|
|
126
|
-
name: "test-app",
|
|
127
|
-
created: expect.any(Date),
|
|
128
|
-
updated: expect.any(Date),
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// Verify no token fetches occurred (cache was used)
|
|
133
|
-
const tokenFetchCalls = mockFetch.mock.calls.filter((call) =>
|
|
134
|
-
call[0].includes(`/auth/temporary/${QB_APP_ID}`)
|
|
135
|
-
);
|
|
136
|
-
expect(tokenFetchCalls).toHaveLength(0); // No token fetches
|
|
137
|
-
|
|
138
|
-
// Verify getApp calls were made with the cached token
|
|
139
|
-
const getAppCalls = mockFetch.mock.calls.filter((call) =>
|
|
140
|
-
call[0].includes(`/apps/${QB_APP_ID}`)
|
|
141
|
-
);
|
|
142
|
-
expect(getAppCalls).toHaveLength(3); // Three getApp requests
|
|
143
|
-
getAppCalls.forEach((call) => {
|
|
144
|
-
expect(call[1].headers).toMatchObject({
|
|
145
|
-
Authorization: `QB-TEMP-TOKEN cached-token-456`,
|
|
146
|
-
"QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
|
|
147
|
-
"Content-Type": "application/json",
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
});
|