quickbase-js 1.1.0-beta.5 → 1.1.0

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.
Files changed (110) hide show
  1. package/README.md +253 -135
  2. package/dist/esm/quickbase.d.ts +5614 -2861
  3. package/dist/esm/quickbase.js +3203 -2113
  4. package/dist/esm/quickbase.js.map +1 -1
  5. package/dist/esm/quickbase.min.js +1 -1
  6. package/dist/esm/quickbase.min.js.map +1 -1
  7. package/dist/umd/quickbase.umd.js +3532 -2322
  8. package/dist/umd/quickbase.umd.js.map +1 -1
  9. package/dist/umd/quickbase.umd.min.js +1 -1
  10. package/dist/umd/quickbase.umd.min.js.map +1 -1
  11. package/package.json +49 -32
  12. package/CHANGELOG.md +0 -86
  13. package/build.js +0 -186
  14. package/dist/umd/quickbase.umd.d.ts +0 -5341
  15. package/examples/react.js +0 -48
  16. package/examples/vanillajs.html +0 -47
  17. package/log-gen.yaml +0 -1301
  18. package/open-api/definitions/apps.ts +0 -274
  19. package/open-api/definitions/auth.ts +0 -10
  20. package/open-api/definitions/fields.ts +0 -751
  21. package/open-api/definitions/index.ts +0 -18
  22. package/open-api/definitions/records.ts +0 -269
  23. package/open-api/definitions/relationships.ts +0 -90
  24. package/open-api/definitions/reports.ts +0 -10
  25. package/open-api/definitions/tables.ts +0 -112
  26. package/open-api/fix-spec-main.ts +0 -176
  27. package/open-api/generate-unified-interface.ts +0 -170
  28. package/open-api/output/quickbase-fixed.json +0 -6760
  29. package/open-api/paths/apps.ts +0 -100
  30. package/open-api/paths/auth.ts +0 -25
  31. package/open-api/paths/fields.ts +0 -207
  32. package/open-api/paths/index.ts +0 -17
  33. package/open-api/paths/records.ts +0 -68
  34. package/open-api/paths/relationships.ts +0 -32
  35. package/open-api/paths/reports.ts +0 -34
  36. package/open-api/paths/tables.ts +0 -162
  37. package/open-api/regenerate-client.ts +0 -110
  38. package/playwright-results.txt/.last-run.json +0 -4
  39. package/playwright.config.ts +0 -37
  40. package/rollup.config.mjs +0 -114
  41. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
  42. package/src/generated-unified/QuickbaseClient.ts +0 -62
  43. package/src/index.ts +0 -1
  44. package/src/quickbaseClient.ts +0 -311
  45. package/src/tokenCache.ts +0 -51
  46. package/test-artifacts/.last-run.json +0 -6
  47. package/test-esm.js +0 -1
  48. package/test-results.json +0 -2050
  49. package/test-umd.js +0 -1
  50. package/test.ts +0 -1
  51. package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -189
  52. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -217
  53. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -151
  54. package/tests/playwright/qb/auth/getTempToken.test.ts +0 -180
  55. package/tests/playwright/qb/auth/tokenPrefetch.test.ts +0 -192
  56. package/tests/playwright/qb/auth/tokenRenewal.test.ts +0 -110
  57. package/tests/playwright/qb/auth/umd.test.ts +0 -10
  58. package/tests/setup.ts +0 -51
  59. package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
  60. package/tests/vitest/qb/apps/createApp.test.ts +0 -64
  61. package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
  62. package/tests/vitest/qb/apps/getApp.test.ts +0 -40
  63. package/tests/vitest/qb/fields/createField.test.ts +0 -78
  64. package/tests/vitest/qb/fields/deleteFields.test.ts +0 -89
  65. package/tests/vitest/qb/fields/getField.test.ts +0 -85
  66. package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -174
  67. package/tests/vitest/qb/fields/getFields.test.ts +0 -232
  68. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
  69. package/tests/vitest/qb/index.ts +0 -28
  70. package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
  71. package/tests/vitest/qb/records/runQuery.test.ts +0 -146
  72. package/tests/vitest/qb/records/upsert.test.ts +0 -102
  73. package/tests/vitest/qb/tables/createTable.test.ts +0 -55
  74. package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
  75. package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
  76. package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
  77. package/tests/vitest/qb/tables/getTable.test.ts +0 -26
  78. package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
  79. package/tests/vitest/unit/apps/copyApp.test.ts +0 -282
  80. package/tests/vitest/unit/apps/createApp.test.ts +0 -125
  81. package/tests/vitest/unit/apps/deleteApp.test.ts +0 -215
  82. package/tests/vitest/unit/apps/getApp.test.ts +0 -86
  83. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -85
  84. package/tests/vitest/unit/auth/getTempToken.test.ts +0 -95
  85. package/tests/vitest/unit/auth/retryOn401.test.ts +0 -106
  86. package/tests/vitest/unit/auth/two401s.test.ts +0 -77
  87. package/tests/vitest/unit/fields/createField.test.ts +0 -391
  88. package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
  89. package/tests/vitest/unit/fields/getField.test.ts +0 -189
  90. package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -147
  91. package/tests/vitest/unit/fields/getFields.test.ts +0 -122
  92. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
  93. package/tests/vitest/unit/index.ts +0 -33
  94. package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
  95. package/tests/vitest/unit/records/runQuery.test.ts +0 -102
  96. package/tests/vitest/unit/records/upsert.test.ts +0 -218
  97. package/tests/vitest/unit/tables/createTable.test.ts +0 -70
  98. package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
  99. package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
  100. package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
  101. package/tests/vitest/unit/tables/getTable.test.ts +0 -233
  102. package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
  103. package/tests/vitest/unit/umd.test.ts +0 -8
  104. package/text.txt +0 -104
  105. package/tools/log-gen.ts +0 -175
  106. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  107. package/tsconfig.build.json +0 -17
  108. package/tsconfig.json +0 -29
  109. package/versionrc.json +0 -9
  110. package/vitest.config.ts +0 -27
@@ -1,125 +0,0 @@
1
- // tests/vitest/unit/apps/createApp.test.ts
2
- import { describe, it, expect, beforeEach } from "vitest";
3
- import {
4
- createClient,
5
- mockFetch,
6
- QB_REALM,
7
- QB_USER_TOKEN,
8
- } from "@tests/setup.ts";
9
- import { CreateAppRequest, CreateApp200Response } from "@/generated/models";
10
-
11
- describe("QuickbaseClient Unit - createApp", () => {
12
- let client: ReturnType<typeof createClient>;
13
-
14
- beforeEach(() => {
15
- mockFetch.mockClear();
16
- });
17
-
18
- it("initializes without errors", () => {
19
- client = createClient(mockFetch, { debug: true });
20
- expect(client).toBeDefined();
21
- });
22
-
23
- it("has createApp method", () => {
24
- client = createClient(mockFetch, { debug: true });
25
- expect(typeof client.createApp).toBe("function");
26
- });
27
-
28
- it("calls createApp successfully with user token", async () => {
29
- client = createClient(mockFetch, { debug: true });
30
-
31
- const request: CreateAppRequest = {
32
- name: "New App",
33
- description: "A new app for testing",
34
- assignToken: true,
35
- };
36
-
37
- const mockResponse: CreateApp200Response = {
38
- id: "new-app-id",
39
- name: "New App",
40
- description: "A new app for testing",
41
- created: new Date("2025-03-11T10:00:00Z"),
42
- updated: new Date("2025-03-11T10:00:00Z"),
43
- dateFormat: "MM-DD-YYYY",
44
- timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
45
- hasEveryoneOnTheInternet: false,
46
- variables: [],
47
- dataClassification: "None",
48
- memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
49
- securityProperties: {
50
- allowClone: false,
51
- allowExport: true,
52
- enableAppTokens: true,
53
- hideFromPublic: false,
54
- mustBeRealmApproved: false,
55
- useIPFilter: false,
56
- },
57
- };
58
-
59
- mockFetch.mockResolvedValueOnce({
60
- ok: true,
61
- status: 200,
62
- json: () =>
63
- Promise.resolve({
64
- ...mockResponse,
65
- created: "2025-03-11T10:00:00Z", // API returns string
66
- updated: "2025-03-11T10:00:00Z", // API returns string
67
- }),
68
- });
69
-
70
- const result = await client.createApp({ body: request });
71
-
72
- expect(result).toEqual(mockResponse);
73
- expect(mockFetch).toHaveBeenCalledWith(
74
- `https://api.quickbase.com/v1/apps`,
75
- expect.objectContaining({
76
- method: "POST",
77
- headers: expect.objectContaining({
78
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
79
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
80
- "Content-Type": "application/json",
81
- }),
82
- body: expect.stringContaining('"name":"New App"'),
83
- credentials: "omit", // Added to match actual behavior
84
- })
85
- );
86
- // Additional check to ensure body contains all properties regardless of order
87
- const callArgs = mockFetch.mock.calls[0];
88
- const body = JSON.parse(callArgs[1].body as string);
89
- expect(body).toEqual(request);
90
- });
91
-
92
- it("handles 400 error for invalid request", async () => {
93
- client = createClient(mockFetch, { debug: true });
94
-
95
- const request: CreateAppRequest = {
96
- name: "", // Invalid: name is required
97
- };
98
-
99
- mockFetch.mockImplementationOnce(() =>
100
- Promise.resolve({
101
- ok: false,
102
- status: 400,
103
- json: () => Promise.resolve({ message: "Name is required" }),
104
- })
105
- );
106
-
107
- await expect(client.createApp({ body: request })).rejects.toThrow(
108
- "API Error: Name is required (Status: 400)"
109
- );
110
-
111
- expect(mockFetch).toHaveBeenCalledWith(
112
- `https://api.quickbase.com/v1/apps`,
113
- expect.objectContaining({
114
- method: "POST",
115
- headers: expect.objectContaining({
116
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
117
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
118
- "Content-Type": "application/json",
119
- }),
120
- body: JSON.stringify(request),
121
- credentials: "omit", // Added to match actual behavior
122
- })
123
- );
124
- });
125
- });
@@ -1,215 +0,0 @@
1
- // tests/vitest/unit/apps/deleteApp.test.ts
2
- import { describe, it, expect, beforeEach } from "vitest";
3
- import {
4
- createClient,
5
- mockFetch,
6
- QB_APP_ID,
7
- QB_REALM,
8
- QB_USER_TOKEN,
9
- } from "@tests/setup.ts";
10
- import { DeleteAppRequest, DeleteApp200Response } from "@/generated/models";
11
-
12
- describe("QuickbaseClient Unit - deleteApp", () => {
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 deleteApp method", () => {
25
- client = createClient(mockFetch, { debug: true });
26
- expect(typeof client.deleteApp).toBe("function");
27
- });
28
-
29
- it("calls deleteApp successfully with user token", async () => {
30
- client = createClient(mockFetch, { debug: true });
31
-
32
- const request: DeleteAppRequest = {
33
- name: "App to Delete",
34
- };
35
-
36
- const mockResponse: DeleteApp200Response = {
37
- deletedAppId: QB_APP_ID,
38
- };
39
-
40
- mockFetch.mockResolvedValueOnce({
41
- ok: true,
42
- status: 200,
43
- json: () => Promise.resolve(mockResponse),
44
- });
45
-
46
- const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
47
-
48
- expect(result).toEqual(mockResponse);
49
- expect(mockFetch).toHaveBeenCalledWith(
50
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
51
- expect.objectContaining({
52
- method: "DELETE",
53
- headers: expect.objectContaining({
54
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
55
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
56
- "Content-Type": "application/json",
57
- }),
58
- body: JSON.stringify(request),
59
- })
60
- );
61
- });
62
-
63
- it("calls deleteApp successfully with temp token", async () => {
64
- client = createClient(mockFetch, { useTempTokens: true, debug: true });
65
-
66
- const request: DeleteAppRequest = {
67
- name: "App to Delete with Temp Token",
68
- };
69
-
70
- const mockResponse: DeleteApp200Response = {
71
- deletedAppId: QB_APP_ID,
72
- };
73
-
74
- mockFetch
75
- .mockResolvedValueOnce({
76
- ok: true,
77
- status: 200,
78
- json: () => Promise.resolve({ temporaryAuthorization: "temp_token" }),
79
- })
80
- .mockResolvedValueOnce({
81
- ok: true,
82
- status: 200,
83
- json: () => Promise.resolve(mockResponse),
84
- });
85
-
86
- const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
87
-
88
- expect(result).toEqual(mockResponse);
89
- expect(mockFetch).toHaveBeenCalledTimes(2);
90
- expect(mockFetch).toHaveBeenNthCalledWith(
91
- 1,
92
- `https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
93
- expect.objectContaining({
94
- method: "GET",
95
- headers: expect.objectContaining({
96
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
97
- "Content-Type": "application/json",
98
- }),
99
- credentials: "include",
100
- })
101
- );
102
- expect(mockFetch).toHaveBeenNthCalledWith(
103
- 2,
104
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
105
- expect.objectContaining({
106
- method: "DELETE",
107
- headers: expect.objectContaining({
108
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
109
- Authorization: "QB-TEMP-TOKEN temp_token",
110
- "Content-Type": "application/json",
111
- }),
112
- body: JSON.stringify(request),
113
- })
114
- );
115
- });
116
-
117
- it("retries successfully after 401 with temp token", async () => {
118
- client = createClient(mockFetch, { useTempTokens: true, debug: true });
119
-
120
- const request: DeleteAppRequest = {
121
- name: "Retry Delete App",
122
- };
123
-
124
- const mockResponse: DeleteApp200Response = {
125
- deletedAppId: QB_APP_ID,
126
- };
127
-
128
- mockFetch
129
- .mockResolvedValueOnce({
130
- ok: true,
131
- status: 200,
132
- json: () =>
133
- Promise.resolve({ temporaryAuthorization: "initial_token" }),
134
- })
135
- .mockResolvedValueOnce({
136
- ok: false,
137
- status: 401,
138
- json: () => Promise.resolve({ message: "Unauthorized" }),
139
- })
140
- .mockResolvedValueOnce({
141
- ok: true,
142
- status: 200,
143
- json: () => Promise.resolve({ temporaryAuthorization: "new_token" }),
144
- })
145
- .mockResolvedValueOnce({
146
- ok: true,
147
- status: 200,
148
- json: () => Promise.resolve(mockResponse),
149
- });
150
-
151
- const result = await client.deleteApp({ appId: QB_APP_ID, body: request });
152
-
153
- expect(result).toEqual(mockResponse);
154
- expect(mockFetch).toHaveBeenCalledTimes(4);
155
- expect(mockFetch).toHaveBeenNthCalledWith(
156
- 1,
157
- `https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
158
- expect.any(Object)
159
- );
160
- expect(mockFetch).toHaveBeenNthCalledWith(
161
- 2,
162
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
163
- expect.objectContaining({
164
- headers: expect.objectContaining({
165
- Authorization: "QB-TEMP-TOKEN initial_token",
166
- }),
167
- })
168
- );
169
- expect(mockFetch).toHaveBeenNthCalledWith(
170
- 3,
171
- `https://api.quickbase.com/v1/auth/temporary/${QB_APP_ID}`,
172
- expect.any(Object)
173
- );
174
- expect(mockFetch).toHaveBeenNthCalledWith(
175
- 4,
176
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
177
- expect.objectContaining({
178
- headers: expect.objectContaining({
179
- Authorization: "QB-TEMP-TOKEN new_token",
180
- }),
181
- })
182
- );
183
- });
184
-
185
- it("handles 400 error for invalid request", async () => {
186
- client = createClient(mockFetch, { debug: true });
187
-
188
- const request: DeleteAppRequest = {
189
- name: "Wrong Name", // Assuming this doesn’t match the app’s actual name
190
- };
191
-
192
- mockFetch.mockResolvedValueOnce({
193
- ok: false,
194
- status: 400,
195
- json: () => Promise.resolve({ message: "Invalid application name" }),
196
- });
197
-
198
- await expect(
199
- client.deleteApp({ appId: QB_APP_ID, body: request })
200
- ).rejects.toThrow("API Error: Invalid application name (Status: 400)");
201
-
202
- expect(mockFetch).toHaveBeenCalledWith(
203
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
204
- expect.objectContaining({
205
- method: "DELETE",
206
- headers: expect.objectContaining({
207
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
208
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
209
- "Content-Type": "application/json",
210
- }),
211
- body: JSON.stringify(request),
212
- })
213
- );
214
- });
215
- });
@@ -1,86 +0,0 @@
1
- // tests/vitest/unit/apps/getApp.test.ts
2
- import { describe, it, expect, beforeEach } from "vitest";
3
- import {
4
- createClient,
5
- mockFetch,
6
- QB_APP_ID,
7
- QB_REALM,
8
- QB_USER_TOKEN,
9
- } from "@tests/setup.ts";
10
-
11
- describe("QuickbaseClient Unit - getApp", () => {
12
- let client: ReturnType<typeof createClient>;
13
-
14
- beforeEach(() => {
15
- mockFetch.mockClear();
16
- client = createClient(mockFetch, { debug: true }); // Add debug: true for consistency
17
- });
18
-
19
- it("initializes without errors", () => {
20
- expect(client).toBeDefined();
21
- });
22
-
23
- it("has getApp method", () => {
24
- expect(typeof client.getApp).toBe("function");
25
- });
26
-
27
- it("calls getApp successfully", async () => {
28
- mockFetch.mockImplementation((url: string, options: any) => {
29
- console.log("Mock fetch:", url, options);
30
- return Promise.resolve({
31
- ok: true,
32
- status: 200,
33
- json: () =>
34
- Promise.resolve({
35
- id: QB_APP_ID,
36
- name: "qb-copy",
37
- created: "2025-02-13T18:22:33Z",
38
- updated: "2025-03-04T04:25:51Z",
39
- description: "",
40
- timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
41
- dateFormat: "MM-DD-YYYY",
42
- hasEveryoneOnTheInternet: false,
43
- memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
44
- securityProperties: {
45
- allowClone: false,
46
- allowExport: true,
47
- enableAppTokens: true,
48
- hideFromPublic: false,
49
- mustBeRealmApproved: false,
50
- useIPFilter: false,
51
- },
52
- }),
53
- } as Response);
54
- });
55
-
56
- const result = await client.getApp({ appId: QB_APP_ID });
57
- expect(result).toEqual({
58
- id: QB_APP_ID,
59
- name: "qb-copy",
60
- created: new Date("2025-02-13T18:22:33Z"),
61
- updated: new Date("2025-03-04T04:25:51Z"),
62
- description: "",
63
- timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
64
- dateFormat: "MM-DD-YYYY",
65
- hasEveryoneOnTheInternet: false,
66
- memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
67
- securityProperties: {
68
- allowClone: false,
69
- allowExport: true,
70
- enableAppTokens: true,
71
- hideFromPublic: false,
72
- mustBeRealmApproved: false,
73
- useIPFilter: false,
74
- },
75
- });
76
- expect(mockFetch).toHaveBeenCalledWith(
77
- `https://api.quickbase.com/v1/apps/${QB_APP_ID}`,
78
- expect.objectContaining({
79
- headers: expect.objectContaining({
80
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
81
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
82
- }),
83
- })
84
- );
85
- });
86
- });
@@ -1,85 +0,0 @@
1
- // tests/vitest/unit/auth/fetchTempToken401.test.ts
2
- import { describe, it, expect, beforeEach, vi } from "vitest";
3
- import {
4
- createClient,
5
- mockFetch,
6
- QB_REALM,
7
- QB_TABLE_ID_1,
8
- } from "@tests/setup.ts";
9
-
10
- describe("QuickbaseClient Unit - 401 with fetchTempToken 401", () => {
11
- let client: ReturnType<typeof createClient>;
12
-
13
- beforeEach(() => {
14
- mockFetch.mockClear();
15
- client = createClient(mockFetch, { useTempTokens: true, debug: true });
16
- });
17
-
18
- it("fails without infinite loop when fetchTempToken returns 401 after initial 401", async () => {
19
- let callCount = 0;
20
-
21
- mockFetch.mockImplementation((url) => {
22
- callCount++;
23
- console.log(`Mock fetch call ${callCount}: ${url}`);
24
- if (url.includes("auth/temporary") && callCount === 1) {
25
- return Promise.resolve({
26
- ok: true,
27
- status: 200,
28
- json: () =>
29
- Promise.resolve({ temporaryAuthorization: "initial_token" }),
30
- });
31
- }
32
- if (url.includes("fields") && callCount === 2) {
33
- return Promise.resolve({
34
- ok: false,
35
- status: 401,
36
- json: () => Promise.resolve({ message: "Unauthorized" }),
37
- });
38
- }
39
- if (url.includes("auth/temporary") && callCount === 3) {
40
- return Promise.resolve({
41
- ok: false,
42
- status: 401,
43
- json: () =>
44
- Promise.resolve({ message: "Unauthorized in fetchTempToken" }),
45
- });
46
- }
47
- return Promise.reject(new Error(`Unexpected fetch call: ${url}`));
48
- });
49
-
50
- const consoleSpy = vi.spyOn(console, "log");
51
- await expect(client.getFields({ tableId: QB_TABLE_ID_1 })).rejects.toThrow(
52
- "API Error: Unauthorized in fetchTempToken (Status: 401)"
53
- );
54
-
55
- expect(mockFetch).toHaveBeenCalledTimes(3);
56
- expect(mockFetch).toHaveBeenNthCalledWith(
57
- 1,
58
- `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_1}`,
59
- expect.any(Object)
60
- );
61
- expect(mockFetch).toHaveBeenNthCalledWith(
62
- 2,
63
- `https://api.quickbase.com/v1/fields?tableId=${QB_TABLE_ID_1}`, // Removed &includeFieldPerms=false
64
- expect.objectContaining({
65
- headers: expect.objectContaining({
66
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
67
- }),
68
- })
69
- );
70
- expect(mockFetch).toHaveBeenNthCalledWith(
71
- 3,
72
- `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_1}`,
73
- expect.any(Object)
74
- );
75
-
76
- expect(consoleSpy).toHaveBeenCalledWith(
77
- "Authorization error for getFields, refreshing token:",
78
- expect.any(String)
79
- );
80
- expect(consoleSpy).not.toHaveBeenCalledWith(
81
- "Retrying getFields with new token"
82
- );
83
- consoleSpy.mockRestore();
84
- });
85
- });
@@ -1,95 +0,0 @@
1
- // tests/vitest/unit/auth/getTempTokenDBID.test.ts
2
- import { describe, it, expect, beforeEach } from "vitest";
3
- import {
4
- createClient,
5
- mockFetch,
6
- QB_REALM,
7
- QB_TABLE_ID_1,
8
- } from "@tests/setup.ts";
9
-
10
- describe("QuickbaseClient Unit - getTempTokenDBID", () => {
11
- let client: ReturnType<typeof createClient>;
12
-
13
- beforeEach(() => {
14
- mockFetch.mockClear();
15
- client = createClient(mockFetch, { useTempTokens: true, debug: false });
16
- });
17
-
18
- it("initializes without errors", () => {
19
- expect(client).toBeDefined();
20
- });
21
-
22
- it("has getTempTokenDBID method", () => {
23
- expect(typeof client.getTempTokenDBID).toBe("function");
24
- });
25
-
26
- it("fetches and caches temp token on first call", async () => {
27
- const mockToken = "b123xyz_temp_token";
28
-
29
- mockFetch.mockResolvedValueOnce({
30
- ok: true,
31
- status: 200,
32
- json: () => Promise.resolve({ temporaryAuthorization: mockToken }),
33
- });
34
-
35
- const result = await client.getTempTokenDBID({ dbid: QB_TABLE_ID_1 });
36
- expect(result).toEqual({ temporaryAuthorization: mockToken });
37
- expect(mockFetch).toHaveBeenCalledWith(
38
- `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_1}`,
39
- expect.objectContaining({
40
- method: "GET",
41
- headers: expect.objectContaining({
42
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
43
- "Content-Type": "application/json",
44
- }),
45
- credentials: "include",
46
- })
47
- );
48
- });
49
-
50
- it("reuses cached temp token on second call", async () => {
51
- const mockToken = "b123xyz_temp_token";
52
-
53
- mockFetch.mockResolvedValueOnce({
54
- ok: true,
55
- status: 200,
56
- json: () => Promise.resolve({ temporaryAuthorization: mockToken }),
57
- });
58
-
59
- const firstResult = await client.getTempTokenDBID({ dbid: QB_TABLE_ID_1 });
60
- expect(firstResult).toEqual({ temporaryAuthorization: mockToken });
61
- expect(mockFetch).toHaveBeenCalledTimes(1);
62
-
63
- mockFetch.mockClear();
64
- const secondResult = await client.getTempTokenDBID({ dbid: QB_TABLE_ID_1 });
65
- expect(secondResult).toEqual({ temporaryAuthorization: mockToken });
66
- expect(mockFetch).not.toHaveBeenCalled();
67
- });
68
-
69
- it("handles API error", async () => {
70
- mockFetch.mockResolvedValueOnce({
71
- ok: false,
72
- status: 401,
73
- json: () => Promise.resolve({ message: "Unauthorized" }),
74
- });
75
-
76
- await expect(
77
- client.getTempTokenDBID({ dbid: QB_TABLE_ID_1 })
78
- ).rejects.toSatisfy((error: Error) => {
79
- expect(error).toBeInstanceOf(Error);
80
- expect(error.message).toBe("API Error: Unauthorized (Status: 401)");
81
- return true;
82
- });
83
- expect(mockFetch).toHaveBeenCalledWith(
84
- `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_1}`,
85
- expect.objectContaining({
86
- method: "GET",
87
- headers: expect.objectContaining({
88
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
89
- "Content-Type": "application/json",
90
- }),
91
- credentials: "include",
92
- })
93
- );
94
- });
95
- });