Skip to content

Commit 32f4ddb

Browse files
author
Hein
committed
Add AttachmentQueue tests
1 parent 5cd0ae0 commit 32f4ddb

File tree

5 files changed

+210
-31
lines changed

5 files changed

+210
-31
lines changed

packages/attachments/package.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,24 @@
2525
"build": "tsc -b",
2626
"build:prod": "tsc -b --sourceMap false",
2727
"clean": "rm -rf lib tsconfig.tsbuildinfo",
28-
"watch": "tsc -b -w"
28+
"watch": "tsc -b -w",
29+
"test": "pnpm build && vitest"
2930
},
3031
"peerDependencies": {
3132
"@powersync/common": "workspace:^1.18.1"
33+
},
34+
"devDependencies": {
35+
"@powersync/web": "workspace:*",
36+
"@journeyapps/wa-sqlite": "^1.0.0",
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
}

packages/attachments/src/AbstractAttachmentQueue.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
300300
}
301301

302302
async downloadRecord(record: AttachmentRecord) {
303+
if (!this.options.downloadAttachments) {
304+
return false;
305+
}
303306
if (!record.local_uri) {
304307
record.local_uri = this.getLocalFilePathSuffix(record.filename);
305308
}
@@ -442,7 +445,7 @@ export abstract class AbstractAttachmentQueue<T extends AttachmentQueueOptions =
442445
}
443446

444447
private async downloadRecords() {
445-
if (this.options.downloadAttachments) {
448+
if (!this.options.downloadAttachments) {
446449
return;
447450
}
448451
if (this.downloading) {
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import * as commonSdk from '@powersync/common';
2+
import { beforeEach, describe, expect, it, vi } from 'vitest';
3+
import { AbstractAttachmentQueue } from '../../src/AbstractAttachmentQueue';
4+
import { AttachmentRecord, AttachmentState } from '../../src/Schema';
5+
import { AbstractPowerSyncDatabase } from '@powersync/common';
6+
import { StorageAdapter } from '../../src/StorageAdapter';
7+
8+
const record = {
9+
id: 'test-1',
10+
filename: 'test.jpg',
11+
state: AttachmentState.QUEUED_DOWNLOAD
12+
}
13+
14+
const mockPowerSync = {
15+
currentStatus: { status: 'initial' },
16+
registerListener: vi.fn(() => {}),
17+
resolveTables: vi.fn(() => ['table1', 'table2']),
18+
onChangeWithCallback: vi.fn(),
19+
getAll: vi.fn(() => Promise.resolve([{id: 'test-1'}, {id: 'test-2'}])),
20+
execute: vi.fn(() => Promise.resolve()),
21+
getOptional: vi.fn((_query, params) => Promise.resolve(record)),
22+
watch: vi.fn((query, params, callbacks) => {
23+
callbacks?.onResult?.({ rows: { _array: [{id: 'test-1'}, {id: 'test-2'}] } });
24+
}),
25+
writeTransaction: vi.fn(async (callback) => {
26+
await callback({
27+
execute: vi.fn(() => Promise.resolve())
28+
});
29+
})
30+
};
31+
32+
const mockStorage: StorageAdapter = {
33+
downloadFile: vi.fn(),
34+
uploadFile: vi.fn(),
35+
deleteFile: vi.fn(),
36+
writeFile: vi.fn(),
37+
readFile: vi.fn(),
38+
fileExists: vi.fn(),
39+
makeDir: vi.fn(),
40+
copyFile: vi.fn(),
41+
getUserStorageDirectory: vi.fn()
42+
};
43+
44+
class TestAttachmentQueue extends AbstractAttachmentQueue {
45+
onAttachmentIdsChange(onUpdate: (ids: string[]) => void): void {
46+
throw new Error('Method not implemented.');
47+
}
48+
newAttachmentRecord(record?: Partial<AttachmentRecord>): Promise<AttachmentRecord> {
49+
throw new Error('Method not implemented.');
50+
}
51+
}
52+
53+
describe('attachments', () => {
54+
beforeEach(() => {
55+
vi.clearAllMocks();
56+
});
57+
58+
it('should not download attachments when downloadRecord is called with downloadAttachments false', async () => {
59+
const queue = new TestAttachmentQueue({
60+
powersync: mockPowerSync as any,
61+
storage: mockStorage,
62+
downloadAttachments: false
63+
});
64+
65+
await queue.downloadRecord(record);
66+
67+
expect(mockStorage.downloadFile).not.toHaveBeenCalled();
68+
});
69+
70+
it('should download attachments when downloadRecord is called with downloadAttachments true', async () => {
71+
const queue = new TestAttachmentQueue({
72+
powersync: mockPowerSync as any,
73+
storage: mockStorage,
74+
downloadAttachments: true
75+
});
76+
77+
await queue.downloadRecord(record);
78+
79+
expect(mockStorage.downloadFile).toHaveBeenCalled();
80+
});
81+
82+
// Testing the inverse of this test, i.e. when downloadAttachments is false, is not required as you can't wait for something that does not happen
83+
it('should not download attachments with watchDownloads is called with downloadAttachments false', async () => {
84+
const queue = new TestAttachmentQueue({
85+
powersync: mockPowerSync as any,
86+
storage: mockStorage,
87+
downloadAttachments: true
88+
});
89+
90+
queue.watchDownloads();
91+
await vi.waitFor(() => {
92+
expect(mockStorage.downloadFile).toBeCalledTimes(2);
93+
});
94+
});
95+
});
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);

0 commit comments

Comments
 (0)