[fabric/sqlite-store] Add QueryBuilder tests and implement assertNone method

This commit is contained in:
Pablo Baleztena 2024-10-30 22:42:13 -03:00
parent ce1f0a04f3
commit 4cc3324b46
2 changed files with 133 additions and 6 deletions

View File

@ -0,0 +1,101 @@
import {
AlreadyExistsError,
Field,
isLike,
Model,
NotFoundError,
} from "@fabric/domain";
import { UUIDGeneratorMock } from "@fabric/domain/mocks";
import { afterEach, beforeEach, describe, expect, test } from "@fabric/testing";
import { SQLiteStateStore } from "./state-store.ts";
describe("QueryBuilder", () => {
const models = [
Model.entityFrom("test", {
name: Field.string(),
}),
];
let stateStore = new SQLiteStateStore(":memory:", models);
beforeEach(async () => {
stateStore = new SQLiteStateStore(":memory:", models);
await stateStore.migrate().unwrapOrThrow();
await stateStore.insertInto("test", {
id: UUIDGeneratorMock.generate(),
name: "test1",
}).unwrapOrThrow();
await stateStore.insertInto("test", {
id: UUIDGeneratorMock.generate(),
name: "test2",
}).unwrapOrThrow();
});
afterEach(async () => {
await stateStore.close().unwrapOrThrow();
});
test("select() after a where() should return valid results", async () => {
const result = await stateStore.from("test").where({
name: isLike("test%"),
})
.select().unwrapOrThrow();
expect(result).toEqual([{
id: expect.any(String),
name: "test1",
}, {
id: expect.any(String),
name: "test2",
}]);
});
test("selectOneOrFail() should return a single result", async () => {
const result = await stateStore.from("test").where({ name: "test1" })
.selectOneOrFail().unwrapOrThrow();
expect(result).toEqual({
id: expect.any(String),
name: "test1",
});
});
test("selectOneOrFail() should fail if no results are found", async () => {
const error = await stateStore.from("test").where({ name: "not-found" })
.selectOneOrFail().unwrapErrorOrThrow();
expect(error).toBeInstanceOf(NotFoundError);
});
test("selectOne() should return a single result", async () => {
const result = await stateStore.from("test")
.selectOne().unwrapOrThrow();
expect(result).toEqual({
id: expect.any(String),
name: "test1",
});
});
test("selectOne() should return undefined if no results are found", async () => {
const result = await stateStore.from("test").where({
name: "not-found",
})
.selectOne().unwrapOrThrow();
expect(result).toBeUndefined();
});
test("assertNone() should succeed if no results are found", async () => {
const result = await stateStore.from("test").where({
name: "not-found",
}).assertNone().unwrapOrThrow();
expect(result).toBeUndefined();
});
test("assertNone() should fail if results are found", async () => {
const error = await stateStore.from("test").where({ name: "test1" })
.assertNone().unwrapErrorOrThrow();
expect(error).toBeInstanceOf(AlreadyExistsError);
});
});

View File

@ -1,6 +1,7 @@
// deno-lint-ignore-file no-explicit-any // deno-lint-ignore-file no-explicit-any
import { AsyncResult, Keyof, Optional } from "@fabric/core"; import { AsyncResult, Keyof, Optional } from "@fabric/core";
import { import {
AlreadyExistsError,
FilterOptions, FilterOptions,
Model, Model,
type ModelSchema, type ModelSchema,
@ -112,18 +113,43 @@ export class QueryBuilder<T> implements StoreQuery<T> {
limit: 1, limit: 1,
}, },
); );
const result = await this.db.onePrepared( return await this.db.onePrepared(
stmt, stmt,
params, params,
transformRow(this.schema[this.query.from]!), transformRow(this.schema[this.query.from]!),
); );
if (!result) {
throw new NotFoundError();
}
return result;
}, },
(err) => new StoreQueryError(err.message), (err) => new StoreQueryError(err.message),
).flatMap((result) => {
if (!result) {
return AsyncResult.failWith(new NotFoundError());
}
return AsyncResult.ok(result);
});
}
assertNone(): AsyncResult<void, StoreQueryError | AlreadyExistsError> {
return AsyncResult.tryFrom(
async () => {
const [stmt, params] = getSelectStatement(
this.schema[this.query.from]!,
{
...this.query,
limit: 1,
},
); );
return await this.db.onePrepared(
stmt,
params,
);
},
(err) => new StoreQueryError(err.message),
).flatMap((result) => {
if (result) {
return AsyncResult.failWith(new AlreadyExistsError());
}
return AsyncResult.ok();
});
} }
} }