@hyper-fetch/firebase-admin 7.5.2 → 8.0.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.
- package/.eslintrc.cjs +12 -0
- package/__tests__/features/firestore/admin/constraints.admin.spec.ts +23 -0
- package/__tests__/features/firestore/admin/methods.admin.spec.ts +20 -0
- package/__tests__/features/firestore/admin/sockets.base.spec.ts +17 -0
- package/__tests__/features/firestore/shared/constraints.shared.tests.ts +72 -0
- package/__tests__/features/firestore/shared/methods/add-doc.test.suite.ts +29 -0
- package/__tests__/features/firestore/shared/methods/delete-doc.test.suite.ts +52 -0
- package/__tests__/features/firestore/shared/methods/get-doc.test.suite.ts +60 -0
- package/__tests__/features/firestore/shared/methods/get-docs.test.suite.ts +45 -0
- package/__tests__/features/firestore/shared/methods/on-snapshot.test.suite.ts +290 -0
- package/__tests__/features/firestore/shared/methods/set-doc.test.suite.ts +70 -0
- package/__tests__/features/firestore/shared/methods/update-doc.test.suite.ts +40 -0
- package/__tests__/features/firestore/shared/methods.shared.tests.ts +24 -0
- package/__tests__/features/realtime/admin/constraints.admin.spec.ts +15 -0
- package/__tests__/features/realtime/admin/methods.admin.spec.ts +24 -0
- package/__tests__/features/realtime/admin/sockets.base.spec.ts +15 -0
- package/__tests__/features/realtime/shared/constraints.shared.tests.ts +57 -0
- package/__tests__/features/realtime/shared/methods/get.test.suite.ts +64 -0
- package/__tests__/features/realtime/shared/methods/on-value.test.suite.ts +190 -0
- package/__tests__/features/realtime/shared/methods/push.test.suite.ts +48 -0
- package/__tests__/features/realtime/shared/methods/remove.test.suite.ts +46 -0
- package/__tests__/features/realtime/shared/methods/set.test.suite.ts +70 -0
- package/__tests__/features/realtime/shared/methods/update.test.suite.ts +42 -0
- package/__tests__/features/realtime/shared/methods.shared.tests.ts +25 -0
- package/__tests__/shared/request-events.shared.ts +32 -0
- package/__tests__/tsconfig.json +21 -0
- package/__tests__/utils/database.rules.json +11 -0
- package/__tests__/utils/index.ts +3 -0
- package/__tests__/utils/initialize.firestore.admin.ts +16 -0
- package/__tests__/utils/initialize.realtime.admin.ts +19 -0
- package/__tests__/utils/seed/seed.data.ts +21 -0
- package/__tests__/utils/seed.admin.ts +23 -0
- package/__tests__/vitest.setup.ts +9 -0
- package/dist/adapter/adapter.d.ts +3 -0
- package/dist/adapter/adapter.d.ts.map +1 -0
- package/dist/adapter/adapter.sockets.d.ts +3 -0
- package/dist/adapter/adapter.sockets.d.ts.map +1 -0
- package/dist/adapter/index.d.ts +4 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/types/adapter.base.types.d.ts +11 -0
- package/dist/adapter/types/adapter.base.types.d.ts.map +1 -0
- package/dist/adapter/types/adapter.firestore.types.d.ts +45 -0
- package/dist/adapter/types/adapter.firestore.types.d.ts.map +1 -0
- package/dist/adapter/types/adapter.realtime.types.d.ts +39 -0
- package/dist/adapter/types/adapter.realtime.types.d.ts.map +1 -0
- package/dist/adapter/types/firestore.socket.types.d.ts +17 -0
- package/dist/adapter/types/firestore.socket.types.d.ts.map +1 -0
- package/dist/adapter/types/index.d.ts +6 -0
- package/dist/adapter/types/index.d.ts.map +1 -0
- package/dist/adapter/types/realtime.socket.types.d.ts +12 -0
- package/dist/adapter/types/realtime.socket.types.d.ts.map +1 -0
- package/dist/constraints/constraints.types.d.ts +13 -0
- package/dist/constraints/constraints.types.d.ts.map +1 -0
- package/dist/constraints/firebase.constraints.d.ts +86 -0
- package/dist/constraints/firebase.constraints.d.ts.map +1 -0
- package/dist/constraints/index.d.ts +3 -0
- package/dist/constraints/index.d.ts.map +1 -0
- package/dist/firestore/firestore.methods.d.ts +21 -0
- package/dist/firestore/firestore.methods.d.ts.map +1 -0
- package/dist/firestore/firestore.sockets.d.ts +4 -0
- package/dist/firestore/firestore.sockets.d.ts.map +1 -0
- package/dist/firestore/index.d.ts +4 -0
- package/dist/firestore/index.d.ts.map +1 -0
- package/dist/firestore/utils/constraints.utils.d.ts +5 -0
- package/dist/firestore/utils/constraints.utils.d.ts.map +1 -0
- package/dist/firestore/utils/index.d.ts +4 -0
- package/dist/firestore/utils/index.d.ts.map +1 -0
- package/dist/firestore/utils/ref.utils.d.ts +3 -0
- package/dist/firestore/utils/ref.utils.d.ts.map +1 -0
- package/dist/firestore/utils/result.utils.d.ts +10 -0
- package/dist/firestore/utils/result.utils.d.ts.map +1 -0
- package/dist/index.d.ts +5 -271
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +670 -0
- package/dist/index.mjs.map +1 -0
- package/dist/realtime/index.d.ts +4 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/realtime.methods.d.ts +19 -0
- package/dist/realtime/realtime.methods.d.ts.map +1 -0
- package/dist/realtime/realtime.sockets.d.ts +4 -0
- package/dist/realtime/realtime.sockets.d.ts.map +1 -0
- package/dist/realtime/utils/constraints.utils.d.ts +5 -0
- package/dist/realtime/utils/constraints.utils.d.ts.map +1 -0
- package/dist/realtime/utils/index.d.ts +3 -0
- package/dist/realtime/utils/index.d.ts.map +1 -0
- package/dist/realtime/utils/result.utils.d.ts +3 -0
- package/dist/realtime/utils/result.utils.d.ts.map +1 -0
- package/dist/utils/cache.utils.d.ts +11 -0
- package/dist/utils/cache.utils.d.ts.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/misc.d.ts +3 -0
- package/dist/utils/misc.d.ts.map +1 -0
- package/package.json +8 -11
- package/project.json +4 -0
- package/src/adapter/adapter.sockets.ts +1 -1
- package/src/adapter/adapter.ts +13 -14
- package/src/adapter/types/adapter.base.types.ts +4 -4
- package/src/adapter/types/adapter.firestore.types.ts +4 -4
- package/src/adapter/types/adapter.realtime.types.ts +4 -4
- package/src/adapter/types/firestore.socket.types.ts +3 -3
- package/src/adapter/types/realtime.socket.types.ts +3 -3
- package/src/constraints/constraints.types.ts +1 -1
- package/src/constraints/firebase.constraints.ts +1 -1
- package/src/firestore/firestore.methods.ts +4 -4
- package/src/firestore/firestore.sockets.ts +3 -9
- package/src/firestore/utils/constraints.utils.ts +4 -3
- package/src/firestore/utils/ref.utils.ts +1 -1
- package/src/firestore/utils/result.utils.ts +1 -1
- package/src/realtime/realtime.methods.ts +4 -4
- package/src/realtime/realtime.sockets.ts +2 -2
- package/src/realtime/utils/constraints.utils.ts +3 -2
- package/src/realtime/utils/result.utils.ts +1 -1
- package/src/utils/cache.utils.ts +4 -2
- package/tsconfig.json +1 -1
- package/vite.config.ts +45 -0
- package/.eslintrc.json +0 -11
- package/dist/index.js +0 -686
- package/dist/index.js.map +0 -7
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { Tea } from "../../../../utils";
|
|
4
|
+
import type { FirebaseAdminAdapter } from "adapter";
|
|
5
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
6
|
+
|
|
7
|
+
export const setDocTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("setDoc", () => {
|
|
9
|
+
it("should set data", async () => {
|
|
10
|
+
const newData = { origin: "Poland", type: "Green", year: 2023, name: "Pou Ran Do Cha", amount: 10 } as Tea;
|
|
11
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
12
|
+
const getReq = client
|
|
13
|
+
.createRequest<{ response: Tea }>()({
|
|
14
|
+
endpoint: ":teaId",
|
|
15
|
+
method: "getDoc",
|
|
16
|
+
})
|
|
17
|
+
.setParams({ teaId: 1 });
|
|
18
|
+
const setReq = client
|
|
19
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
20
|
+
endpoint: ":teaId",
|
|
21
|
+
method: "setDoc",
|
|
22
|
+
})
|
|
23
|
+
.setParams({ teaId: 1 })
|
|
24
|
+
.setPayload(newData);
|
|
25
|
+
|
|
26
|
+
await setReq.send();
|
|
27
|
+
const { data } = await getReq.send();
|
|
28
|
+
|
|
29
|
+
expect(data).toStrictEqual({ ...newData, __key: "1" });
|
|
30
|
+
});
|
|
31
|
+
it("should merge data if merge options is passed", async () => {
|
|
32
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
33
|
+
const getReq = client
|
|
34
|
+
.createRequest<{ response: Tea }>()({
|
|
35
|
+
endpoint: ":teaId",
|
|
36
|
+
method: "getDoc",
|
|
37
|
+
})
|
|
38
|
+
.setParams({ teaId: 1 });
|
|
39
|
+
const { data: existingData } = await getReq.send();
|
|
40
|
+
const setReq = client
|
|
41
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
42
|
+
endpoint: ":teaId",
|
|
43
|
+
method: "setDoc",
|
|
44
|
+
options: { merge: true },
|
|
45
|
+
})
|
|
46
|
+
.setParams({ teaId: 1 })
|
|
47
|
+
.setPayload({ name: "Pou Ran Do Cha" } as Tea);
|
|
48
|
+
|
|
49
|
+
await setReq.send();
|
|
50
|
+
const { data } = await getReq.send();
|
|
51
|
+
|
|
52
|
+
expect(data).toStrictEqual({ ...existingData, name: "Pou Ran Do Cha" });
|
|
53
|
+
// expect(extra.snapshot.exists()).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
it("should emit lifecycle events", async () => {
|
|
56
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
57
|
+
|
|
58
|
+
const request = client
|
|
59
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
60
|
+
endpoint: ":teaId",
|
|
61
|
+
method: "setDoc",
|
|
62
|
+
options: { merge: true },
|
|
63
|
+
})
|
|
64
|
+
.setParams({ teaId: 1 })
|
|
65
|
+
.setPayload({ name: "Pou Ran Do Cha" } as Tea);
|
|
66
|
+
|
|
67
|
+
await testLifecycleEvents(request);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter } from "adapter";
|
|
4
|
+
import type { Tea } from "../../../../utils";
|
|
5
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
6
|
+
|
|
7
|
+
export const updateDocTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("updateDoc", () => {
|
|
9
|
+
it("should allow for updating data", async () => {
|
|
10
|
+
const newData = { name: "Pou Ran Do Cha", amount: 100, year: 966 } as Tea;
|
|
11
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
12
|
+
const updateReq = client
|
|
13
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
14
|
+
endpoint: ":teaId",
|
|
15
|
+
method: "updateDoc",
|
|
16
|
+
})
|
|
17
|
+
.setPayload(newData);
|
|
18
|
+
const getReq = client.createRequest<{ response: Tea }>()({
|
|
19
|
+
endpoint: ":teaId",
|
|
20
|
+
method: "getDoc",
|
|
21
|
+
});
|
|
22
|
+
await updateReq.send({ params: { teaId: 1 } });
|
|
23
|
+
const { data } = await getReq.send({ params: { teaId: 1 } });
|
|
24
|
+
expect(data).toStrictEqual({ ...newData, origin: "China", type: "Green", __key: "1" });
|
|
25
|
+
});
|
|
26
|
+
it("should emit lifecycle events", async () => {
|
|
27
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
28
|
+
const newData = { name: "Pou Ran Do Cha", amount: 100, year: 966 } as Tea;
|
|
29
|
+
|
|
30
|
+
const request = client
|
|
31
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
32
|
+
endpoint: ":teaId",
|
|
33
|
+
method: "updateDoc",
|
|
34
|
+
})
|
|
35
|
+
.setPayload(newData);
|
|
36
|
+
|
|
37
|
+
await testLifecycleEvents(request);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FirebaseAdminAdapter, FirebaseAdminAdapterTypes, FirebaseAdminSocketAdapterTypes } from "adapter";
|
|
2
|
+
import { addDocTestSuite } from "./methods/add-doc.test.suite";
|
|
3
|
+
import { deleteDocTestSuite } from "./methods/delete-doc.test.suite";
|
|
4
|
+
import { getDocTestSuite } from "./methods/get-doc.test.suite";
|
|
5
|
+
import { getDocsTestSuite } from "./methods/get-docs.test.suite";
|
|
6
|
+
import { setDocTestSuite } from "./methods/set-doc.test.suite";
|
|
7
|
+
import { updateDocTestSuite } from "./methods/update-doc.test.suite";
|
|
8
|
+
import { onSnapshotTestSuite } from "./methods/on-snapshot.test.suite";
|
|
9
|
+
|
|
10
|
+
export const methodsSharedTestCases = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
11
|
+
addDocTestSuite(adapterFunction);
|
|
12
|
+
deleteDocTestSuite(adapterFunction);
|
|
13
|
+
getDocTestSuite(adapterFunction);
|
|
14
|
+
getDocsTestSuite(adapterFunction);
|
|
15
|
+
setDocTestSuite(adapterFunction);
|
|
16
|
+
updateDocTestSuite(adapterFunction);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const socketsMethodsSharedTestCases = (
|
|
20
|
+
adapter: FirebaseAdminSocketAdapterTypes<any>,
|
|
21
|
+
coreAdapter: FirebaseAdminAdapterTypes<any>,
|
|
22
|
+
) => {
|
|
23
|
+
onSnapshotTestSuite(adapter, coreAdapter);
|
|
24
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FirebaseAdminAdapter } from "adapter";
|
|
2
|
+
import { seedRealtimeDatabaseAdmin } from "../../../utils/seed.admin";
|
|
3
|
+
import { realtimeDbAdmin } from "../../../utils";
|
|
4
|
+
import { constraintsSharedTestCases } from "../shared/constraints.shared.tests";
|
|
5
|
+
|
|
6
|
+
describe("Realtime Database Admin [Constraints]", () => {
|
|
7
|
+
let db: any;
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
db = await realtimeDbAdmin;
|
|
10
|
+
await db.ref("teas").set(null);
|
|
11
|
+
await seedRealtimeDatabaseAdmin(db);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
constraintsSharedTestCases(() => FirebaseAdminAdapter(db));
|
|
15
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment node
|
|
3
|
+
*/
|
|
4
|
+
import { realtimeDbAdmin, seedRealtimeDatabaseAdmin } from "../../../utils";
|
|
5
|
+
import { FirebaseAdminAdapter } from "adapter";
|
|
6
|
+
import { methodsSharedTestCases } from "../shared/methods.shared.tests";
|
|
7
|
+
|
|
8
|
+
describe("Realtime Database Admin [ Methods ]", () => {
|
|
9
|
+
let db: any;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
db = await realtimeDbAdmin;
|
|
13
|
+
});
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
await db.ref("teas").set(null);
|
|
16
|
+
await seedRealtimeDatabaseAdmin(db);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(async () => {
|
|
20
|
+
await db.ref("teas").set(null);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
methodsSharedTestCases(() => FirebaseAdminAdapter(db));
|
|
24
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment node
|
|
3
|
+
*/
|
|
4
|
+
import { realtimeDbAdmin, seedRealtimeDatabaseAdmin } from "../../../utils";
|
|
5
|
+
import { socketsMethodsSharedTestCases } from "../shared/methods.shared.tests";
|
|
6
|
+
import { FirebaseSocketsAdminAdapter, FirebaseAdminAdapter } from "adapter";
|
|
7
|
+
|
|
8
|
+
describe("Realtime Database Admin [Sockets]", () => {
|
|
9
|
+
socketsMethodsSharedTestCases(
|
|
10
|
+
realtimeDbAdmin,
|
|
11
|
+
seedRealtimeDatabaseAdmin,
|
|
12
|
+
FirebaseSocketsAdminAdapter,
|
|
13
|
+
FirebaseAdminAdapter,
|
|
14
|
+
);
|
|
15
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter } from "../../../../src";
|
|
4
|
+
import { $endAt, $limitToFirst, $orderByChild, $startAt } from "../../../../src";
|
|
5
|
+
import type { Tea } from "../../../utils";
|
|
6
|
+
|
|
7
|
+
export const constraintsSharedTestCases = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("Ordering", () => {
|
|
9
|
+
it("Should allow ordering by child", async () => {
|
|
10
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
11
|
+
const req = client.createRequest<{ response: Tea[] }>()({
|
|
12
|
+
endpoint: "",
|
|
13
|
+
method: "getDocs",
|
|
14
|
+
});
|
|
15
|
+
const { data } = await req.send({
|
|
16
|
+
queryParams: { constraints: [$orderByChild("origin")] },
|
|
17
|
+
});
|
|
18
|
+
expect(data?.map((el) => el.origin)).toStrictEqual([
|
|
19
|
+
"China",
|
|
20
|
+
"China",
|
|
21
|
+
"China",
|
|
22
|
+
"China",
|
|
23
|
+
"China",
|
|
24
|
+
"China",
|
|
25
|
+
"China",
|
|
26
|
+
"Japan",
|
|
27
|
+
"Taiwan",
|
|
28
|
+
"Taiwan",
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("Filtering and ordering", () => {
|
|
33
|
+
it("Should allow to limit the result and order it", async () => {
|
|
34
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
35
|
+
const req = client.createRequest<{ response: Tea[] }>()({
|
|
36
|
+
endpoint: "",
|
|
37
|
+
method: "getDocs",
|
|
38
|
+
});
|
|
39
|
+
const { data } = await req.send({
|
|
40
|
+
queryParams: { constraints: [$orderByChild("origin"), $limitToFirst(5)] },
|
|
41
|
+
});
|
|
42
|
+
expect(data?.map((tea) => tea.origin)).toStrictEqual(["China", "China", "China", "China", "China"]);
|
|
43
|
+
});
|
|
44
|
+
it("Should allow to combine multiple filters", async () => {
|
|
45
|
+
const client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
46
|
+
const req = client.createRequest<{ response: Tea[] }>()({
|
|
47
|
+
endpoint: "",
|
|
48
|
+
method: "getDocs",
|
|
49
|
+
});
|
|
50
|
+
const { data } = await req.send({
|
|
51
|
+
queryParams: { constraints: [$orderByChild("year"), $startAt(2021), $endAt(2022)] },
|
|
52
|
+
});
|
|
53
|
+
expect(data).toHaveLength(5);
|
|
54
|
+
expect(data?.map((tea) => tea.year)).toStrictEqual([2021, 2021, 2021, 2022, 2022]);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter } from "adapter";
|
|
4
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
5
|
+
import type { Tea } from "../../../../utils";
|
|
6
|
+
|
|
7
|
+
export const getTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("get", () => {
|
|
9
|
+
let client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
10
|
+
let clientBees = new Client({ url: "bees/" }).setAdapter(adapterFunction());
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
clientBees = new Client({ url: "bees/" }).setAdapter(adapterFunction());
|
|
13
|
+
client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should return data available for endpoint", async () => {
|
|
17
|
+
const req = client.createRequest<{ response: Tea[] }>()({
|
|
18
|
+
endpoint: "",
|
|
19
|
+
method: "get",
|
|
20
|
+
});
|
|
21
|
+
const { data, extra, status, success, error } = await req.send();
|
|
22
|
+
expect(data).toHaveLength(10);
|
|
23
|
+
expect(data![0]).toHaveProperty("__key");
|
|
24
|
+
expect(extra).toHaveProperty("snapshot");
|
|
25
|
+
expect(extra).toHaveProperty("ref");
|
|
26
|
+
expect(status).toBe("success");
|
|
27
|
+
expect(success).toBe(true);
|
|
28
|
+
expect(error).toBe(null);
|
|
29
|
+
});
|
|
30
|
+
it("should return data for dynamic endpoint", async () => {
|
|
31
|
+
const req = client
|
|
32
|
+
.createRequest<{ response: Tea }>()({
|
|
33
|
+
endpoint: ":teaId",
|
|
34
|
+
method: "get",
|
|
35
|
+
})
|
|
36
|
+
.setParams({ teaId: 1 });
|
|
37
|
+
|
|
38
|
+
const { data } = await req.send();
|
|
39
|
+
expect(data).toStrictEqual({ amount: 150, name: "Taiping Hou Kui", origin: "China", type: "Green", year: 2023 });
|
|
40
|
+
});
|
|
41
|
+
it("should return emptyResource status for non existing resource", async () => {
|
|
42
|
+
const req = clientBees
|
|
43
|
+
.createRequest<{ response: Tea }>()({
|
|
44
|
+
endpoint: ":teaId",
|
|
45
|
+
method: "get",
|
|
46
|
+
})
|
|
47
|
+
.setParams({ teaId: 1 });
|
|
48
|
+
|
|
49
|
+
const { data, status } = await req.send();
|
|
50
|
+
expect(data).toStrictEqual(null);
|
|
51
|
+
expect(status).toStrictEqual("emptyResource");
|
|
52
|
+
});
|
|
53
|
+
it("should emit lifecycle events", async () => {
|
|
54
|
+
const req = clientBees
|
|
55
|
+
.createRequest<{ response: Tea }>()({
|
|
56
|
+
endpoint: ":teaId",
|
|
57
|
+
method: "get",
|
|
58
|
+
})
|
|
59
|
+
.setParams({ teaId: 1 });
|
|
60
|
+
|
|
61
|
+
await testLifecycleEvents(req);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/* eslint-disable max-params */
|
|
2
|
+
import { Socket } from "@hyper-fetch/sockets";
|
|
3
|
+
import { Client } from "@hyper-fetch/core";
|
|
4
|
+
import waitForExpect from "wait-for-expect";
|
|
5
|
+
|
|
6
|
+
import type { FirebaseAdminAdapterTypes, FirebaseAdminSocketAdapterTypes } from "adapter";
|
|
7
|
+
import type { Tea } from "../../../../utils";
|
|
8
|
+
|
|
9
|
+
export const onValueTestSuite = (
|
|
10
|
+
db: Promise<any>,
|
|
11
|
+
seedDb: (initializedDb: any) => Promise<void>,
|
|
12
|
+
socketsAdapter: (database: any) => FirebaseAdminSocketAdapterTypes<any>,
|
|
13
|
+
coreAdapter: (database: any) => FirebaseAdminAdapterTypes<any>,
|
|
14
|
+
) => {
|
|
15
|
+
describe("when using onValue method", () => {
|
|
16
|
+
let initializedSocketsAdapter: any;
|
|
17
|
+
let initializedCoreAdapter: any;
|
|
18
|
+
let initializedDb: any;
|
|
19
|
+
let spy = vi.fn();
|
|
20
|
+
const newData = { origin: "Poland", type: "Green", year: 2043, name: "Pou Ran Do Cha", amount: 100 } as Tea;
|
|
21
|
+
|
|
22
|
+
beforeAll(async () => {
|
|
23
|
+
initializedDb = await db;
|
|
24
|
+
initializedSocketsAdapter = socketsAdapter(initializedDb);
|
|
25
|
+
initializedCoreAdapter = coreAdapter(initializedDb);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
beforeEach(async () => {
|
|
29
|
+
await seedDb(initializedDb);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const initialize = async () => {
|
|
33
|
+
const client = new Client({ url: "teas/" }).setAdapter(initializedCoreAdapter);
|
|
34
|
+
const socket = new Socket({ url: "teas/", adapter: initializedSocketsAdapter });
|
|
35
|
+
const pushReq = client
|
|
36
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
37
|
+
endpoint: "",
|
|
38
|
+
method: "push",
|
|
39
|
+
})
|
|
40
|
+
.setPayload(newData);
|
|
41
|
+
const socketBees = new Socket({ url: "bees/", adapter: initializedSocketsAdapter });
|
|
42
|
+
|
|
43
|
+
return { client, socket, pushReq, socketBees };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
vi.resetAllMocks();
|
|
48
|
+
vi.clearAllMocks();
|
|
49
|
+
spy = vi.fn();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should return unmount function", async () => {
|
|
53
|
+
const { socket } = await initialize();
|
|
54
|
+
const onValueReq = socket.createListener<Tea[]>()({
|
|
55
|
+
topic: "",
|
|
56
|
+
});
|
|
57
|
+
const unmount = onValueReq.listen(spy);
|
|
58
|
+
expect(typeof unmount).toBe("function");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should unmount listeners", async () => {
|
|
62
|
+
const { socket, pushReq } = await initialize();
|
|
63
|
+
const onValueReq = socket.createListener<Tea[]>()({
|
|
64
|
+
topic: "",
|
|
65
|
+
});
|
|
66
|
+
const unmount = onValueReq.listen(spy);
|
|
67
|
+
|
|
68
|
+
await waitForExpect(async () => {
|
|
69
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
unmount();
|
|
73
|
+
|
|
74
|
+
await pushReq.send();
|
|
75
|
+
await pushReq.send();
|
|
76
|
+
|
|
77
|
+
await waitForExpect(async () => {
|
|
78
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
79
|
+
}, 1000);
|
|
80
|
+
|
|
81
|
+
expect(socket.adapter.listeners.get(onValueReq.topic)?.size).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should return emptyResource status", async () => {
|
|
85
|
+
const { socketBees } = await initialize();
|
|
86
|
+
const onValueReq = socketBees.createListener<Tea[]>()({
|
|
87
|
+
topic: "",
|
|
88
|
+
options: { onlyOnce: false },
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
let receivedData: any;
|
|
92
|
+
let receivedExtra: any;
|
|
93
|
+
|
|
94
|
+
const unmount = onValueReq.listen(({ data, extra }) => {
|
|
95
|
+
spy();
|
|
96
|
+
receivedData = data;
|
|
97
|
+
receivedExtra = extra;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await waitForExpect(async () => {
|
|
101
|
+
expect(spy).toHaveBeenCalled();
|
|
102
|
+
expect(receivedData).toBeNull();
|
|
103
|
+
expect(receivedExtra.status).toBe("emptyResource");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
unmount();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("should be called once with onlyOnce option", async () => {
|
|
110
|
+
const { socket, pushReq } = await initialize();
|
|
111
|
+
const onValueReq = socket.createListener<Tea[]>()({
|
|
112
|
+
topic: "",
|
|
113
|
+
options: { onlyOnce: true },
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const unmount = onValueReq.listen(spy);
|
|
117
|
+
|
|
118
|
+
await pushReq.send();
|
|
119
|
+
|
|
120
|
+
await waitForExpect(async () => {
|
|
121
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
unmount();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should receive updates", async () => {
|
|
128
|
+
const { socket, pushReq } = await initialize();
|
|
129
|
+
|
|
130
|
+
const onValueReq = socket.createListener<Tea[]>()({
|
|
131
|
+
topic: "",
|
|
132
|
+
options: { onlyOnce: false },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
let receivedData: Tea[] | null;
|
|
136
|
+
let receivedExtra: any;
|
|
137
|
+
|
|
138
|
+
const unmount = onValueReq.listen(({ data, extra }) => {
|
|
139
|
+
spy();
|
|
140
|
+
receivedData = data;
|
|
141
|
+
receivedExtra = extra;
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const { data } = await pushReq.send();
|
|
145
|
+
|
|
146
|
+
await waitForExpect(async () => {
|
|
147
|
+
expect(receivedData).toEqual(expect.arrayContaining([{ ...newData, __key: data?.__key }]));
|
|
148
|
+
expect(receivedExtra).toHaveProperty("snapshot");
|
|
149
|
+
expect(receivedExtra).toHaveProperty("status");
|
|
150
|
+
expect(receivedExtra).toHaveProperty("ref");
|
|
151
|
+
expect(receivedExtra.status).toBe("success");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
unmount();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("should return data available for doc", async () => {
|
|
158
|
+
const { socket } = await initialize();
|
|
159
|
+
const onValueReq = socket
|
|
160
|
+
.createListener<Tea[]>()({
|
|
161
|
+
topic: ":teaId",
|
|
162
|
+
})
|
|
163
|
+
.setParams({ teaId: 1 });
|
|
164
|
+
|
|
165
|
+
let receivedData: any;
|
|
166
|
+
let receivedExtra: any;
|
|
167
|
+
const unmount = onValueReq.listen(({ data, extra }) => {
|
|
168
|
+
spy();
|
|
169
|
+
receivedData = data;
|
|
170
|
+
receivedExtra = extra;
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
await waitForExpect(async () => {
|
|
174
|
+
expect(receivedData).toStrictEqual({
|
|
175
|
+
__key: "1",
|
|
176
|
+
amount: 150,
|
|
177
|
+
name: "Taiping Hou Kui",
|
|
178
|
+
origin: "China",
|
|
179
|
+
type: "Green",
|
|
180
|
+
year: 2023,
|
|
181
|
+
});
|
|
182
|
+
expect(receivedExtra).toHaveProperty("snapshot");
|
|
183
|
+
expect(receivedExtra).toHaveProperty("ref");
|
|
184
|
+
expect(receivedExtra.status).toBe("success");
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
unmount();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter } from "adapter";
|
|
4
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
5
|
+
import type { Tea } from "../../../../utils";
|
|
6
|
+
|
|
7
|
+
export const pushTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("push", () => {
|
|
9
|
+
let client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should allow for adding data to a list", async () => {
|
|
15
|
+
const newData = { origin: "Poland", type: "Green", year: 2023, name: "Pou Ran Do Cha", amount: 100 } as Tea;
|
|
16
|
+
const getReq = client.createRequest<{ response: Tea[] }>()({
|
|
17
|
+
endpoint: "",
|
|
18
|
+
method: "getDoc",
|
|
19
|
+
});
|
|
20
|
+
const pushReq = client
|
|
21
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
22
|
+
endpoint: "",
|
|
23
|
+
method: "setDoc",
|
|
24
|
+
options: {},
|
|
25
|
+
})
|
|
26
|
+
.setPayload(newData);
|
|
27
|
+
const { data: pushedData, extra } = await pushReq.send();
|
|
28
|
+
const { data } = await getReq.send();
|
|
29
|
+
|
|
30
|
+
expect(data).toHaveLength(11);
|
|
31
|
+
expect(data).toContainEqual({ ...newData, __key: pushedData?.__key });
|
|
32
|
+
expect(extra).toHaveProperty("key");
|
|
33
|
+
});
|
|
34
|
+
it("should emit lifecycle events", async () => {
|
|
35
|
+
const newData = { origin: "Poland", type: "Green", year: 2043, name: "Pou Ran Do Cha", amount: 100 } as Tea;
|
|
36
|
+
|
|
37
|
+
const pushReq = client
|
|
38
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
39
|
+
endpoint: "teas/",
|
|
40
|
+
method: "setDoc",
|
|
41
|
+
options: {},
|
|
42
|
+
})
|
|
43
|
+
.setPayload(newData);
|
|
44
|
+
|
|
45
|
+
await testLifecycleEvents(pushReq);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter } from "adapter";
|
|
4
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
5
|
+
import type { Tea } from "../../../../utils";
|
|
6
|
+
|
|
7
|
+
export const removeTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
let client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
11
|
+
});
|
|
12
|
+
describe("remove", () => {
|
|
13
|
+
it("should allow for removing data", async () => {
|
|
14
|
+
const getReq = client
|
|
15
|
+
.createRequest<{ response: Tea }>()({
|
|
16
|
+
endpoint: ":teaId",
|
|
17
|
+
method: "getDoc",
|
|
18
|
+
})
|
|
19
|
+
.setParams({ teaId: 1 });
|
|
20
|
+
|
|
21
|
+
const removeReq = client
|
|
22
|
+
.createRequest<{ response: Tea }>()({
|
|
23
|
+
endpoint: ":teaId",
|
|
24
|
+
method: "deleteDoc",
|
|
25
|
+
})
|
|
26
|
+
.setParams({ teaId: 1 });
|
|
27
|
+
|
|
28
|
+
await removeReq.send();
|
|
29
|
+
const { data, extra } = await getReq.send();
|
|
30
|
+
expect(data).toBe(null);
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
expect(extra?.snapshot?.exists()).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
it("should emit lifecycle events", async () => {
|
|
36
|
+
const removeReq = client
|
|
37
|
+
.createRequest<{ response: Tea }>()({
|
|
38
|
+
endpoint: ":teaId",
|
|
39
|
+
method: "deleteDoc",
|
|
40
|
+
})
|
|
41
|
+
.setParams({ teaId: 1 });
|
|
42
|
+
|
|
43
|
+
await testLifecycleEvents(removeReq);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Client } from "@hyper-fetch/core";
|
|
2
|
+
|
|
3
|
+
import type { FirebaseAdminAdapter, RealtimeDbGetMethodExtra } from "adapter";
|
|
4
|
+
import { testLifecycleEvents } from "../../../../shared/request-events.shared";
|
|
5
|
+
import type { Tea } from "../../../../utils";
|
|
6
|
+
|
|
7
|
+
export const setTestSuite = (adapterFunction: () => ReturnType<typeof FirebaseAdminAdapter>) => {
|
|
8
|
+
describe("set", () => {
|
|
9
|
+
let client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
client = new Client({ url: "teas/" }).setAdapter(adapterFunction());
|
|
12
|
+
});
|
|
13
|
+
it("should set data", async () => {
|
|
14
|
+
const newData = { origin: "Poland", type: "Green", year: 2023, name: "Pou Ran Do Cha", amount: 10 } as Tea;
|
|
15
|
+
|
|
16
|
+
const getReq = client
|
|
17
|
+
.createRequest<{ response: Tea }>()({
|
|
18
|
+
endpoint: ":teaId",
|
|
19
|
+
method: "get",
|
|
20
|
+
})
|
|
21
|
+
.setParams({ teaId: 1 });
|
|
22
|
+
const setReq = client
|
|
23
|
+
.createRequest<{ response: Tea; payload: Tea }>()({
|
|
24
|
+
endpoint: ":teaId",
|
|
25
|
+
method: "set",
|
|
26
|
+
})
|
|
27
|
+
.setParams({ teaId: 1 })
|
|
28
|
+
.setPayload(newData);
|
|
29
|
+
|
|
30
|
+
await setReq.send();
|
|
31
|
+
const { data, extra } = await getReq.send();
|
|
32
|
+
expect(data).toStrictEqual(newData);
|
|
33
|
+
expect(extra).not.toBeNull();
|
|
34
|
+
expect((extra as RealtimeDbGetMethodExtra).snapshot.exists()).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
it("should allow for removing data via set", async () => {
|
|
37
|
+
const getReq = client
|
|
38
|
+
.createRequest<{ response: Tea | null }>()({
|
|
39
|
+
endpoint: ":teaId",
|
|
40
|
+
method: "get",
|
|
41
|
+
})
|
|
42
|
+
.setParams({ teaId: 1 });
|
|
43
|
+
|
|
44
|
+
const setReq = client
|
|
45
|
+
.createRequest<{ response: Tea | null; payload: { data: null } }>()({
|
|
46
|
+
endpoint: ":teaId",
|
|
47
|
+
method: "set",
|
|
48
|
+
})
|
|
49
|
+
.setParams({ teaId: 1 })
|
|
50
|
+
.setPayload({ data: null });
|
|
51
|
+
|
|
52
|
+
await setReq.send();
|
|
53
|
+
const { data, extra } = await getReq.send();
|
|
54
|
+
expect(data).toBe(null);
|
|
55
|
+
expect(extra).not.toBeNull();
|
|
56
|
+
expect((extra as RealtimeDbGetMethodExtra).snapshot.exists()).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it("should emit lifecycle events", async () => {
|
|
59
|
+
const setReq = client
|
|
60
|
+
.createRequest<{ response: Tea | null; payload: { data: null } }>()({
|
|
61
|
+
endpoint: ":teaId",
|
|
62
|
+
method: "set",
|
|
63
|
+
})
|
|
64
|
+
.setParams({ teaId: 1 })
|
|
65
|
+
.setPayload({ data: null });
|
|
66
|
+
|
|
67
|
+
await testLifecycleEvents(setReq);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
};
|