Skip to content

Commit

Permalink
feat: added assertDate util and unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
arturwojnar committed Apr 5, 2024
1 parent 970a0ac commit 00d1fcb
Show file tree
Hide file tree
Showing 14 changed files with 374 additions and 879 deletions.
1,019 changes: 152 additions & 867 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@
"@microsoft/tsdoc": "~0.14.2",
"@microsoft/tsdoc-config": "~0.16.2",
"@types/jest": "~29.5.12",
"@types/node": "~20.11.30",
"@types/node": "~20.12.4",
"@types/sinon": "~17.0.3",
"@typescript-eslint/eslint-plugin": "~7.4.0",
"@typescript-eslint/parser": "~7.4.0",
"@typescript-eslint/eslint-plugin": "~7.5.0",
"@typescript-eslint/parser": "~7.5.0",
"ajv": "~8.12.0",
"conventional-changelog-conventionalcommits": "~7.0.2",
"eslint": "~8.57.0",
Expand All @@ -81,8 +81,8 @@
"typedoc": "~0.25.12",
"typedoc-material-theme": "~1.0.2",
"typedoc-plugin-markdown": "~3.17.1",
"typescript": "~5.4.3",
"vitepress": "~1.0.1"
"typescript": "~5.4.4",
"vitepress": "~1.0.2"
},
"private": true,
"workspaces": [
Expand Down
19 changes: 19 additions & 0 deletions packages/hermes/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest/presets/default-esm',
extensionsToTreatAsEsm: ['.ts'],
transform: {
'^.+\\.ts$': [
'ts-jest',
{
useESM: true,
tsconfig: 'tsconfig.jest.json',
},
],
},
testMatch: ['**/*/*.test.ts'],
testEnvironment: 'node',
testTimeout: 20000,
collectCoverage: true,
coverageDirectory: 'coverage',
}
13 changes: 7 additions & 6 deletions packages/hermes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"lint:eslint": "eslint 'src/**/*.ts'",
"lint:prettier": "prettier --check \"**/**/!(*.d).{ts,json,md}\"",
"lint-fix": "eslint --fix -f unix \"src/**/*.{ts,tsx}\"",
"test": "echo 1",
"test": "node --experimental-vm-modules ../../node_modules/.bin/jest --colors --coverage --verbose --maxConcurrency=5 --config=jest.config.cjs",
"typecheck": "tsc --noEmit",
"typedoc": "typedoc"
},
Expand Down Expand Up @@ -57,16 +57,17 @@
"access": "public"
},
"devDependencies": {
"@jest/globals": "~29.7.0",
"@microsoft/tsdoc": "~0.14.2",
"@microsoft/tsdoc-config": "~0.16.2",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@types/jest": "~29.5.12",
"@types/node": "~20.11.30",
"@typescript-eslint/eslint-plugin": "~7.4.0",
"@typescript-eslint/parser": "~7.4.0",
"@types/node": "~20.12.4",
"@typescript-eslint/eslint-plugin": "~7.5.0",
"@typescript-eslint/parser": "~7.5.0",
"ajv": "~8.12.0",
"eslint": "~8.57.0",
"eslint-config-prettier": "~9.1.0",
Expand All @@ -78,11 +79,11 @@
"lint-staged": "~15.2.2",
"prettier": "~3.2.5",
"prettier-eslint": "~16.3.0",
"rollup": "^4.13.0",
"rollup": "^4.14.0",
"ts-essentials": "~9.4.1",
"ts-jest": "~29.1.2",
"ts-node": "~10.9.2",
"typedoc": "~0.25.12",
"typescript": "~5.4.3"
"typescript": "~5.4.4"
}
}
7 changes: 6 additions & 1 deletion packages/hermes/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ export default [
sourcemap: true,
},
],
plugins: [json(), typescript({ tsconfig: './tsconfig.build.json' }), resolve(), commonjs()],
plugins: [
json(),
typescript({ tsconfig: './tsconfig.build.json', outputToFilesystem: false }),
resolve(),
commonjs(),
],
onwarn(warning, warn) {
// Check the warning code
if (warning.code === 'CIRCULAR_DEPENDENCY' && /node_modules/.test(warning.message)) {
Expand Down
24 changes: 24 additions & 0 deletions packages/hermes/src/CancellablePromise.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { expect } from '@jest/globals'
import { CancellationPromise } from './CancellablePromise'

test(`CancellationPromise can be resolved`, async () => {
const promise = new CancellationPromise()

expect(promise).toBeInstanceOf(Promise)
expect(typeof promise.resolve).toEqual('function')

promise.resolve('test')

await expect(promise).resolves.toBe('test')
})

test(`CancellationPromise can be rejected`, async () => {
const promise = new CancellationPromise()

expect(promise).toBeInstanceOf(Promise)
expect(typeof promise.reject).toEqual('function')

promise.reject('error')

await expect(promise).rejects.toBe('error')
})
36 changes: 36 additions & 0 deletions packages/hermes/src/addDisposeOnSigterm.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* eslint-disable @typescript-eslint/unbound-method */

import { afterAll, beforeAll, describe, expect, jest } from '@jest/globals'
import { setTimeout } from 'node:timers/promises'
import { addDisposeOnSigterm } from './addDisposeOnSigterm'

describe('addDisposeOnSigterm', () => {
const _processOn = process.on

beforeAll(() => {
process.on = jest.fn<(event: NodeJS.Signals, listener: (signal: NodeJS.Signals) => void) => NodeJS.Process>() as any
})
afterAll(() => {
process.on = _processOn
})

test(`it registers a callback for SIGTERM and SIGINT`, async () => {
const cleanMock = jest.fn<() => Promise<void>>().mockResolvedValue(undefined)

addDisposeOnSigterm(cleanMock)

expect(cleanMock).not.toHaveBeenCalled()
expect(process.on).toHaveBeenCalledTimes(2)
expect(process.on).toHaveBeenCalledWith('SIGTERM', expect.any(Function))

const callback1 = jest.mocked(process.on).mock.calls[0][1]
const callback2 = jest.mocked(process.on).mock.calls[1][1]

callback1()
callback2()

await setTimeout(200)

expect(cleanMock).toHaveBeenCalledTimes(2)
})
})
22 changes: 22 additions & 0 deletions packages/hermes/src/assert.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect } from '@jest/globals'
import { assertDate } from './assert'
import { AssertionError } from './errors'

test(`assertDate throws an AssertionError is the value is not a Date`, () => {
expect(() => assertDate(1)).toThrowError(AssertionError)
expect(() => assertDate('1')).toThrowError(AssertionError)
expect(() => assertDate(new Date('no date'))).toThrowError(AssertionError)
expect(() => assertDate(true)).toThrowError(AssertionError)
expect(() => assertDate({})).toThrowError(AssertionError)
expect(() => assertDate(undefined)).toThrowError(AssertionError)
expect(() => assertDate(null)).toThrowError(AssertionError)
expect(() => assertDate(new Date().getTime())).toThrowError(AssertionError)

try {
assertDate('test')
} catch (error) {
expect(error).toEqual(new AssertionError({ forValue: 'test', forKey: 'date' }, `Value is not a date`))
}

assertDate(new Date()) // no exception
})
7 changes: 7 additions & 0 deletions packages/hermes/src/assert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { AssertionError } from './errors'

export function assertDate(value: unknown): asserts value is Date {
if (!(value instanceof Date) || isNaN(new Date(value).getTime())) {
throw new AssertionError({ forValue: value, forKey: 'date' }, `Value is not a date`)
}
}
16 changes: 16 additions & 0 deletions packages/hermes/src/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { expect } from '@jest/globals'
import { AssertionError, HermesError, HermesErrorCode } from './errors'

test(`HermesError is instance of Error`, () => {
expect(HermesError.prototype.name).toEqual('Error')
})

test(`AssertionError works`, () => {
const error = new AssertionError({ forValue: 'test', forKey: 'date' }, `Value is not a date`)
expect(error).toBeInstanceOf(Error)
expect(error).toBeInstanceOf(HermesError)
expect(error.code).toEqual(HermesErrorCode.Assertion)
expect(error.details?.forKey).toEqual('date')
expect(error.details?.forValue).toEqual('test')
expect(error.message).toEqual('Value is not a date')
})
29 changes: 29 additions & 0 deletions packages/hermes/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
enum HermesErrorCode {
Assertion = 'Assertion',
}

type HermesErrorDetails = {
forKey?: string
forValue?: unknown
}

abstract class HermesError extends Error {
constructor(
public code: HermesErrorCode,
public details?: HermesErrorDetails,
message?: string,
) {
super(message)
}
}

class AssertionError extends HermesError {
constructor(
public details?: HermesErrorDetails,
message?: string,
) {
super(HermesErrorCode.Assertion, details, message)
}
}

export { AssertionError, HermesError, HermesErrorCode }
2 changes: 2 additions & 0 deletions packages/hermes/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { CancellationPromise } from './CancellablePromise'
export { addDisposeOnSigterm } from './addDisposeOnSigterm'
export { assertDate } from './assert'
export { OutboxConsumersCollectionName, OutboxMessagesCollectionName } from './consts'
export { AssertionError, HermesError, HermesErrorCode } from './errors'
export { isNil, noop, swallow } from './utils'
31 changes: 31 additions & 0 deletions packages/hermes/src/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@jest/globals'
import { isNil, noop, swallow } from './utils'

test(`noop is a function that does nothing`, () => {
expect(typeof noop).toEqual('function')
expect(noop()).toBeUndefined()
})

test(`isNil checks whether the value is null or undefined`, () => {
expect(typeof isNil).toEqual('function')
expect(isNil(null)).toBeTruthy()
expect(isNil(undefined)).toBeTruthy()
expect(isNil(0)).toBeFalsy()
expect(isNil('')).toBeFalsy()
expect(isNil(NaN)).toBeFalsy()
expect(isNil({})).toBeFalsy()
expect(isNil([])).toBeFalsy()
expect(isNil('test')).toBeFalsy()
})

test(`swallow cacthes a sync function error and do nothing`, () => {
swallow(() => {
throw new Error()
}) // no error
swallow(() => 'some value')
})

test(`swallow cacthes an async function error and do nothing`, async () => {
await swallow(async () => await Promise.reject(new Error())) // no error
await swallow(async () => await Promise.resolve())
})
18 changes: 18 additions & 0 deletions packages/hermes/tsconfig.jest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": "./tsconfig.json",
"include": ["./src/**/*", "./test/**/*"],
"compilerOptions": {
"composite": true,
"noEmit": true,
"baseUrl": ".",
"outDir": "./dist",
"module": "NodeNext",
"target": "ESNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
}
}

0 comments on commit 00d1fcb

Please sign in to comment.