quickbase-js 1.1.0-beta.2 → 1.1.0-beta.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +53 -22
  2. package/README.md +61 -5
  3. package/dist/quickbase.d.ts +1711 -613
  4. package/dist/quickbase.js +1469 -468
  5. package/dist/quickbase.js.map +1 -1
  6. package/examples/react.js +12 -12
  7. package/examples/vanillajs.html +12 -12
  8. package/log-gen.yaml +3558 -528
  9. package/package.json +12 -14
  10. package/playwright-results.txt/.last-run.json +4 -0
  11. package/playwright.config.ts +1 -1
  12. package/src/code-generation/definitions/apps.ts +274 -0
  13. package/src/code-generation/definitions/auth.ts +10 -0
  14. package/src/code-generation/definitions/fields.ts +751 -0
  15. package/src/code-generation/definitions/index.ts +18 -0
  16. package/src/code-generation/definitions/records.ts +269 -0
  17. package/src/code-generation/definitions/relationships.ts +90 -0
  18. package/src/code-generation/definitions/reports.ts +10 -0
  19. package/src/code-generation/definitions/tables.ts +112 -0
  20. package/src/code-generation/fix-spec-main.ts +2 -2
  21. package/src/code-generation/output/quickbase-fixed.json +1724 -3044
  22. package/src/code-generation/paths/apps.ts +100 -0
  23. package/src/code-generation/paths/auth.ts +25 -0
  24. package/src/code-generation/paths/fields.ts +207 -0
  25. package/src/code-generation/paths/index.ts +17 -0
  26. package/src/code-generation/paths/records.ts +68 -0
  27. package/src/code-generation/paths/relationships.ts +32 -0
  28. package/src/code-generation/paths/reports.ts +34 -0
  29. package/src/code-generation/paths/tables.ts +162 -0
  30. package/src/generated-unified/QuickbaseClient.ts +10 -8
  31. package/src/log-gen.ts +6 -2
  32. package/src/quickbaseClient.ts +35 -41
  33. package/tests/setup.ts +5 -1
  34. package/tests/vitest/qb/apps/copyApp.test.ts +76 -0
  35. package/tests/vitest/qb/apps/createApp.test.ts +64 -0
  36. package/tests/vitest/qb/apps/deleteApp.test.ts +76 -0
  37. package/tests/vitest/qb/fields/createField.test.ts +78 -0
  38. package/tests/vitest/qb/fields/deleteFields.test.ts +89 -0
  39. package/tests/vitest/qb/fields/getField.test.ts +85 -0
  40. package/tests/vitest/qb/fields/getFieldUsage.test.ts +174 -0
  41. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +77 -0
  42. package/tests/vitest/qb/index.ts +25 -1
  43. package/tests/vitest/qb/records/deleteRecords.test.ts +42 -10
  44. package/tests/vitest/qb/records/runQuery.test.ts +81 -17
  45. package/tests/vitest/qb/records/upsert.test.ts +33 -3
  46. package/tests/vitest/qb/tables/getRelationships.test.ts +80 -0
  47. package/tests/vitest/unit/apps/copyApp.test.ts +282 -0
  48. package/tests/vitest/unit/apps/createApp.test.ts +125 -0
  49. package/tests/vitest/unit/apps/deleteApp.test.ts +215 -0
  50. package/tests/vitest/unit/fields/createField.test.ts +391 -0
  51. package/tests/vitest/unit/fields/deleteFields.test.ts +141 -0
  52. package/tests/vitest/unit/fields/getField.test.ts +189 -0
  53. package/tests/vitest/unit/fields/getFieldUsage.test.ts +147 -0
  54. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +160 -0
  55. package/tests/vitest/unit/index.ts +30 -1
  56. package/tests/vitest/unit/tables/getRelationships.test.ts +259 -0
  57. package/src/code-generation/fix-spec-definitions.ts +0 -543
  58. package/src/code-generation/fix-spec-paths.ts +0 -355
  59. package/test-artifacts/test-results.json +0 -829
@@ -0,0 +1,147 @@
1
+ // tests/vitest/unit/fields/getFieldUsage.test.ts
2
+ import { describe, it, expect, beforeEach } from "vitest";
3
+ import {
4
+ createClient,
5
+ mockFetch,
6
+ QB_REALM,
7
+ QB_USER_TOKEN,
8
+ QB_TABLE_ID_1,
9
+ } from "@tests/setup.ts";
10
+ import { FieldUsage } from "@/generated/models";
11
+
12
+ describe("QuickbaseClient Unit - getFieldUsage", () => {
13
+ let client: ReturnType<typeof createClient>;
14
+
15
+ beforeEach(() => {
16
+ mockFetch.mockClear();
17
+ client = createClient(mockFetch, { realm: QB_REALM, debug: true });
18
+ });
19
+
20
+ it("initializes without errors and has getFieldUsage method", () => {
21
+ expect(client).toBeDefined();
22
+ expect(typeof client.getFieldUsage).toBe("function");
23
+ });
24
+
25
+ it("calls getFieldUsage successfully with user token", async () => {
26
+ const mockResponse: FieldUsage = {
27
+ field: {
28
+ id: 6,
29
+ name: "name",
30
+ type: "text", // Match QuickBase's lowercase response
31
+ },
32
+ usage: {
33
+ actions: { count: 0 },
34
+ appHomePages: { count: 0 },
35
+ dashboards: { count: 2 },
36
+ defaultReports: { count: 1 },
37
+ exactForms: { count: 0 },
38
+ fields: { count: 0 },
39
+ forms: { count: 1 },
40
+ notifications: { count: 0 },
41
+ personalReports: { count: 0 },
42
+ pipelines: { count: 1 },
43
+ relationships: { count: 0 },
44
+ reminders: { count: 0 },
45
+ reports: { count: 2 },
46
+ roles: { count: 2 },
47
+ tableImports: { count: 2 },
48
+ tableRules: { count: 1 },
49
+ webhooks: { count: 0 },
50
+ },
51
+ };
52
+
53
+ // Mock the response as an array to match the updated API behavior
54
+ mockFetch.mockResolvedValueOnce(
55
+ new Response(JSON.stringify([mockResponse]), {
56
+ status: 200,
57
+ statusText: "OK",
58
+ headers: { "Content-Type": "application/json" },
59
+ })
60
+ );
61
+
62
+ const result = await client.getFieldUsage({
63
+ fieldId: 6,
64
+ tableId: QB_TABLE_ID_1,
65
+ });
66
+
67
+ // Expect an array and unwrap the first item
68
+ expect(result).toBeInstanceOf(Array);
69
+ expect(result).toHaveLength(1);
70
+ const fieldUsage = result[0];
71
+
72
+ expect(fieldUsage).toEqual(mockResponse);
73
+ expect(mockFetch).toHaveBeenCalledWith(
74
+ `https://api.quickbase.com/v1/fields/usage/6?tableId=${QB_TABLE_ID_1}`,
75
+ expect.objectContaining({
76
+ method: "GET",
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
+ })
83
+ );
84
+ expect(fieldUsage.field.id).toBe(6);
85
+ expect(fieldUsage.field.name).toBe("name");
86
+ expect(fieldUsage.usage.dashboards.count).toBe(2);
87
+ });
88
+
89
+ it("handles 404 error for non-existent field", async () => {
90
+ mockFetch.mockResolvedValueOnce(
91
+ new Response(JSON.stringify({ message: "Field not found" }), {
92
+ status: 404,
93
+ statusText: "Not Found",
94
+ headers: { "Content-Type": "application/json" },
95
+ })
96
+ );
97
+
98
+ await expect(
99
+ client.getFieldUsage({
100
+ fieldId: 999,
101
+ tableId: QB_TABLE_ID_1,
102
+ })
103
+ ).rejects.toThrow("API Error: Field not found (Status: 404)");
104
+
105
+ expect(mockFetch).toHaveBeenCalledWith(
106
+ `https://api.quickbase.com/v1/fields/usage/999?tableId=${QB_TABLE_ID_1}`,
107
+ expect.objectContaining({
108
+ method: "GET",
109
+ headers: expect.objectContaining({
110
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
111
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
112
+ "Content-Type": "application/json",
113
+ }),
114
+ })
115
+ );
116
+ });
117
+
118
+ it("handles 401 error and does not retry with user token", async () => {
119
+ mockFetch.mockResolvedValueOnce(
120
+ new Response(JSON.stringify({ message: "Unauthorized" }), {
121
+ status: 401,
122
+ statusText: "Unauthorized",
123
+ headers: { "Content-Type": "application/json" },
124
+ })
125
+ );
126
+
127
+ await expect(
128
+ client.getFieldUsage({
129
+ fieldId: 6,
130
+ tableId: QB_TABLE_ID_1,
131
+ })
132
+ ).rejects.toThrow("API Error: Unauthorized (Status: 401)");
133
+
134
+ expect(mockFetch).toHaveBeenCalledTimes(1); // No retry with user token
135
+ expect(mockFetch).toHaveBeenCalledWith(
136
+ `https://api.quickbase.com/v1/fields/usage/6?tableId=${QB_TABLE_ID_1}`,
137
+ expect.objectContaining({
138
+ method: "GET",
139
+ headers: expect.objectContaining({
140
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
141
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
142
+ "Content-Type": "application/json",
143
+ }),
144
+ })
145
+ );
146
+ });
147
+ });
@@ -0,0 +1,160 @@
1
+ // tests/vitest/unit/fields/getFieldsUsage.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
+ QB_USER_TOKEN,
9
+ } from "@tests/setup.ts";
10
+ import { FieldUsage } from "@/generated/models";
11
+
12
+ describe("QuickbaseClient Unit - getFieldsUsage", () => {
13
+ let client: ReturnType<typeof createClient>;
14
+
15
+ beforeEach(() => {
16
+ mockFetch.mockClear();
17
+ client = createClient(mockFetch, { debug: true });
18
+ });
19
+
20
+ it("initializes without errors and has getFieldsUsage method", () => {
21
+ expect(client).toBeDefined();
22
+ expect(typeof client.getFieldsUsage).toBe("function");
23
+ });
24
+
25
+ it("calls getFieldsUsage successfully with user token", async () => {
26
+ const mockResponse: FieldUsage[] = [
27
+ {
28
+ field: {
29
+ id: 6,
30
+ name: "name",
31
+ type: "Text",
32
+ },
33
+ usage: {
34
+ actions: { count: 0 },
35
+ appHomePages: { count: 0 },
36
+ dashboards: { count: 2 },
37
+ defaultReports: { count: 1 },
38
+ exactForms: { count: 0 },
39
+ fields: { count: 0 },
40
+ forms: { count: 1 },
41
+ notifications: { count: 0 },
42
+ personalReports: { count: 0 },
43
+ pipelines: { count: 1 },
44
+ relationships: { count: 0 },
45
+ reminders: { count: 0 },
46
+ reports: { count: 2 },
47
+ roles: { count: 2 },
48
+ tableImports: { count: 3 },
49
+ tableRules: { count: 1 },
50
+ webhooks: { count: 0 },
51
+ },
52
+ },
53
+ ];
54
+
55
+ mockFetch.mockResolvedValueOnce({
56
+ ok: true,
57
+ status: 200,
58
+ json: () => Promise.resolve(mockResponse),
59
+ });
60
+
61
+ const result = await client.getFieldsUsage({
62
+ tableId: QB_TABLE_ID_1,
63
+ });
64
+
65
+ expect(result).toEqual(mockResponse);
66
+ expect(mockFetch).toHaveBeenCalledWith(
67
+ `https://api.quickbase.com/v1/fields/usage?tableId=${QB_TABLE_ID_1}`,
68
+ expect.objectContaining({
69
+ method: "GET",
70
+ headers: expect.objectContaining({
71
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
72
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
73
+ "Content-Type": "application/json",
74
+ }),
75
+ })
76
+ );
77
+ });
78
+
79
+ it("calls getFieldsUsage with skip and top parameters", async () => {
80
+ const mockResponse: FieldUsage[] = [
81
+ {
82
+ field: {
83
+ id: 7,
84
+ name: "priority",
85
+ type: "Text",
86
+ },
87
+ usage: {
88
+ actions: { count: 1 },
89
+ appHomePages: { count: 0 },
90
+ dashboards: { count: 0 },
91
+ defaultReports: { count: 0 },
92
+ exactForms: { count: 0 },
93
+ fields: { count: 1 },
94
+ forms: { count: 0 },
95
+ notifications: { count: 0 },
96
+ personalReports: { count: 0 },
97
+ pipelines: { count: 0 },
98
+ relationships: { count: 0 },
99
+ reminders: { count: 0 },
100
+ reports: { count: 1 },
101
+ roles: { count: 1 },
102
+ tableImports: { count: 0 },
103
+ tableRules: { count: 0 },
104
+ webhooks: { count: 0 },
105
+ },
106
+ },
107
+ ];
108
+
109
+ mockFetch.mockResolvedValueOnce({
110
+ ok: true,
111
+ status: 200,
112
+ json: () => Promise.resolve(mockResponse),
113
+ });
114
+
115
+ const result = await client.getFieldsUsage({
116
+ tableId: QB_TABLE_ID_1,
117
+ skip: 1,
118
+ top: 1,
119
+ });
120
+
121
+ expect(result).toEqual(mockResponse);
122
+ expect(mockFetch).toHaveBeenCalledWith(
123
+ `https://api.quickbase.com/v1/fields/usage?tableId=${QB_TABLE_ID_1}&skip=1&top=1`,
124
+ expect.objectContaining({
125
+ method: "GET",
126
+ headers: expect.objectContaining({
127
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
128
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
129
+ "Content-Type": "application/json",
130
+ }),
131
+ })
132
+ );
133
+ });
134
+
135
+ it("handles 404 error for non-existent table", async () => {
136
+ const nonExistentTableId = "nonexistent_dbid";
137
+
138
+ mockFetch.mockResolvedValueOnce({
139
+ ok: false,
140
+ status: 404,
141
+ json: () => Promise.resolve({ message: "Table not found" }),
142
+ });
143
+
144
+ await expect(
145
+ client.getFieldsUsage({ tableId: nonExistentTableId })
146
+ ).rejects.toThrow("API Error: Table not found (Status: 404)");
147
+
148
+ expect(mockFetch).toHaveBeenCalledWith(
149
+ `https://api.quickbase.com/v1/fields/usage?tableId=${nonExistentTableId}`,
150
+ expect.objectContaining({
151
+ method: "GET",
152
+ headers: expect.objectContaining({
153
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
154
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
155
+ "Content-Type": "application/json",
156
+ }),
157
+ })
158
+ );
159
+ });
160
+ });
@@ -1,4 +1,33 @@
1
- // tests/unit/index.ts
1
+ // tests/vitest/unit/index.ts
2
+ // Apps
3
+ export * from "./apps/copyApp.test.ts";
4
+ export * from "./apps/createApp.test.ts";
5
+ export * from "./apps/deleteApp.test.ts";
2
6
  export * from "./apps/getApp.test.ts";
7
+
8
+ // Auth
9
+ export * from "./auth/fetchTempToken401.test.ts";
10
+ export * from "./auth/getTempToken.test.ts";
11
+ export * from "./auth/retryOn401.test.ts";
12
+ export * from "./auth/two401s.test.ts";
13
+
14
+ // Fields
3
15
  export * from "./fields/getFields.test.ts";
16
+ export * from "./fields/getField.test.ts";
17
+ export * from "./fields/createField.test.ts";
18
+ export * from "./fields/deleteFields.test.ts";
19
+ export * from "./fields/getFieldsUsage.test.ts";
20
+ export * from "./fields/getFieldUsage.test.ts";
21
+
22
+ // Records
23
+ export * from "./records/deleteRecords.test.ts";
24
+ export * from "./records/runQuery.test.ts";
25
+ export * from "./records/upsert.test.ts";
26
+
27
+ // Tables
28
+ export * from "./tables/createTable.test.ts";
29
+ export * from "./tables/deleteTable.test.ts";
4
30
  export * from "./tables/getAppTables.test.ts";
31
+ export * from "./tables/getRelationships.test.ts";
32
+ export * from "./tables/getTable.test.ts";
33
+ export * from "./tables/updateTable.test.ts";
@@ -0,0 +1,259 @@
1
+ // tests/vitest/unit/relationships/getRelationships.test.ts
2
+ import { describe, it, expect, beforeEach } from "vitest";
3
+ import {
4
+ createClient,
5
+ mockFetch,
6
+ QB_REALM,
7
+ QB_USER_TOKEN,
8
+ QB_TABLE_ID_1,
9
+ QB_TABLE_ID_2,
10
+ } from "@tests/setup.ts";
11
+ import { GetRelationships200Response } from "/home/drew/Projects/quickbase-js/src/generated/models";
12
+
13
+ describe("QuickbaseClient Unit - getRelationships", () => {
14
+ let client: ReturnType<typeof createClient>;
15
+
16
+ beforeEach(() => {
17
+ mockFetch.mockClear();
18
+ client = createClient(mockFetch, { debug: true }); // Consistent with output
19
+ });
20
+
21
+ it("initializes without errors", () => {
22
+ expect(client).toBeDefined();
23
+ });
24
+
25
+ it("has getRelationships method", () => {
26
+ expect(typeof client.getRelationships).toBe("function");
27
+ });
28
+
29
+ it("sends correct GET request and handles successful response", async () => {
30
+ const mockResponse: GetRelationships200Response = {
31
+ metadata: {
32
+ numRelationships: 1,
33
+ skip: 0,
34
+ totalRelationships: 1,
35
+ },
36
+ relationships: [
37
+ {
38
+ id: 6,
39
+ parentTableId: QB_TABLE_ID_1, // Parent table
40
+ childTableId: QB_TABLE_ID_2, // Child table
41
+ foreignKeyField: {
42
+ id: 6,
43
+ label: "Related record",
44
+ type: "numeric",
45
+ },
46
+ isCrossApp: false,
47
+ lookupFields: [
48
+ {
49
+ id: 3,
50
+ label: "Name",
51
+ type: "text",
52
+ },
53
+ ],
54
+ summaryFields: [
55
+ {
56
+ id: 8,
57
+ label: "my summary field",
58
+ type: "numeric",
59
+ },
60
+ ],
61
+ },
62
+ ],
63
+ };
64
+
65
+ mockFetch.mockResolvedValueOnce({
66
+ ok: true,
67
+ status: 200,
68
+ json: () => Promise.resolve(mockResponse),
69
+ });
70
+
71
+ const result = await client.getRelationships({
72
+ tableId: QB_TABLE_ID_2,
73
+ skip: 0,
74
+ });
75
+
76
+ expect(mockFetch).toHaveBeenCalledWith(
77
+ `https://api.quickbase.com/v1/tables/${QB_TABLE_ID_2}/relationships?skip=0`,
78
+ expect.objectContaining({
79
+ method: "GET",
80
+ headers: expect.objectContaining({
81
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
82
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
83
+ "Content-Type": "application/json",
84
+ }),
85
+ })
86
+ );
87
+
88
+ expect(result).toEqual(mockResponse);
89
+ expect(result.metadata.numRelationships).toBe(1);
90
+ expect(result.relationships).toHaveLength(1);
91
+ expect(result.relationships[0].id).toBe(6);
92
+ expect(result.relationships[0].foreignKeyField.label).toBe(
93
+ "Related record"
94
+ );
95
+ });
96
+
97
+ it("handles request without skip parameter", async () => {
98
+ const mockResponse: GetRelationships200Response = {
99
+ metadata: {
100
+ numRelationships: 1,
101
+ skip: 0,
102
+ totalRelationships: 1,
103
+ },
104
+ relationships: [
105
+ {
106
+ id: 6,
107
+ parentTableId: QB_TABLE_ID_1,
108
+ childTableId: QB_TABLE_ID_2,
109
+ foreignKeyField: {
110
+ id: 6,
111
+ label: "Related record",
112
+ type: "numeric",
113
+ },
114
+ isCrossApp: false,
115
+ lookupFields: [],
116
+ summaryFields: [],
117
+ },
118
+ ],
119
+ };
120
+
121
+ mockFetch.mockResolvedValueOnce({
122
+ ok: true,
123
+ status: 200,
124
+ json: () => Promise.resolve(mockResponse),
125
+ });
126
+
127
+ const result = await client.getRelationships({
128
+ tableId: QB_TABLE_ID_2, // Corrected from QB_TABLE_ID_1
129
+ });
130
+
131
+ expect(mockFetch).toHaveBeenCalledWith(
132
+ `https://api.quickbase.com/v1/tables/${QB_TABLE_ID_2}/relationships`,
133
+ expect.objectContaining({
134
+ method: "GET",
135
+ headers: expect.objectContaining({
136
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
137
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
138
+ "Content-Type": "application/json",
139
+ }),
140
+ })
141
+ );
142
+
143
+ expect(result).toEqual(mockResponse);
144
+ });
145
+
146
+ it("handles API error response", async () => {
147
+ mockFetch.mockResolvedValueOnce({
148
+ ok: false,
149
+ status: 404,
150
+ json: () => Promise.resolve({ message: "Table not found" }),
151
+ });
152
+
153
+ await expect(
154
+ client.getRelationships({
155
+ tableId: QB_TABLE_ID_2, // Corrected from QB_TABLE_ID_1
156
+ skip: 0,
157
+ })
158
+ ).rejects.toThrow("API Error: Table not found (Status: 404)");
159
+
160
+ expect(mockFetch).toHaveBeenCalledWith(
161
+ `https://api.quickbase.com/v1/tables/${QB_TABLE_ID_2}/relationships?skip=0`,
162
+ expect.objectContaining({
163
+ method: "GET",
164
+ headers: expect.objectContaining({
165
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
166
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
167
+ "Content-Type": "application/json",
168
+ }),
169
+ })
170
+ );
171
+ });
172
+
173
+ it("retries with temp token after 401", async () => {
174
+ const mockResponse: GetRelationships200Response = {
175
+ metadata: {
176
+ numRelationships: 1,
177
+ skip: 0,
178
+ totalRelationships: 1,
179
+ },
180
+ relationships: [
181
+ {
182
+ id: 6,
183
+ parentTableId: QB_TABLE_ID_1,
184
+ childTableId: QB_TABLE_ID_2,
185
+ foreignKeyField: {
186
+ id: 6,
187
+ label: "Related record",
188
+ type: "numeric",
189
+ },
190
+ isCrossApp: false,
191
+ },
192
+ ],
193
+ };
194
+
195
+ mockFetch
196
+ .mockResolvedValueOnce({
197
+ ok: true,
198
+ status: 200,
199
+ json: () =>
200
+ Promise.resolve({ temporaryAuthorization: "initial_token" }),
201
+ })
202
+ .mockResolvedValueOnce({
203
+ ok: false,
204
+ status: 401,
205
+ json: () => Promise.resolve({ message: "Unauthorized" }),
206
+ })
207
+ .mockResolvedValueOnce({
208
+ ok: true,
209
+ status: 200,
210
+ json: () => Promise.resolve({ temporaryAuthorization: "new_token" }),
211
+ })
212
+ .mockResolvedValueOnce({
213
+ ok: true,
214
+ status: 200,
215
+ json: () => Promise.resolve(mockResponse),
216
+ });
217
+
218
+ const tempClient = createClient(mockFetch, {
219
+ useTempTokens: true,
220
+ debug: true,
221
+ });
222
+ const result = await tempClient.getRelationships({
223
+ tableId: QB_TABLE_ID_2,
224
+ skip: 0,
225
+ });
226
+
227
+ expect(mockFetch).toHaveBeenCalledTimes(4);
228
+ expect(mockFetch).toHaveBeenNthCalledWith(
229
+ 1,
230
+ `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_2}`,
231
+ expect.any(Object)
232
+ );
233
+ expect(mockFetch).toHaveBeenNthCalledWith(
234
+ 2,
235
+ `https://api.quickbase.com/v1/tables/${QB_TABLE_ID_2}/relationships?skip=0`,
236
+ expect.objectContaining({
237
+ headers: expect.objectContaining({
238
+ Authorization: "QB-TEMP-TOKEN initial_token",
239
+ }),
240
+ })
241
+ );
242
+ expect(mockFetch).toHaveBeenNthCalledWith(
243
+ 3,
244
+ `https://api.quickbase.com/v1/auth/temporary/${QB_TABLE_ID_2}`,
245
+ expect.any(Object)
246
+ );
247
+ expect(mockFetch).toHaveBeenNthCalledWith(
248
+ 4,
249
+ `https://api.quickbase.com/v1/tables/${QB_TABLE_ID_2}/relationships?skip=0`,
250
+ expect.objectContaining({
251
+ headers: expect.objectContaining({
252
+ Authorization: "QB-TEMP-TOKEN new_token",
253
+ }),
254
+ })
255
+ );
256
+
257
+ expect(result).toEqual(mockResponse);
258
+ });
259
+ });