quickbase-js 1.0.1-beta.0 → 1.1.0-beta.1
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/CHANGELOG.md +38 -0
- package/dist/{quickbaseClient.d.ts → quickbase.d.ts} +344 -339
- package/dist/{quickbaseClient.js → quickbase.js} +350 -266
- package/dist/quickbase.js.map +1 -0
- package/examples/react.js +42 -16
- package/examples/vanillajs.html +32 -8
- package/log-gen.yaml +3513 -0
- package/package.json +13 -9
- package/rollup.config.js +2 -2
- package/src/code-generation/fix-spec-definitions.ts +473 -66
- package/src/code-generation/fix-spec-paths.ts +210 -18
- package/src/code-generation/generate-unified-interface.ts +1 -8
- package/src/code-generation/output/quickbase-fixed.json +783 -1138
- package/src/generated-unified/QuickbaseClient.ts +10 -9
- package/src/log-gen.ts +82 -35
- package/src/quickbaseClient.ts +39 -42
- package/test-artifacts/test-results.json +173 -1145
- package/tests/playwright/qb/auth/cacheSwitching.test.ts +4 -4
- package/tests/playwright/qb/auth/fetchTempToken401.test.ts +2 -2
- package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +2 -2
- package/tests/playwright/qb/auth/getTempToken.test.ts +2 -2
- package/tests/playwright/qb/auth/tokenPrefetch.test.ts +2 -2
- package/tests/playwright/qb/auth/tokenRenewal.test.ts +2 -2
- package/tests/setup.ts +37 -9
- package/tests/vitest/qb/apps/getApp.test.ts +37 -43
- package/tests/vitest/qb/fields/getFields.test.ts +3 -5
- package/tests/vitest/qb/records/deleteRecords.test.ts +78 -0
- package/tests/vitest/qb/records/runQuery.test.ts +82 -0
- package/tests/vitest/qb/records/upsert.test.ts +72 -0
- package/tests/vitest/qb/tables/createTable.test.ts +55 -0
- package/tests/vitest/qb/tables/deleteTable.test.ts +50 -0
- package/tests/vitest/qb/tables/getAppTables.test.ts +43 -64
- package/tests/vitest/qb/tables/getTable.test.ts +26 -0
- package/tests/vitest/qb/tables/updateTable.test.ts +48 -0
- package/tests/vitest/unit/apps/getApp.test.ts +17 -12
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +32 -6
- package/tests/vitest/unit/auth/getTempToken.test.ts +36 -24
- package/tests/vitest/unit/auth/retryOn401.test.ts +39 -5
- package/tests/vitest/unit/auth/two401s.test.ts +1 -1
- package/tests/vitest/unit/fields/getFields.test.ts +14 -7
- package/tests/vitest/unit/records/deleteRecords.test.ts +112 -0
- package/tests/vitest/unit/records/runQuery.test.ts +102 -0
- package/tests/vitest/unit/records/upsert.test.ts +218 -0
- package/tests/vitest/unit/tables/createTable.test.ts +70 -0
- package/tests/vitest/unit/tables/deleteTable.test.ts +77 -0
- package/tests/vitest/unit/tables/getAppTables.test.ts +41 -28
- package/tests/vitest/unit/tables/getTable.test.ts +233 -0
- package/tests/vitest/unit/tables/updateTable.test.ts +80 -0
- package/tsconfig.json +3 -2
- package/vitest.config.ts +8 -2
- package/dist/quickbaseClient.js.map +0 -1
- package/logGen.yaml +0 -1820
- package/src/utils.ts +0 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/playwright/qb/auth/cacheSwitching.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
|
|
@@ -67,13 +67,13 @@ test.describe("QuickbaseClient Integration - Cache Switching with Temp Tokens",
|
|
|
67
67
|
console.log("Starting cacheSwitching test");
|
|
68
68
|
const realm = process.env.QB_REALM;
|
|
69
69
|
const appId = process.env.QB_APP_ID;
|
|
70
|
-
const tableId = process.env.
|
|
70
|
+
const tableId = process.env.QB_TABLE_ID_1;
|
|
71
71
|
const username = process.env.QB_USERNAME;
|
|
72
72
|
const password = process.env.QB_PASSWORD;
|
|
73
73
|
|
|
74
74
|
if (!realm) throw new Error("QB_REALM is not defined in .env");
|
|
75
75
|
if (!appId) throw new Error("QB_APP_ID is not defined in .env");
|
|
76
|
-
if (!tableId) throw new Error("
|
|
76
|
+
if (!tableId) throw new Error("QB_TABLE_ID_1 is not defined in .env");
|
|
77
77
|
if (!username) throw new Error("QB_USERNAME is not defined in .env");
|
|
78
78
|
if (!password) throw new Error("QB_PASSWORD is not defined in .env");
|
|
79
79
|
|
|
@@ -137,7 +137,7 @@ test.describe("QuickbaseClient Integration - Cache Switching with Temp Tokens",
|
|
|
137
137
|
return fetchResponse;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
const client =
|
|
140
|
+
const client = quickbase({
|
|
141
141
|
realm,
|
|
142
142
|
useTempTokens: true,
|
|
143
143
|
debug: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/playwright/qb/auth/tokenInvalidation.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
|
|
@@ -141,7 +141,7 @@ test.describe("QuickbaseClient Integration - Token Invalidation with Cached Toke
|
|
|
141
141
|
return fetchResponse;
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
const client =
|
|
144
|
+
const client = quickbase({
|
|
145
145
|
realm,
|
|
146
146
|
useTempTokens: true,
|
|
147
147
|
debug: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/integration/auth/getAppWithUserToken.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import dotenv from "dotenv";
|
|
5
5
|
|
|
6
6
|
dotenv.config();
|
|
@@ -89,7 +89,7 @@ test.describe("QuickbaseClient Integration - getApp with User Token", () => {
|
|
|
89
89
|
console.log("Post-login URL after app navigation:", currentUrl);
|
|
90
90
|
|
|
91
91
|
// Create Quickbase client with user token
|
|
92
|
-
const client =
|
|
92
|
+
const client = quickbase({
|
|
93
93
|
realm,
|
|
94
94
|
userToken, // Use user token instead of temp tokens
|
|
95
95
|
debug: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/integration/auth/getTempToken.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
|
|
@@ -132,7 +132,7 @@ test.describe("QuickbaseClient Integration - getApp with Temp Tokens", () => {
|
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
// Single client with conditional fetch
|
|
135
|
-
const client =
|
|
135
|
+
const client = quickbase({
|
|
136
136
|
realm,
|
|
137
137
|
useTempTokens: true,
|
|
138
138
|
debug: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/playwright/qb/auth/tokenPrefetch.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
|
|
@@ -134,7 +134,7 @@ test.describe("QuickbaseClient Integration - Token Pre-Fetch and Cache Reuse", (
|
|
|
134
134
|
return fetchResponse;
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
-
const client =
|
|
137
|
+
const client = quickbase({
|
|
138
138
|
realm,
|
|
139
139
|
useTempTokens: true,
|
|
140
140
|
debug: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// tests/playwright/qb/auth/tokenRenewal.test.ts
|
|
2
2
|
import { test, expect } from "@playwright/test";
|
|
3
|
-
import {
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient.ts";
|
|
4
4
|
import dotenv from "dotenv";
|
|
5
5
|
|
|
6
6
|
dotenv.config();
|
|
@@ -70,7 +70,7 @@ test.describe("QuickbaseClient Integration - Temp Token Renewal", () => {
|
|
|
70
70
|
});
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
const client =
|
|
73
|
+
const client = quickbase({
|
|
74
74
|
realm,
|
|
75
75
|
useTempTokens: true,
|
|
76
76
|
debug: true,
|
package/tests/setup.ts
CHANGED
|
@@ -1,19 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
import dotenv from "dotenv";
|
|
1
|
+
// @tests/setup.ts
|
|
3
2
|
import { vi } from "vitest";
|
|
3
|
+
import { quickbase } from "../src/quickbaseClient.ts";
|
|
4
|
+
import type { QuickbaseConfig } from "../src/quickbaseClient.ts";
|
|
5
|
+
import dotenv from "dotenv";
|
|
6
|
+
|
|
7
|
+
// Load environment variables from .env file
|
|
8
|
+
dotenv.config({ path: "./.env" }); // Assumes .env is at project root
|
|
9
|
+
|
|
10
|
+
export const mockFetch = vi.fn();
|
|
11
|
+
|
|
12
|
+
export const QB_REALM = process.env.QB_REALM || "test-realm";
|
|
13
|
+
export const QB_USER_TOKEN =
|
|
14
|
+
process.env.QB_USER_TOKEN || "user-token-1234567890";
|
|
15
|
+
export const QB_APP_ID = process.env.QB_APP_ID || "app-id-1234567890";
|
|
16
|
+
export const QB_TABLE_ID_1 = process.env.QB_TABLE_ID_1 || "table-id-1234567890";
|
|
4
17
|
|
|
5
|
-
|
|
18
|
+
// Mock env variables for consistency, using .env values if available
|
|
19
|
+
vi.stubEnv("QB_REALM", QB_REALM);
|
|
20
|
+
vi.stubEnv("QB_USER_TOKEN", QB_USER_TOKEN);
|
|
21
|
+
vi.stubEnv("QB_APP_ID", QB_APP_ID);
|
|
22
|
+
vi.stubEnv("QB_TABLE_ID_1", QB_TABLE_ID_1);
|
|
6
23
|
|
|
7
24
|
export const createClient = (
|
|
8
25
|
fetchApi?: any,
|
|
9
26
|
config: Partial<QuickbaseConfig> = {}
|
|
10
|
-
) =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
) => {
|
|
28
|
+
// Use loaded env vars with fallbacks for safety
|
|
29
|
+
const realm = QB_REALM;
|
|
30
|
+
const userToken = QB_USER_TOKEN;
|
|
31
|
+
|
|
32
|
+
const client = quickbase({
|
|
33
|
+
realm,
|
|
34
|
+
userToken,
|
|
14
35
|
debug: true,
|
|
15
36
|
fetchApi,
|
|
37
|
+
...config, // Allow overrides if provided
|
|
38
|
+
});
|
|
39
|
+
console.log("[createClient] Config:", {
|
|
40
|
+
realm,
|
|
41
|
+
userToken,
|
|
42
|
+
debug: true,
|
|
16
43
|
...config,
|
|
17
44
|
});
|
|
18
|
-
|
|
19
|
-
|
|
45
|
+
console.log("[createClient] Returning:", client);
|
|
46
|
+
return client;
|
|
47
|
+
};
|
|
@@ -1,46 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { quickbase } from "../../../../src/quickbaseClient";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
test(
|
|
5
|
+
"QuickbaseClient Integration - getApp > fetches real app data from QuickBase",
|
|
6
|
+
{ timeout: 10000 },
|
|
7
|
+
async () => {
|
|
8
|
+
const config = {
|
|
9
|
+
realm: process.env.QB_REALM || "",
|
|
10
|
+
userToken: process.env.QB_USER_TOKEN || "",
|
|
11
|
+
debug: true,
|
|
12
|
+
};
|
|
13
|
+
const client = quickbase(config);
|
|
14
|
+
const getAppId = "buwai2zpe";
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const getAppId = process.env.QB_APP_ID;
|
|
11
|
-
if (!getAppId) throw new Error("QB_APP_ID is not defined in .env");
|
|
12
|
-
if (!process.env.QB_REALM)
|
|
13
|
-
throw new Error("QB_REALM is not defined in .env");
|
|
14
|
-
if (!process.env.QB_USER_TOKEN)
|
|
15
|
-
throw new Error("QB_USER_TOKEN is not defined in .env");
|
|
16
|
+
console.log("Config used:", config);
|
|
17
|
+
const result = await client.getApp({ appId: getAppId });
|
|
18
|
+
console.log("Real API response:", result);
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
hideFromPublic: false,
|
|
39
|
-
mustBeRealmApproved: false,
|
|
40
|
-
useIPFilter: false,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
},
|
|
44
|
-
{ timeout: 10000 }
|
|
45
|
-
);
|
|
46
|
-
});
|
|
20
|
+
expect(result).toEqual({
|
|
21
|
+
id: getAppId,
|
|
22
|
+
name: "qb-copy",
|
|
23
|
+
created: expect.any(Date), // Matches Date object from client
|
|
24
|
+
updated: expect.any(Date), // Matches Date object from client
|
|
25
|
+
description: "",
|
|
26
|
+
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
27
|
+
dateFormat: "MM-DD-YYYY",
|
|
28
|
+
hasEveryoneOnTheInternet: false,
|
|
29
|
+
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
30
|
+
securityProperties: {
|
|
31
|
+
allowClone: false,
|
|
32
|
+
allowExport: true,
|
|
33
|
+
enableAppTokens: true,
|
|
34
|
+
hideFromPublic: false,
|
|
35
|
+
mustBeRealmApproved: false,
|
|
36
|
+
useIPFilter: false,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { createClient } from "../../../setup.ts";
|
|
2
|
+
import { createClient, QB_TABLE_ID_1 } from "../../../setup.ts";
|
|
3
3
|
|
|
4
4
|
describe("QuickbaseClient Integration - getFields", () => {
|
|
5
5
|
const client = createClient();
|
|
@@ -7,8 +7,6 @@ describe("QuickbaseClient Integration - getFields", () => {
|
|
|
7
7
|
it(
|
|
8
8
|
"fetches real field data from QuickBase",
|
|
9
9
|
async () => {
|
|
10
|
-
const tableId = "buwai2z3s";
|
|
11
|
-
if (!tableId) throw new Error("Table ID is not defined");
|
|
12
10
|
if (!process.env.QB_REALM)
|
|
13
11
|
throw new Error("QB_REALM is not defined in .env");
|
|
14
12
|
if (!process.env.QB_USER_TOKEN)
|
|
@@ -17,10 +15,10 @@ describe("QuickbaseClient Integration - getFields", () => {
|
|
|
17
15
|
console.log("Config used:", {
|
|
18
16
|
realm: process.env.QB_REALM,
|
|
19
17
|
userToken: process.env.QB_USER_TOKEN,
|
|
20
|
-
tableId,
|
|
18
|
+
tableId: QB_TABLE_ID_1,
|
|
21
19
|
});
|
|
22
20
|
const result = await client.getFields({
|
|
23
|
-
tableId,
|
|
21
|
+
tableId: QB_TABLE_ID_1,
|
|
24
22
|
includeFieldPerms: true,
|
|
25
23
|
});
|
|
26
24
|
console.log("Real API response:", result);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// tests/vitest/qb/records/deleteRecords.test.ts
|
|
2
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { quickbase } from "@/quickbaseClient.ts";
|
|
4
|
+
|
|
5
|
+
const TABLE_ID = "buwai2zws";
|
|
6
|
+
const UNIQUE_FIELD_ID = 3; // Record ID field
|
|
7
|
+
const MARKER_FIELD_ID = 6; // Text field for marking test records
|
|
8
|
+
|
|
9
|
+
describe("QuickbaseClient - DeleteRecords Integration", () => {
|
|
10
|
+
const qb = quickbase({
|
|
11
|
+
realm: "builderprogram-dbradford6815",
|
|
12
|
+
userToken: process.env.QB_USER_TOKEN,
|
|
13
|
+
debug: true,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
beforeEach(async () => {
|
|
17
|
+
try {
|
|
18
|
+
await qb.deleteRecords({
|
|
19
|
+
body: {
|
|
20
|
+
from: TABLE_ID,
|
|
21
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// Ignore if no records exist
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(async () => {
|
|
30
|
+
try {
|
|
31
|
+
await qb.deleteRecords({
|
|
32
|
+
body: {
|
|
33
|
+
from: TABLE_ID,
|
|
34
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
} catch (e) {}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test(
|
|
41
|
+
"deletes a newly upserted record",
|
|
42
|
+
async () => {
|
|
43
|
+
const upsertResponse = await qb.upsert({
|
|
44
|
+
body: {
|
|
45
|
+
to: TABLE_ID,
|
|
46
|
+
data: [{ [MARKER_FIELD_ID]: { value: "test-marker-delete" } }],
|
|
47
|
+
fieldsToReturn: [UNIQUE_FIELD_ID], // Return record ID
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
const recordId = upsertResponse.metadata.createdRecordIds[0];
|
|
51
|
+
expect(recordId).toBeDefined();
|
|
52
|
+
expect(upsertResponse.data[0][UNIQUE_FIELD_ID].value).toBe(recordId);
|
|
53
|
+
|
|
54
|
+
const deleteResponse = await qb.deleteRecords({
|
|
55
|
+
body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(deleteResponse).toEqual({ numberDeleted: 1 });
|
|
59
|
+
|
|
60
|
+
const checkResponse = await qb.deleteRecords({
|
|
61
|
+
body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
|
|
62
|
+
});
|
|
63
|
+
expect(checkResponse.numberDeleted).toBe(0);
|
|
64
|
+
},
|
|
65
|
+
{ timeout: 10000 }
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
test(
|
|
69
|
+
"handles empty result when no records match",
|
|
70
|
+
async () => {
|
|
71
|
+
const response = await qb.deleteRecords({
|
|
72
|
+
body: { from: TABLE_ID, where: "{3.EX.'999999'}" },
|
|
73
|
+
});
|
|
74
|
+
expect(response).toEqual({ numberDeleted: 0 });
|
|
75
|
+
},
|
|
76
|
+
{ timeout: 10000 }
|
|
77
|
+
);
|
|
78
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// tests/vitest/qb/records/runQuery.test.ts
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { createClient, QB_TABLE_ID_1 } from "../../../setup.ts"; // Import QB_TABLE_ID_1
|
|
4
|
+
import { RunQueryRequest, RunQueryResponse } from "@/generated/models";
|
|
5
|
+
|
|
6
|
+
describe("QuickbaseClient Integration - runQuery", () => {
|
|
7
|
+
let createdRecordId: number;
|
|
8
|
+
|
|
9
|
+
it(
|
|
10
|
+
"queries real records from QuickBase",
|
|
11
|
+
async () => {
|
|
12
|
+
const client = createClient();
|
|
13
|
+
|
|
14
|
+
// Upsert a test record to query later
|
|
15
|
+
const upsertResponse = await client.upsert({
|
|
16
|
+
body: {
|
|
17
|
+
to: QB_TABLE_ID_1,
|
|
18
|
+
data: [
|
|
19
|
+
{
|
|
20
|
+
"6": { value: "Test Task " + Date.now() }, // Assuming field 6 is a text field
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
fieldsToReturn: [3, 6], // Record ID# and the text field
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
createdRecordId = upsertResponse.metadata.createdRecordIds[0];
|
|
27
|
+
console.log("Created test record with ID:", createdRecordId);
|
|
28
|
+
|
|
29
|
+
// Query the record
|
|
30
|
+
const queryRequest: RunQueryRequest = {
|
|
31
|
+
from: QB_TABLE_ID_1,
|
|
32
|
+
select: [3, 6], // Query Record ID# and the text field
|
|
33
|
+
where: `{3.EX.${createdRecordId}}`, // Filter by the created record
|
|
34
|
+
sortBy: [{ fieldId: 6, order: "ASC" }],
|
|
35
|
+
options: { skip: 0, top: 1 },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
console.log("Config used:", {
|
|
39
|
+
realm: process.env.QB_REALM,
|
|
40
|
+
userToken: process.env.QB_USER_TOKEN,
|
|
41
|
+
tableId: QB_TABLE_ID_1,
|
|
42
|
+
});
|
|
43
|
+
console.log("Query request:", queryRequest);
|
|
44
|
+
const response: RunQueryResponse = await client.runQuery({
|
|
45
|
+
body: queryRequest,
|
|
46
|
+
});
|
|
47
|
+
console.log("Real API response:", response);
|
|
48
|
+
|
|
49
|
+
// Assertions
|
|
50
|
+
expect(response.data).toHaveLength(1);
|
|
51
|
+
expect(response.data[0]["3"].value).toBe(createdRecordId);
|
|
52
|
+
expect(response.data[0]["6"].value).toContain("Test Task");
|
|
53
|
+
expect(response.fields).toContainEqual({
|
|
54
|
+
id: 3,
|
|
55
|
+
label: expect.any(String),
|
|
56
|
+
type: expect.any(String),
|
|
57
|
+
});
|
|
58
|
+
expect(response.fields).toContainEqual({
|
|
59
|
+
id: 6,
|
|
60
|
+
label: expect.any(String),
|
|
61
|
+
type: expect.any(String),
|
|
62
|
+
});
|
|
63
|
+
expect(response.metadata).toMatchObject({
|
|
64
|
+
numFields: 2,
|
|
65
|
+
numRecords: 1,
|
|
66
|
+
skip: 0,
|
|
67
|
+
top: 1,
|
|
68
|
+
totalRecords: expect.any(Number),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Cleanup: Delete the test record
|
|
72
|
+
await client.deleteRecords({
|
|
73
|
+
body: {
|
|
74
|
+
from: QB_TABLE_ID_1,
|
|
75
|
+
where: `{3.EX.${createdRecordId}}`, // Assuming field 3 is Record ID#
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
console.log("Cleaned up test record with ID:", createdRecordId);
|
|
79
|
+
},
|
|
80
|
+
{ timeout: 10000 }
|
|
81
|
+
);
|
|
82
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// tests/vitest/qb/records/upsert.test.ts
|
|
2
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { quickbase } from "@/quickbaseClient.ts";
|
|
4
|
+
|
|
5
|
+
const TABLE_ID = "buwai2zws";
|
|
6
|
+
const MARKER_FIELD_ID = 6; // Text field for marking test records
|
|
7
|
+
|
|
8
|
+
describe("QuickbaseClient - Upsert Integration", () => {
|
|
9
|
+
const qb = quickbase({
|
|
10
|
+
realm: "builderprogram-dbradford6815",
|
|
11
|
+
userToken: process.env.QB_USER_TOKEN,
|
|
12
|
+
debug: true,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
try {
|
|
17
|
+
await qb.deleteRecords({
|
|
18
|
+
body: {
|
|
19
|
+
from: TABLE_ID,
|
|
20
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
} catch (e) {
|
|
24
|
+
// Ignore if no records exist
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
try {
|
|
30
|
+
await qb.deleteRecords({
|
|
31
|
+
body: {
|
|
32
|
+
from: TABLE_ID,
|
|
33
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
} catch (e) {}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test(
|
|
40
|
+
"creates a new record successfully",
|
|
41
|
+
async () => {
|
|
42
|
+
const response = await qb.upsert({
|
|
43
|
+
body: {
|
|
44
|
+
to: TABLE_ID,
|
|
45
|
+
data: [{ [MARKER_FIELD_ID]: { value: "test-marker-upsert" } }],
|
|
46
|
+
fieldsToReturn: [MARKER_FIELD_ID, 3], // Return marker and record ID
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(response.metadata.createdRecordIds.length).toBe(1);
|
|
51
|
+
expect(response.data).toHaveLength(1);
|
|
52
|
+
expect(response.data[0][MARKER_FIELD_ID].value).toBe(
|
|
53
|
+
"test-marker-upsert"
|
|
54
|
+
);
|
|
55
|
+
expect(response.data[0][3].value).toBeDefined(); // Record ID assigned by QuickBase
|
|
56
|
+
expect(response.metadata.totalNumberOfRecordsProcessed).toBe(1);
|
|
57
|
+
},
|
|
58
|
+
{ timeout: 10000 }
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
test(
|
|
62
|
+
"handles empty data gracefully",
|
|
63
|
+
async () => {
|
|
64
|
+
await expect(
|
|
65
|
+
qb.upsert({
|
|
66
|
+
body: { to: TABLE_ID, data: [] },
|
|
67
|
+
})
|
|
68
|
+
).rejects.toThrow("API Error: Bad Request (Status: 400)");
|
|
69
|
+
},
|
|
70
|
+
{ timeout: 10000 }
|
|
71
|
+
);
|
|
72
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { quickbase } from "../../../../src/quickbaseClient";
|
|
3
|
+
|
|
4
|
+
test(
|
|
5
|
+
"QuickbaseClient Integration - createTable > creates a new table in QuickBase",
|
|
6
|
+
{ timeout: 10000 },
|
|
7
|
+
async () => {
|
|
8
|
+
const config = {
|
|
9
|
+
realm: process.env.QB_REALM || "",
|
|
10
|
+
userToken: process.env.QB_USER_TOKEN || "",
|
|
11
|
+
debug: true,
|
|
12
|
+
};
|
|
13
|
+
const client = quickbase(config);
|
|
14
|
+
const appId = "buwai2zpe";
|
|
15
|
+
|
|
16
|
+
const tableName = `TestTable_${Date.now()}`;
|
|
17
|
+
const createBody = {
|
|
18
|
+
name: tableName,
|
|
19
|
+
description: "Test table creation",
|
|
20
|
+
singleRecordName: "TestRecord",
|
|
21
|
+
pluralRecordName: "TestRecords",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
console.log("Config used:", config);
|
|
25
|
+
console.log("Creating table with:", createBody);
|
|
26
|
+
const response = await client.createTable({ appId, body: createBody });
|
|
27
|
+
|
|
28
|
+
expect(response).toBeDefined();
|
|
29
|
+
expect(response.id).toBeDefined();
|
|
30
|
+
expect(response.name).toBe(tableName);
|
|
31
|
+
expect(response.description).toBe(createBody.description);
|
|
32
|
+
expect(response.singleRecordName).toBe(createBody.singleRecordName);
|
|
33
|
+
expect(response.pluralRecordName).toBe(createBody.pluralRecordName);
|
|
34
|
+
expect(response.alias).toMatch(/^_DBID_/);
|
|
35
|
+
expect(response.created).toBeInstanceOf(Date);
|
|
36
|
+
expect(response.updated).toBeInstanceOf(Date);
|
|
37
|
+
expect(response.nextRecordId).toBeGreaterThanOrEqual(1);
|
|
38
|
+
expect(response.nextFieldId).toBeGreaterThanOrEqual(1);
|
|
39
|
+
expect(response.defaultSortFieldId).toBeGreaterThanOrEqual(0);
|
|
40
|
+
expect(response.keyFieldId).toBeGreaterThanOrEqual(1);
|
|
41
|
+
expect(response.sizeLimit).toMatch(/^\d+\sMB$/); // e.g., "500 MB"
|
|
42
|
+
expect(response.spaceUsed).toMatch(/^\d+\s(KB|MB)$/); // e.g., "0 KB"
|
|
43
|
+
expect(response.spaceRemaining).toMatch(/^\d+\sMB$/); // e.g., "500 MB"
|
|
44
|
+
|
|
45
|
+
console.log("Real API response:", response);
|
|
46
|
+
|
|
47
|
+
// Cleanup: Delete the table to avoid clutter
|
|
48
|
+
const deleteResponse = await client.deleteTable({
|
|
49
|
+
tableId: response.id,
|
|
50
|
+
appId,
|
|
51
|
+
});
|
|
52
|
+
expect(deleteResponse.deletedTableId).toBe(response.id);
|
|
53
|
+
console.log("Cleanup - Deleted table:", deleteResponse);
|
|
54
|
+
}
|
|
55
|
+
);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { quickbase } from "../../../../src/quickbaseClient";
|
|
3
|
+
|
|
4
|
+
test(
|
|
5
|
+
"QuickbaseClient Integration - deleteTable > deletes a table in QuickBase",
|
|
6
|
+
{ timeout: 20000 },
|
|
7
|
+
async () => {
|
|
8
|
+
const config = {
|
|
9
|
+
realm: process.env.QB_REALM || "",
|
|
10
|
+
userToken: process.env.QB_USER_TOKEN || "",
|
|
11
|
+
debug: true,
|
|
12
|
+
};
|
|
13
|
+
const client = quickbase(config);
|
|
14
|
+
const appId = "buwai2zpe";
|
|
15
|
+
|
|
16
|
+
// Step 1: Create a temporary table to delete
|
|
17
|
+
const tableName = `DeleteTest_${Date.now()}`;
|
|
18
|
+
const createBody = {
|
|
19
|
+
name: tableName,
|
|
20
|
+
description: "Temporary table for delete test",
|
|
21
|
+
singleRecordName: "DeleteTest",
|
|
22
|
+
pluralRecordName: "DeleteTests",
|
|
23
|
+
};
|
|
24
|
+
console.log("Creating temporary table with:", createBody);
|
|
25
|
+
const createResponse = await client.createTable({
|
|
26
|
+
appId,
|
|
27
|
+
body: createBody,
|
|
28
|
+
});
|
|
29
|
+
expect(createResponse.id).toBeDefined();
|
|
30
|
+
expect(createResponse.name).toBe(tableName);
|
|
31
|
+
console.log("Created table:", createResponse);
|
|
32
|
+
const tableId = createResponse.id;
|
|
33
|
+
|
|
34
|
+
// Step 2: Delete the table
|
|
35
|
+
console.log("Deleting table:", { tableId, appId });
|
|
36
|
+
const deleteResponse = await client.deleteTable({ tableId, appId });
|
|
37
|
+
expect(deleteResponse).toBeDefined();
|
|
38
|
+
expect(deleteResponse.deletedTableId).toBe(tableId);
|
|
39
|
+
console.log("Delete API response:", deleteResponse);
|
|
40
|
+
|
|
41
|
+
// Step 3: Verify the table is gone
|
|
42
|
+
try {
|
|
43
|
+
await client.getTable({ tableId, appId });
|
|
44
|
+
throw new Error("Table should not exist after deletion");
|
|
45
|
+
} catch (error) {
|
|
46
|
+
expect(error.message).toMatch(/404|not found/i); // Expect a 404 error
|
|
47
|
+
console.log("Verified table deletion:", error.message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
);
|