-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
105 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 37 additions & 18 deletions
55
packages/backend/src/tests/propertyBased/properties/defer.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,56 @@ | ||
import { describe } from "node:test"; | ||
import { ArbitraryQueryBuilder } from "../arbitraries/ArbitraryQueryBuilder"; | ||
import { test } from "@fast-check/vitest"; | ||
import { queryEngine } from "../../queryEngine"; | ||
import { expect } from "vitest"; | ||
import { queryHeight } from "../../util/queryHeight"; | ||
import { flattenDeferredQueryResult } from "../../util/flattenDeferredResults"; | ||
import { describe } from 'node:test'; | ||
import { ArbitraryQueryBuilder } from '../arbitraries/ArbitraryQueryBuilder'; | ||
import { test } from '@fast-check/vitest'; | ||
import { queryEngine } from '../../queryEngine'; | ||
import { expect } from 'vitest'; | ||
import { queryHeight } from '../../util/queryHeight'; | ||
import { flattenDeferredQueryResult } from '../../util/flattenDeferredQueryResults'; | ||
import { Query } from '@synthql/queries'; | ||
import { DB } from '../../generated'; | ||
|
||
const queryBuilder = ArbitraryQueryBuilder.fromPagila(); | ||
|
||
describe('property based tests for defer', () => { | ||
const numRuns = 100; | ||
const timeout = numRuns * 20; | ||
const timeout = numRuns * 100; | ||
const endOnFailure = true; | ||
|
||
|
||
test.prop([queryBuilder.withCardinality('many').withSomeResults().build()], { | ||
verbose: true, | ||
numRuns, | ||
timeout, | ||
endOnFailure, | ||
})( | ||
'A query and a defer() query return essentially the same result', | ||
test.prop( | ||
[queryBuilder.withCardinality('many').withSomeResults().build()], | ||
{ | ||
verbose: true, | ||
numRuns, | ||
endOnFailure, | ||
}, | ||
)( | ||
[ | ||
'A query and a deferred query return essentially the same QueryResult', | ||
].join(''), | ||
async (query) => { | ||
// so far we're only generating queries of height 1 | ||
// this is here as a reminder when we start supporting deeper queries. | ||
// The moment we start supporting deeper queries, this line will break, | ||
// but the rest of the test should still pass. | ||
expect(queryHeight(query)).toBe(1); | ||
const queryResult = await queryEngine.executeAndWait(query); | ||
|
||
// as a quick sanity check, make sure there are actually some results | ||
expect(queryResult).not.toEqual([]); | ||
|
||
// now another sanity check on the flattenDeferResultsRecursively | ||
expect(queryResult).toEqual(flattenDeferredQueryResult(query)); | ||
expect(queryResult).toEqual( | ||
flattenDeferredQueryResult(queryResult), | ||
); | ||
|
||
const deferredQuery: Query<DB> = { ...query, lazy: true }; | ||
|
||
const deferredQueryResult = | ||
await queryEngine.executeAndWait(deferredQuery); | ||
|
||
expect(queryResult).toEqual( | ||
flattenDeferredQueryResult(deferredQueryResult), | ||
); | ||
}, | ||
timeout, | ||
); | ||
}); | ||
|
32 changes: 17 additions & 15 deletions
32
...til/flattenDeferredQueryResultsResults.ts → ...tests/util/flattenDeferredQueryResults.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,42 @@ | ||
import { DeferredResult } from "@synthql/queries"; | ||
import { getObjectChildren, iterateTree } from "../../util/tree/iterateTree"; | ||
import { DeferredResult } from '@synthql/queries'; | ||
import { mapRecursive } from '../../util/tree/mapRecursive'; | ||
|
||
/** | ||
* Function used for testing to flatten deferred results in a query object. | ||
* | ||
* | ||
* Example: | ||
* | ||
* | ||
* ```ts | ||
* {user_id: string, friends: DeferredResult<{user_id: string, name: string}[]>} | ||
* ``` | ||
* | ||
* | ||
* Becomes: | ||
* | ||
* ```ts | ||
* | ||
* ```ts | ||
* {user_id: string, friends: {user_id: string, name: string}[]} | ||
* ``` | ||
*/ | ||
export function flattenDeferredQueryResult(queryWithDeferResult: { [key: string]: any }) { | ||
for (const { node, path, parent } of iterateTree(queryWithDeferResult, getObjectChildren)) { | ||
if (isDeferredResult(node) && parent) { | ||
const key = path[path.length - 1]; | ||
parent[key] = node.data; | ||
export function flattenDeferredQueryResult(queryWithDeferResult: { | ||
[key: string]: any; | ||
}) { | ||
return mapRecursive(queryWithDeferResult, (node) => { | ||
if (isDeferredResult(node)) { | ||
return node.data; | ||
} | ||
} | ||
return node; | ||
}); | ||
} | ||
|
||
type DoneDeferredResult<T = unknown> = DeferredResult<T> & { status: 'done' }; | ||
|
||
// note that this cannot be made a general purpose function because it can very easily produce | ||
// false positives. This is only intended to be used in tests. | ||
// Maybe in the future we will force DeferredResult | ||
// Maybe in the future we will force DeferredResult | ||
function isDeferredResult<T = unknown>(x: any): x is DoneDeferredResult<T> { | ||
return ( | ||
x !== null && | ||
x !== undefined && | ||
x.status === 'done' && | ||
x.data !== undefined | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export function mapRecursive<T>( | ||
item: T, | ||
visitor: (traversable: unknown) => T, | ||
): T { | ||
const result = visitor(item); | ||
|
||
if ( | ||
result === null || | ||
typeof result !== 'object' || | ||
result instanceof Date | ||
) { | ||
return result; | ||
} | ||
|
||
for (const [key, value] of Object.entries(result)) { | ||
// @ts-ignore this operation is safe because we know that the result is an object | ||
result[key] = mapRecursive(value, visitor); | ||
} | ||
|
||
return result; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.