Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

npm_bin=$(npm bin)

$npm_bin/jest $@
$npm_bin/jest --maxWorkers 3 $@
31 changes: 31 additions & 0 deletions src/__tests__/utils/createTestInParallel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Runs all of the tests declared with this funcion in a file in parallel. This
* breaks any `beforeEach` and `afterEach` functions, but any `beforeAll` and
* `afterAll` functions should work.
*
* This function will break the timing numbers in the Jest console.
*/
export default function createTestInParallel(): (name: string, fn: () => void | Promise<void>) => void {
// All of the test functions. We collect them in a single array so that we can
// call them all at once.
const testFns: Array<() => void | Promise<void>> = []

// The promised results of calling all of our test functions. The single serial
// tests will await these values.
let testResults: Array<Promise<void>> | undefined

return (name: string, fn: () => void | Promise<void>): void => {
// Add the test function and record its position.
const index = testFns.length
testFns.push(fn)

test(name, async () => {
// If the tests have not yet been run then run all of our tests.
if (!testResults) {
testResults = testFns.map(testFn => Promise.resolve(testFn()))
}
// Await the result.
await testResults[index]
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import kitchenSinkSchemaSql from './kitchenSinkSchemaSql'
* client. The client will be connected from the pool at the start of the test,
* and released back at the end. All changes will be rolled back.
*/
export default function withPgClient (fn: (client: Client) => void | Promise<void>): () => Promise<void> {
return async (): Promise<void> => {
export default function withPgClient <T>(fn: (client: Client) => T | Promise<T>): () => Promise<T> {
return async (): Promise<T> => {
let result: T | undefined

// Connect a client from our pool and begin a transaction.
const client = await pgPool.connect()

Expand All @@ -27,8 +29,11 @@ export default function withPgClient (fn: (client: Client) => void | Promise<voi
await client.query(await kitchenSinkSchemaSql)
}
catch (error) {
// tslint:disable-next-line no-console
console.error(error.stack || error)
// Release the client if an error was thrown.
await client.query('rollback')
client.release()
// Log the error for debugging purposes.
console.error(error.stack || error) // tslint:disable-line no-console
throw error
}

Expand All @@ -37,13 +42,17 @@ export default function withPgClient (fn: (client: Client) => void | Promise<voi

// Try to run our test, if it fails we still want to cleanup the client.
try {
await fn(client)
result = await fn(client)
}
// Always rollback our changes and release the client, even if the test
// fails.
finally {
await client.query('rollback')
client.release()
}

// We will always define our result in the above block. It appears that
// TypeScript cannot detect that so we need to tell it with the bang.
return result!
}
}
Loading