Skip to content

Instantly share code, notes, and snippets.

@patrixr
Last active August 11, 2021 07:50
Show Gist options
  • Save patrixr/98f2a9d59c4ba0e45bfeb887a9f0871b to your computer and use it in GitHub Desktop.
Save patrixr/98f2a9d59c4ba0e45bfeb887a9f0871b to your computer and use it in GitHub Desktop.
Typed Test Matrix
// ---------------------------
// ~ Helpers
// ---------------------------
const capitalize = (s : string) => s.charAt(0).toUpperCase() + s.slice(1);
// ---------------------------
// ~ TYPES
// ---------------------------
// CHECK BOTTOM OF FILE
// ---------------------------
// ~ IMPLEMENTATION
// ---------------------------
export function testMatrix<
R, // Type of the row argument
C, // Type of the column argument
RK extends string, // Key of the row argument
CK extends string // Key of the column argument
>(
params : {
row: RN,
column: CN,
rows: [string, () => R][],
columns: [string, () => C][]
}
) {
return {
do(
action: MatrixAction<
MatrixItem<RN, R>,
MatrixItem<CN, C>
>) {
for (const [rowName, rowGetter] of params.rows) {
for (const [colName, colGetter] of params.columns) {
action({
row: <MatrixItem<RN, R>>{
name: rowName,
['get' + capitalize(params.row)]: rowGetter
},
column: <MatrixItem<CN, C>>{
name: colName,
['get' + capitalize(params.column)]: colGetter
}
})
}
}
}
}
}
// ---------------------------
// ~ EXAMPLE TEST
// ---------------------------
let admin : User
let user : User
let owner : User
let publicRecord : Article
let privateRecord : Article
beforeEach(async () => {
tag = await factories.tagFactory.create();
admin = await createUser({ role: 'admin' });
moderator = await createUser();
owner = await createUser();
publicRecord = await createRecord({ type: 'public', owner })
privateRecord = await createRecord({ type: 'private', owner })
})
testMatrix({
row: "user",
column: "record",
rows: [
['admin', () => admin],
['moderator', () => user],
['owner', () => owner]
],
columns: [
['public record', () => publicRecord],
['private record', () => privateRecord]
]
}).do(({ row, column }) => {
context(`As an ${row.name}`, () => {
beforeEach(() => {
setCurrentUser(row.getUser());
})
context(`of a record of type ${column.name}`, () => {
it('gives me access', async () => {
await agent
.get('/record/' + column.getRecord().id)
.expect(200)
})
})
})
});
// ---------------------------
// ~ TYPES
// ---------------------------
export type MatrixGetter<T = any> = {
name: string,
getter: () => T
}
export type MatrixItem<N extends string, T> = (
Record<`get${Capitalize<N>}`, () => T> & { name: string }
)
export type MatrixAction<R, C> = (args : { row: R, column: C }) => any
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment