Skip to content

Commit 97aa39b

Browse files
committed
Basic tests for Drizzle ORM package.
1 parent a071882 commit 97aa39b

File tree

8 files changed

+251
-136
lines changed

8 files changed

+251
-136
lines changed

packages/drizzle-driver/package.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,27 @@
2222
"build": "tsc --build",
2323
"build:prod": "tsc --build --sourceMap false",
2424
"clean": "rm -rf lib tsconfig.tsbuildinfo",
25-
"watch": "tsc --build -w"
25+
"watch": "tsc --build -w",
26+
"test": "vitest"
2627
},
2728
"peerDependencies": {
2829
"@powersync/common": "workspace:^1.19.0"
2930
},
3031
"dependencies": {
3132
"drizzle-orm": "0.35.2"
33+
},
34+
"devDependencies": {
35+
"@powersync/web": "workspace:*",
36+
"@journeyapps/wa-sqlite": "^0.4.1",
37+
"@types/node": "^20.17.6",
38+
"@vitest/browser": "^2.1.4",
39+
"ts-loader": "^9.5.1",
40+
"ts-node": "^10.9.2",
41+
"typescript": "^5.6.3",
42+
"vite": "^5.4.10",
43+
"vite-plugin-top-level-await": "^1.4.4",
44+
"vite-plugin-wasm": "^3.3.0",
45+
"vitest": "^2.1.4",
46+
"webdriverio": "^9.2.8"
3247
}
3348
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Schema, PowerSyncDatabase, column, Table, AbstractPowerSyncDatabase } from '@powersync/web';
2+
import { sqliteTable, text } from 'drizzle-orm/sqlite-core';
3+
import { wrapPowerSyncWithDrizzle, PowerSyncSQLiteDatabase } from '../../src/sqlite/db';
4+
5+
const users = new Table({
6+
name: column.text
7+
});
8+
9+
export const drizzleUsers = sqliteTable('users', {
10+
id: text('id').primaryKey().notNull(),
11+
name: text('name').notNull()
12+
});
13+
14+
export const TestSchema = new Schema({ users });
15+
export const DrizzleSchema = { users: drizzleUsers };
16+
17+
export const getPowerSyncDb = () => {
18+
const database = new PowerSyncDatabase({
19+
database: {
20+
dbFilename: 'test.db'
21+
},
22+
schema: TestSchema
23+
});
24+
25+
return database;
26+
};
27+
28+
export const getDrizzleDb = (db: AbstractPowerSyncDatabase) => {
29+
const database = wrapPowerSyncWithDrizzle(db, { schema: DrizzleSchema });
30+
31+
return database;
32+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { TestSchema } from './db';
2+
3+
export type Database = (typeof TestSchema)['types'];
4+
5+
export type UsersTable = Database['users'];
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { AbstractPowerSyncDatabase } from '@powersync/common';
2+
import { eq, sql } from 'drizzle-orm';
3+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
4+
import * as SUT from '../../src/sqlite/db';
5+
import { DrizzleSchema, drizzleUsers, getDrizzleDb, getPowerSyncDb } from '../setup/db';
6+
7+
describe('Database operations', () => {
8+
let powerSyncDb: AbstractPowerSyncDatabase;
9+
let db: SUT.PowerSyncSQLiteDatabase<typeof DrizzleSchema>;
10+
11+
beforeEach(() => {
12+
powerSyncDb = getPowerSyncDb();
13+
db = getDrizzleDb(powerSyncDb);
14+
});
15+
16+
afterEach(async () => {
17+
await powerSyncDb.disconnectAndClear();
18+
});
19+
20+
it('should insert a user and select that user', async () => {
21+
await db.insert(drizzleUsers).values({ id: '1', name: 'John' });
22+
const result = await db.select().from(drizzleUsers);
23+
24+
expect(result.length).toEqual(1);
25+
});
26+
27+
it('should insert a user and delete that user', async () => {
28+
await db.insert(drizzleUsers).values({ id: '2', name: 'Ben' });
29+
await db.delete(drizzleUsers).where(eq(drizzleUsers.name, 'Ben'));
30+
const result = await db.select().from(drizzleUsers);
31+
32+
expect(result.length).toEqual(0);
33+
});
34+
35+
it('should insert a user and update that user', async () => {
36+
await db.insert(drizzleUsers).values({ id: '3', name: 'Lucy' });
37+
await db.update(drizzleUsers).set({ name: 'Lucy Smith' }).where(eq(drizzleUsers.name, 'Lucy'));
38+
const result = await db.select().from(drizzleUsers).get();
39+
40+
expect(result!.name).toEqual('Lucy Smith');
41+
});
42+
43+
it('should insert a user and update that user within a transaction', async () => {
44+
await db.transaction(async (transaction) => {
45+
await transaction.insert(drizzleUsers).values({ id: '4', name: 'James' });
46+
await transaction.update(drizzleUsers).set({ name: 'James Smith' }).where(eq(drizzleUsers.name, 'James'));
47+
});
48+
const result = await db.select().from(drizzleUsers).get();
49+
50+
expect(result!.name).toEqual('James Smith');
51+
});
52+
53+
it('should insert a user and update that user within a transaction when raw sql is used', async () => {
54+
await db.transaction(async (transaction) => {
55+
await transaction.run(sql`INSERT INTO users (id, name) VALUES ('4', 'James');`);
56+
await db.update(drizzleUsers).set({ name: 'James Smith' }).where(eq(drizzleUsers.name, 'James'));
57+
});
58+
59+
const result = await db.select().from(drizzleUsers).get();
60+
61+
expect(result!.name).toEqual('James Smith');
62+
});
63+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// import { PowerSyncSQLitePreparedQuery, mapResultRow } from './PowerSyncSQLitePreparedQuery';
2+
import { AbstractPowerSyncDatabase } from '@powersync/web';
3+
import { Query } from 'drizzle-orm/sql/sql';
4+
import { PowerSyncSQLiteDatabase } from '../../src/sqlite/db';
5+
import { PowerSyncSQLitePreparedQuery } from '../../src/sqlite/sqlite-query';
6+
import { DrizzleSchema, drizzleUsers, getDrizzleDb, getPowerSyncDb } from '../setup/db';
7+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
8+
9+
describe('PowerSyncSQLitePreparedQuery', () => {
10+
let powerSyncDb: AbstractPowerSyncDatabase;
11+
let db: PowerSyncSQLiteDatabase<typeof DrizzleSchema>;
12+
const loggerMock = { logQuery: () => {} };
13+
14+
beforeEach(async () => {
15+
powerSyncDb = getPowerSyncDb();
16+
db = getDrizzleDb(powerSyncDb);
17+
18+
await db.insert(drizzleUsers).values({ id: '1', name: 'Alice' });
19+
await db.insert(drizzleUsers).values({ id: '2', name: 'Bob' });
20+
});
21+
22+
afterEach(async () => {
23+
await powerSyncDb.disconnectAndClear();
24+
});
25+
26+
it('should execute a query in run()', async () => {
27+
const query: Query = { sql: `SELECT * FROM users WHERE id = ?`, params: [1] };
28+
const preparedQuery = new PowerSyncSQLitePreparedQuery(powerSyncDb, query, loggerMock, undefined, 'run', false);
29+
30+
const result = await preparedQuery.run();
31+
expect(result.rows?._array).toEqual([{ id: '1', name: 'Alice' }]);
32+
});
33+
34+
it('should retrieve all rows in all()', async () => {
35+
const query: Query = { sql: `SELECT * FROM users`, params: [] } as Query;
36+
const preparedQuery = new PowerSyncSQLitePreparedQuery(powerSyncDb, query, loggerMock, undefined, 'all', false);
37+
38+
const rows = await preparedQuery.all();
39+
expect(rows).toEqual([
40+
{ id: '1', name: 'Alice' },
41+
{ id: '2', name: 'Bob' }
42+
]);
43+
});
44+
45+
it('should retrieve a single row in get()', async () => {
46+
const query: Query = { sql: `SELECT * FROM users WHERE id = ?`, params: [1] };
47+
48+
const preparedQuery = new PowerSyncSQLitePreparedQuery(powerSyncDb, query, loggerMock, undefined, 'get', false);
49+
50+
const row = await preparedQuery.get();
51+
expect(row).toEqual({ id: '1', name: 'Alice' });
52+
});
53+
54+
it('should retrieve values in values()', async () => {
55+
const query: Query = { sql: `SELECT * FROM users`, params: [] } as Query;
56+
57+
const preparedQuery = new PowerSyncSQLitePreparedQuery(powerSyncDb, query, loggerMock, undefined, 'all', false);
58+
59+
const values = await preparedQuery.values();
60+
expect(values).toEqual([
61+
{ id: '1', name: 'Alice' },
62+
{ id: '2', name: 'Bob' }
63+
]);
64+
});
65+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import wasm from 'vite-plugin-wasm';
2+
import topLevelAwait from 'vite-plugin-top-level-await';
3+
import { defineConfig, UserConfigExport } from 'vitest/config';
4+
5+
const config: UserConfigExport = {
6+
worker: {
7+
format: 'es',
8+
plugins: () => [wasm(), topLevelAwait()]
9+
},
10+
optimizeDeps: {
11+
// Don't optimise these packages as they contain web workers and WASM files.
12+
// https://github.com/vitejs/vite/issues/11672#issuecomment-1415820673
13+
exclude: ['@journeyapps/wa-sqlite', '@powersync/web']
14+
},
15+
plugins: [wasm(), topLevelAwait()],
16+
test: {
17+
isolate: false,
18+
globals: true,
19+
include: ['tests/**/*.test.ts'],
20+
browser: {
21+
enabled: true,
22+
headless: true,
23+
provider: 'webdriverio',
24+
name: 'chrome' // browser name is required
25+
}
26+
}
27+
};
28+
29+
export default defineConfig(config);

packages/kysely-driver/tests/sqlite/db.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@ describe('CRUD operations', () => {
5151
expect(result.name).toEqual('James Smith');
5252
});
5353

54-
5554
it('should insert a user and update that user within a transaction when raw sql is used', async () => {
5655
await db.transaction().execute(async (transaction) => {
57-
await sql`INSERT INTO users (id, name) VALUES ('4', 'James');`.execute(transaction)
56+
await sql`INSERT INTO users (id, name) VALUES ('4', 'James');`.execute(transaction);
5857
await transaction.updateTable('users').where('name', '=', 'James').set('name', 'James Smith').execute();
5958
});
60-
console.log(await db.selectFrom('users').selectAll().execute())
6159
const result = await db.selectFrom('users').select('name').executeTakeFirstOrThrow();
6260

6361
expect(result.name).toEqual('James Smith');

0 commit comments

Comments
 (0)