Skip to content

Commit

Permalink
INFRA30 (#251)
Browse files Browse the repository at this point in the history
* Refactor firestore utilities for Astro
  • Loading branch information
camillobucciarelli authored Jul 25, 2024
1 parent aa2beab commit 301fa53
Show file tree
Hide file tree
Showing 14 changed files with 745 additions and 19 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"generate-translations": "npx astro-i18next generate",
"prettier": "prettier --write . --plugin=prettier-plugin-astro",
"test": "firebase emulators:exec --only firestore 'vitest --coverage'",
"test:ui": "firebase emulators:exec --only firestore 'vitest --coverage --ui'",
"test:e2e": "playwright test",
"emulators": "cd functions/ && npm run build && cd .. && firebase emulators:start --import=./firebase-data",
"emulators:export": "firebase emulators:export ./firebase-data"
Expand Down Expand Up @@ -47,6 +48,7 @@
"@types/node": "^20.11.17",
"@typescript-eslint/parser": "^6.21.0",
"@vitest/coverage-v8": "^1.2.2",
"@vitest/ui": "^2.0.4",
"eslint": "^8.56.0",
"eslint-plugin-astro": "^0.30.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
Expand Down
80 changes: 75 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 105 additions & 0 deletions src/data/firestore/common/create.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { test, describe, expect } from "vitest";
import { createDocument } from "./create";
import { getDocumentById } from "./get-by-id";
import { testConverter, type TestDoc, type TestModel } from "./test-model";
import type { FirestoreDataConverter } from "firebase-admin/firestore";

const testCollection = "create-test";

describe("Create a new document", () => {
test("Should create a document success", async () => {
const modelToSave: TestModel = {
lastUpdate: new Date("2024-01-01"),
name: "Test Document",
};
const result = await createDocument(
testCollection,
testConverter,
modelToSave,
);
expect(result).toMatchObject({
status: "success",
data: expect.any(String),
});

const getResult = await getDocumentById(
testCollection,
testConverter,
result.data as string,
);
expect(getResult).toMatchObject({
status: "success",
data: expect.objectContaining({
...modelToSave,
id: result.data,
}),
});
});

test("Should return an error if id is present", async () => {
const modelToSave: TestModel = {
id: "test-id",
lastUpdate: new Date("2024-01-01"),
name: "Test Document",
};
const result = await createDocument(
testCollection,
testConverter,
modelToSave,
);
expect(result).toMatchObject({
status: "error",
data: {
code: `${testCollection}/create-error:id-is-present`,
message: "Document ID is required",
},
});
});

test("Should return an error if firestore error", async () => {
const modelToSave: TestModel = {
lastUpdate: new Date("2024-01-01"),
name: "Test Document",
};
const fakeConverter: FirestoreDataConverter<TestModel, TestDoc> = {
toFirestore: (): TestDoc => {
throw new Error("Error converting to firestore");
},
fromFirestore: (): TestModel => {
throw new Error("Error converting from firestore");
},
};
const result = await createDocument(
testCollection,
fakeConverter,
modelToSave,
);
expect(result).toMatchObject({
status: "error",
data: {
code: `${testCollection}/create-error`,
message: `Error creating document in collection ${testCollection}`,
},
});
});

test("Should return an error if id is present", async () => {
const modelToSave: TestModel = {
id: "test-id",
lastUpdate: new Date("2024-01-01"),
name: "Test Document",
};
const result = await createDocument(
testCollection,
testConverter,
modelToSave,
);
expect(result).toMatchObject({
status: "error",
data: {
code: `${testCollection}/create-error:id-is-present`,
message: "Document ID is required",
},
});
});
});
51 changes: 51 additions & 0 deletions src/data/firestore/common/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type {
DocumentData,
FirestoreDataConverter,
} from "firebase-admin/firestore";
import { firestoreInstance } from "~/firebase/server";
import type { BaseModel } from "~/models/base-model";
import type { ServerResponse } from "~/models/server-response/server-response.type";

export const createDocument = async <
M extends BaseModel,
D extends DocumentData,
C extends string,
>(
collection: C,
converter: FirestoreDataConverter<M, D>,
model: M,
): Promise<
ServerResponse<
string,
`${C}/create-error` | `${C}/create-error:id-is-present`
>
> => {
try {
if (model.id) {
return {
status: "error",
data: {
code: `${collection}/create-error:id-is-present`,
message: "Document ID is required",
},
};
}
const result = await firestoreInstance
.collection(collection)
.withConverter<M, D>(converter)
.add(model);
return {
status: "success",
data: result.id,
};
} catch (error) {
console.error(`Error creating document in collection ${collection}`, error);
return {
status: "error",
data: {
code: `${collection}/create-error`,
message: `Error creating document in collection ${collection}`,
},
};
}
};
Loading

0 comments on commit 301fa53

Please sign in to comment.