Skip to content

Commit f47f172

Browse files
committed
test(*): finish test setup
1 parent d8b9be1 commit f47f172

File tree

8 files changed

+183
-3
lines changed

8 files changed

+183
-3
lines changed

test/_mocks/create-loader-context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export function createLoaderContext(
1212
logger: new LoggerMock(),
1313
parseData: vi.fn().mockResolvedValue({}),
1414
store: new StoreMock(),
15+
meta: new Map<string, string>(),
1516
...context
1617
} satisfies Partial<LoaderContext> as unknown as LoaderContext;
1718
}

test/_mocks/create-pocketbase-entry.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export function createPocketbaseEntry(
99
collectionId: Math.random().toString(36).substring(2, 17),
1010
collectionName: "test",
1111
customId: randomUUID(),
12+
updated: new Date().toISOString().replace("T", " "),
1213
...entry
1314
};
1415
}

test/_mocks/superuser_schema.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@
3636
"system": true,
3737
"type": "password"
3838
},
39+
{
40+
"hidden": true,
41+
"id": "file376926767",
42+
"maxSelect": 1,
43+
"maxSize": 0,
44+
"mimeTypes": [
45+
"image/jpeg",
46+
"image/png",
47+
"image/svg+xml",
48+
"image/gif",
49+
"image/webp"
50+
],
51+
"name": "avatar",
52+
"presentable": false,
53+
"protected": false,
54+
"required": false,
55+
"system": false,
56+
"thumbs": null,
57+
"type": "file"
58+
},
3959
{
4060
"autogeneratePattern": "[a-zA-Z0-9]{50}",
4161
"hidden": true,

test/loader/loader.spec.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import type { LoaderContext } from "astro/loaders";
2+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
3+
import packageJson from "../../package.json";
4+
import { cleanupEntries } from "../../src/loader/cleanup-entries";
5+
import { handleRealtimeUpdates } from "../../src/loader/handle-realtime-updates";
6+
import { loadEntries } from "../../src/loader/load-entries";
7+
import { loader } from "../../src/loader/loader";
8+
import { getSuperuserToken } from "../../src/utils/get-superuser-token";
9+
import { createLoaderContext } from "../_mocks/create-loader-context";
10+
import { createLoaderOptions } from "../_mocks/create-loader-options";
11+
import { createPocketbaseEntry } from "../_mocks/create-pocketbase-entry";
12+
13+
vi.mock("../../src/utils/get-superuser-token");
14+
vi.mock("../../src/utils/should-refresh");
15+
vi.mock("../../src/loader/cleanup-entries");
16+
vi.mock("../../src/loader/handle-realtime-updates");
17+
vi.mock("../../src/loader/load-entries");
18+
19+
describe("loader", async () => {
20+
let context: LoaderContext;
21+
const options = createLoaderOptions({ updatedField: "updated" });
22+
const srm = await import("../../src/utils/should-refresh");
23+
const hrum = await import("../../src/loader/handle-realtime-updates");
24+
const gstm = await import("../../src/utils/get-superuser-token");
25+
26+
beforeEach(() => {
27+
context = createLoaderContext();
28+
context.meta.set("version", packageJson.version);
29+
context.meta.set(
30+
"last-modified",
31+
new Date().toISOString().replace("T", " ")
32+
);
33+
});
34+
35+
afterEach(() => {
36+
vi.resetAllMocks();
37+
});
38+
39+
test("should not refresh if shouldRefresh returns false", async () => {
40+
srm.shouldRefresh = vi.fn().mockReturnValue(false);
41+
42+
await loader(context, options);
43+
44+
expect(srm.shouldRefresh).toHaveBeenCalledOnce();
45+
expect(handleRealtimeUpdates).not.toHaveBeenCalled();
46+
expect(loadEntries).not.toHaveBeenCalled();
47+
});
48+
49+
test("should not refresh if handleRealtimeUpdates handled update", async () => {
50+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
51+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(true);
52+
53+
await loader(context, options);
54+
55+
expect(handleRealtimeUpdates).toHaveBeenCalledOnce();
56+
expect(loadEntries).not.toHaveBeenCalled();
57+
});
58+
59+
test("should clear store and disable incremental builds if version changes", async () => {
60+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
61+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(false);
62+
gstm.getSuperuserToken = vi.fn().mockResolvedValue(undefined);
63+
const storeClearSpy = vi.spyOn(context.store, "clear");
64+
context.meta.set("version", "invalidVersion");
65+
66+
await loader(context, options);
67+
68+
expect(storeClearSpy).toHaveBeenCalledOnce();
69+
expect(loadEntries).toHaveBeenCalledWith(
70+
options,
71+
context,
72+
undefined,
73+
undefined
74+
);
75+
});
76+
77+
test("should disable incremental builds if no updatedField is provided", async () => {
78+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
79+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(false);
80+
gstm.getSuperuserToken = vi.fn().mockResolvedValue(undefined);
81+
options.updatedField = undefined;
82+
83+
await loader(context, options);
84+
85+
expect(loadEntries).toHaveBeenCalledWith(
86+
options,
87+
context,
88+
undefined,
89+
undefined
90+
);
91+
});
92+
93+
test("should get superuser token if superuserCredentials are provided", async () => {
94+
const token = "token";
95+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
96+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(false);
97+
gstm.getSuperuserToken = vi.fn().mockResolvedValue(token);
98+
const entry = createPocketbaseEntry();
99+
context.store.set({ id: entry.id, data: entry });
100+
101+
await loader(context, options);
102+
103+
expect(getSuperuserToken).toHaveBeenCalledOnce();
104+
expect(cleanupEntries).toHaveBeenCalledWith(options, context, token);
105+
expect(loadEntries).toHaveBeenCalledWith(
106+
options,
107+
context,
108+
token,
109+
undefined
110+
);
111+
});
112+
113+
test("should cleanup old entries if store has keys", async () => {
114+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
115+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(false);
116+
gstm.getSuperuserToken = vi.fn().mockResolvedValue(undefined);
117+
const entry = createPocketbaseEntry();
118+
context.store.set({ id: entry.id, data: entry });
119+
120+
await loader(context, options);
121+
122+
expect(cleanupEntries).toHaveBeenCalledWith(options, context, undefined);
123+
});
124+
125+
test("should set last-modified and version in meta after loading entries", async () => {
126+
srm.shouldRefresh = vi.fn().mockReturnValue(true);
127+
hrum.handleRealtimeUpdates = vi.fn().mockResolvedValue(false);
128+
gstm.getSuperuserToken = vi.fn().mockResolvedValue(undefined);
129+
context.meta.delete("last-modified");
130+
context.meta.delete("version");
131+
132+
await loader(context, options);
133+
134+
expect(context.meta.get("last-modified")).toBeDefined();
135+
expect(context.meta.get("version")).toBe(packageJson.version);
136+
});
137+
});

test/loader/parse-entry.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ describe("parseEntry", () => {
7575
expect(context.logger.warn).toHaveBeenCalledOnce();
7676
});
7777

78+
test("should use updated field as digest if provided", async () => {
79+
const options = createLoaderOptions({ updatedField: "updated" });
80+
81+
await parseEntry(entry, context, options);
82+
83+
expect(context.generateDigest).toHaveBeenCalledWith(entry.updated);
84+
});
85+
7886
test("should concatenate multiple content fields", async () => {
7987
const options = createLoaderOptions({
8088
contentFields: ["collectionName", "customId"]

test/schema/generate-schema.e2e-spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,14 @@ describe("generateSchema", () => {
5151
it("should return schema from local file if path is provided", async () => {
5252
const result = (await generateSchema({
5353
...options,
54+
superuserCredentials: undefined,
5455
localSchema: "test/_mocks/superuser_schema.json"
5556
})) as ZodObject<Record<string, ZodSchema<unknown>>>;
5657

5758
expect(Object.keys(result.shape)).toEqual([
5859
"id",
5960
"collectionId",
6061
"collectionName",
61-
"password",
62-
"tokenKey",
6362
"email",
6463
"emailVisibility",
6564
"verified",

test/utils/get-superuser-token.e2e-spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { beforeAll, describe, expect, it } from "vitest";
22
import { getSuperuserToken } from "../../src/utils/get-superuser-token";
33
import { checkE2eConnection } from "../_mocks/check-e2e-connection";
4+
import { createLoaderContext } from "../_mocks/create-loader-context";
45
import { createLoaderOptions } from "../_mocks/create-loader-options";
56

67
describe("getSuperuserToken", () => {
@@ -18,6 +19,18 @@ describe("getSuperuserToken", () => {
1819
expect(result).toBeUndefined();
1920
});
2021

22+
it("should use integration logger if provided", async () => {
23+
const { logger } = createLoaderContext();
24+
25+
await getSuperuserToken(
26+
options.url,
27+
{ email: "invalid", password: "invalid" },
28+
logger
29+
);
30+
31+
expect(logger.error).toHaveBeenCalled();
32+
});
33+
2134
it("should return token if fetch request is successful", async () => {
2235
const result = await getSuperuserToken(
2336
options.url,

vitest.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export default defineConfig({
55
include: ["test/**/*.spec.ts", "test/**/*.e2e-spec.ts"],
66
silent: true,
77
coverage: {
8-
include: ["src/**/*.ts"]
8+
include: ["src/**/*.ts"],
9+
exclude: ["src/types/**/*.ts", "src/index.ts", "src/pocketbase-loader.ts"]
910
}
1011
}
1112
});

0 commit comments

Comments
 (0)