Skip to content

Commit 83b1289

Browse files
update unit tests
1 parent f273312 commit 83b1289

File tree

11 files changed

+121
-100
lines changed

11 files changed

+121
-100
lines changed

packages/common/rollup.config.mjs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import commonjs from '@rollup/plugin-commonjs';
22
import inject from '@rollup/plugin-inject';
33
import json from '@rollup/plugin-json';
44
import nodeResolve from '@rollup/plugin-node-resolve';
5+
import terser from '@rollup/plugin-terser';
56

7+
/**
8+
* @returns {import('rollup').RollupOptions}
9+
*/
610
export default (commandLineArgs) => {
7-
const sourcemap = (commandLineArgs.sourceMap || 'true') == 'true';
11+
const sourceMap = (commandLineArgs.sourceMap || 'true') == 'true';
812

913
// Clears rollup CLI warning https://github.com/rollup/rollup/issues/2694
1014
delete commandLineArgs.sourceMap;
@@ -14,7 +18,7 @@ export default (commandLineArgs) => {
1418
output: {
1519
file: 'dist/bundle.mjs',
1620
format: 'esm',
17-
sourcemap: sourcemap
21+
sourcemap: sourceMap
1822
},
1923
plugins: [
2024
json(),
@@ -25,8 +29,8 @@ export default (commandLineArgs) => {
2529
ReadableStream: ['web-streams-polyfill/ponyfill', 'ReadableStream'],
2630
// Used by can-ndjson-stream
2731
TextDecoder: ['text-encoding', 'TextDecoder']
28-
})
29-
// terser()
32+
}),
33+
terser({ sourceMap })
3034
],
3135
// This makes life easier
3236
external: [

packages/common/src/client/watched/processors/AbstractQueryProcessor.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
4141
protected abortController: AbortController;
4242
protected initialized: Promise<void>;
4343
protected _closed: boolean;
44+
protected disposeListeners: (() => void) | null;
4445

4546
get closed() {
4647
return this._closed;
@@ -66,6 +67,7 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
6667
lastUpdated: null,
6768
data: options.watchOptions.placeholderData
6869
};
70+
this.disposeListeners = null;
6971
this.initialized = this.init();
7072
}
7173

@@ -97,6 +99,9 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
9799
protected async updateState(update: Partial<WatchedQueryState<Data>>) {
98100
if (typeof update.error !== 'undefined') {
99101
await this.iterateAsyncListenersWithError(async (l) => l.onError?.(update.error!));
102+
// An error always stops for the current fetching state
103+
update.isFetching = false;
104+
update.isLoading = false;
100105
}
101106

102107
if (typeof update.data !== 'undefined') {
@@ -113,19 +118,29 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
113118
protected async init() {
114119
const { db } = this.options;
115120

116-
db.registerListener({
121+
const disposeCloseListener = db.registerListener({
122+
closed: async () => {
123+
this.close();
124+
}
125+
});
126+
127+
// Wait for the schema to be set before listening to changes
128+
await db.waitForReady();
129+
const disposeSchemaListener = db.registerListener({
117130
schemaChanged: async () => {
118131
await this.runWithReporting(async () => {
119132
await this.updateSettings(this.options.watchOptions);
120133
});
121-
},
122-
closing: () => {
123-
this.close();
124134
}
125135
});
126136

137+
this.disposeListeners = () => {
138+
disposeCloseListener();
139+
disposeSchemaListener();
140+
};
141+
127142
// Initial setup
128-
await this.runWithReporting(async () => {
143+
this.runWithReporting(async () => {
129144
await this.updateSettings(this.options.watchOptions);
130145
});
131146
}
@@ -134,18 +149,19 @@ export abstract class AbstractQueryProcessor<Data = unknown[]>
134149
// hook in to subscription events in order to report changes
135150
const baseDispose = this.registerListener({ ...subscription });
136151

137-
const counts = this.subscriptionCounts;
138-
this.iterateListeners((l) => l.subscriptionsChanged?.(counts));
152+
this.iterateListeners((l) => l.subscriptionsChanged?.(this.subscriptionCounts));
139153

140154
return () => {
141155
baseDispose();
142-
this.iterateListeners((l) => l.subscriptionsChanged?.(counts));
156+
this.iterateListeners((l) => l.subscriptionsChanged?.(this.subscriptionCounts));
143157
};
144158
}
145159

146160
async close() {
147161
await this.initialized;
148162
this.abortController.abort();
163+
this.disposeListeners?.();
164+
this.disposeListeners = null;
149165
this._closed = true;
150166
this.iterateListeners((l) => l.closed?.());
151167
}

packages/react/src/QueryStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AbstractPowerSyncDatabase, WatchCompatibleQuery, WatchedQuery } from '@powersync/common';
2-
import { AdditionalOptions } from './hooks/useQuery';
2+
import { AdditionalOptions } from './hooks/watched/watch-types';
33

44
export function generateQueryKey(
55
sqlStatement: string,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import { QueryResult } from '../useQuery';
1+
import { QueryResult } from '../watched/watch-types';
22

33
export type SuspenseQueryResult<T> = Pick<QueryResult<T>, 'data' | 'refresh'>;

packages/react/src/hooks/suspense/useSingleSuspenseQuery.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ export const useSingleSuspenseQuery = <T = any>(
3838
// Only use a temporary watched query if we don't have data yet.
3939
const watchedQuery = data ? null : (store.getQuery(key, parsedQuery, options) as WatchedQuery<T[]>);
4040
const { releaseHold } = useTemporaryHold(watchedQuery);
41-
41+
console.log('single watched query', !!watchedQuery);
4242
React.useEffect(() => {
4343
// Set the initial yielded data
4444
// it should be available once we commit the component
4545
if (watchedQuery?.state.error) {
4646
setError(watchedQuery.state.error);
47-
} else if (watchedQuery?.state.data) {
47+
} else if (watchedQuery?.state.isLoading === false) {
4848
setData(watchedQuery.state.data);
4949
setError(null);
5050
}
@@ -57,16 +57,18 @@ export const useSingleSuspenseQuery = <T = any>(
5757
if (error != null) {
5858
// Report errors - this is caught by an error boundary
5959
throw error;
60-
} else if (data || watchedQuery?.state.data) {
60+
} else if (data || watchedQuery?.state.isLoading === false) {
6161
// Happy path data return
6262
return {
6363
data: data ?? watchedQuery?.state.data ?? [],
6464
refresh: async (signal) => {
6565
try {
66+
console.log('calling refresh for single query', key);
6667
const result = await parsedQuery.execute(parsedQuery.compile());
6768
if (signal.aborted) {
6869
return; // Abort if the signal is already aborted
6970
}
71+
console.log('done with query refresh');
7072
setData(result);
7173
setError(null);
7274
} catch (e) {

packages/react/src/hooks/suspense/useWatchedQuerySuspenseSubscription.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export const useWatchedQuerySuspenseSubscription = <ResultType>(query: WatchedQu
5555
// Happy path data return
5656
return {
5757
data: query.state.data,
58-
refresh: () => {
58+
refresh: async () => {
5959
// no-op for watched queries
6060
}
6161
};

packages/react/src/hooks/watched/watch-utils.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { AbstractPowerSyncDatabase, CompilableQuery, WatchCompatibleQuery } from '@powersync/common';
1+
import {
2+
AbstractPowerSyncDatabase,
3+
CompilableQuery,
4+
WatchCompatibleQuery,
5+
WatchCompiledQuery
6+
} from '@powersync/common';
27
import React from 'react';
38
import { usePowerSync } from '../PowerSyncContext';
49
import { AdditionalOptions } from './watch-types';
@@ -10,7 +15,14 @@ export type InternalHookOptions<DataType> = {
1015
};
1116

1217
export const checkQueryChanged = <T>(query: WatchCompatibleQuery<T>, options: AdditionalOptions) => {
13-
const compiled = query.compile();
18+
let _compiled: WatchCompiledQuery;
19+
try {
20+
_compiled = query.compile();
21+
} catch (error) {
22+
return false; // If compilation fails, we assume the query has changed
23+
}
24+
const compiled = _compiled!;
25+
1426
const stringifiedParams = JSON.stringify(compiled.parameters);
1527
const stringifiedOptions = JSON.stringify(options);
1628

packages/react/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export * from './hooks/PowerSyncContext';
55
export { SuspenseQueryResult } from './hooks/suspense/SuspenseQueryResult';
66
export { useSuspenseQuery } from './hooks/suspense/useSuspenseQuery';
77
export { useWatchedQuerySuspenseSubscription } from './hooks/suspense/useWatchedQuerySuspenseSubscription';
8-
export { useQuery } from './hooks/useQuery';
98
export { useStatus } from './hooks/useStatus';
9+
export { useQuery } from './hooks/watched/useQuery';
10+
export { AdditionalOptions } from './hooks/watched/watch-types';

packages/react/tests/QueryStore.test.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { AbstractPowerSyncDatabase, SQLWatchOptions } from '@powersync/common';
12
import { beforeEach, describe, expect, it } from 'vitest';
23
import { generateQueryKey, getQueryStore, QueryStore } from '../src/QueryStore';
3-
import { AbstractPowerSyncDatabase, SQLWatchOptions } from '@powersync/common';
4+
import { openPowerSync } from './useQuery.test';
45

56
describe('QueryStore', () => {
67
describe('generateQueryKey', () => {
@@ -46,7 +47,7 @@ describe('QueryStore', () => {
4647
let options: SQLWatchOptions;
4748

4849
beforeEach(() => {
49-
db = createMockDatabase();
50+
db = openPowerSync();
5051
store = new QueryStore(db);
5152
query = {};
5253
options = {};

packages/react/tests/useQuery.test.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
import React from 'react';
12
import * as commonSdk from '@powersync/common';
23
import { PowerSyncDatabase } from '@powersync/web';
34
import { act, cleanup, renderHook, waitFor } from '@testing-library/react';
45
import pDefer from 'p-defer';
56
import { beforeEach, describe, expect, it, onTestFinished, vi } from 'vitest';
67
import { PowerSyncContext } from '../src/hooks/PowerSyncContext';
7-
import { useQuery } from '../src/hooks/useQuery';
8-
8+
import { useQuery } from '../src/hooks/watched/useQuery';
99
export const openPowerSync = () => {
1010
const db = new PowerSyncDatabase({
1111
database: { dbFilename: 'test.db' },
@@ -128,8 +128,6 @@ describe('useQuery', () => {
128128
},
129129
{ timeout: 500, interval: 100 }
130130
);
131-
132-
console.log('got to this point');
133131
});
134132

135133
it('should accept compilable queries', async () => {

0 commit comments

Comments
 (0)