Skip to content

Commit

Permalink
feat: add Bun support
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeboone02 committed Jan 4, 2024
1 parent c89f1ce commit c17239d
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 1 deletion.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"setup": "npm install && npm run validate -s",
"test": "kcd-scripts test",
"test:update": "npm test -- --updateSnapshot --coverage",
"test:types": "tsc -p types/__tests__/jest && tsc -p types/__tests__/jest-globals && tsc -p types/__tests__/vitest",
"test:types": "tsc -p types/__tests__/jest && tsc -p types/__tests__/jest-globals && tsc -p types/__tests__/vitest && tsc -p types/__tests__/bun",
"validate": "kcd-scripts validate && npm run test:types"
},
"files": [
Expand Down Expand Up @@ -92,6 +92,8 @@
"devDependencies": {
"@jest/globals": "^29.6.2",
"@rollup/plugin-commonjs": "^25.0.4",
"@types/bun": "latest",
"@types/web": "latest",
"expect": "^29.6.2",
"jest-environment-jsdom-sixteen": "^1.0.3",
"jest-watch-select-projects": "^2.0.0",
Expand All @@ -105,6 +107,7 @@
},
"peerDependencies": {
"@jest/globals": ">= 28",
"@types/bun": "latest",
"@types/jest": ">= 28",
"jest": ">= 28",
"vitest": ">= 0.32"
Expand All @@ -113,6 +116,9 @@
"@jest/globals": {
"optional": true
},
"@types/bun": {
"optional": true
},
"@types/jest": {
"optional": true
},
Expand Down
98 changes: 98 additions & 0 deletions types/__tests__/bun/bun-custom-expect-types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* File that tests whether the TypeScript typings work as expected.
*/

/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/no-unsafe-argument */

import {expect} from 'bun:test'
import * as matchersStandalone from '../../matchers-standalone'
import * as originalMatchers from '../../matchers'

expect.extend(matchersStandalone)

const element: HTMLElement = document.body

function customExpect(
_actual: HTMLElement,
):
| originalMatchers.TestingLibraryMatchers<unknown, void>
| originalMatchers.TestingLibraryMatchers<unknown, Promise<void>> {
throw new Error('Method not implemented.')
}

customExpect(element).toBeInTheDOM()
customExpect(element).toBeInTheDOM(document.body)
customExpect(element).toBeInTheDocument()
customExpect(element).toBeVisible()
customExpect(element).toBeEmpty()
customExpect(element).toBeDisabled()
customExpect(element).toBeEnabled()
customExpect(element).toBeInvalid()
customExpect(element).toBeRequired()
customExpect(element).toBeValid()
customExpect(element).toContainElement(document.body)
customExpect(element).toContainElement(null)
customExpect(element).toContainHTML('body')
customExpect(element).toHaveAttribute('attr')
customExpect(element).toHaveAttribute('attr', true)
customExpect(element).toHaveAttribute('attr', 'yes')
customExpect(element).toHaveClass()
customExpect(element).toHaveClass('cls1')
customExpect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
customExpect(element).toHaveClass('cls1', {exact: true})
customExpect(element).toHaveDisplayValue('str')
customExpect(element).toHaveDisplayValue(['str1', 'str2'])
customExpect(element).toHaveDisplayValue(/str/)
customExpect(element).toHaveDisplayValue([/str1/, 'str2'])
customExpect(element).toHaveFocus()
customExpect(element).toHaveFormValues({foo: 'bar', baz: 1})
customExpect(element).toHaveStyle('display: block')
customExpect(element).toHaveStyle({display: 'block', width: 100})
customExpect(element).toHaveTextContent('Text')
customExpect(element).toHaveTextContent(/Text/)
customExpect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
customExpect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
customExpect(element).toHaveValue()
customExpect(element).toHaveValue('str')
customExpect(element).toHaveValue(['str1', 'str2'])
customExpect(element).toHaveValue(1)
customExpect(element).toHaveValue(null)
customExpect(element).toBeChecked()
customExpect(element).toHaveDescription('some description')
customExpect(element).toHaveDescription(/some description/)
customExpect(element).toHaveDescription(expect.stringContaining('partial'))
customExpect(element).toHaveDescription()
customExpect(element).toHaveAccessibleDescription('some description')
customExpect(element).toHaveAccessibleDescription(/some description/)
customExpect(element).toHaveAccessibleDescription(
expect.stringContaining('partial'),
)
customExpect(element).toHaveAccessibleDescription()

customExpect(element).toHaveAccessibleErrorMessage()
customExpect(element).toHaveAccessibleErrorMessage(
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
)
customExpect(element).toHaveAccessibleErrorMessage(/invalid time/i)
customExpect(element).toHaveAccessibleErrorMessage(
expect.stringContaining('Invalid time'),
)

customExpect(element).toHaveAccessibleName('a label')
customExpect(element).toHaveAccessibleName(/a label/)
customExpect(element).toHaveAccessibleName(
expect.stringContaining('partial label'),
)
customExpect(element).toHaveAccessibleName()
customExpect(element).toHaveErrorMessage(
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
)
customExpect(element).toHaveErrorMessage(/invalid time/i)
customExpect(element).toHaveErrorMessage(
expect.stringContaining('Invalid time'),
)

// @ts-expect-error The types accidentally allowed any property by falling back to "any"
customExpect(element).nonExistentProperty()
118 changes: 118 additions & 0 deletions types/__tests__/bun/bun-types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* File that tests whether the TypeScript typings for @types/jest work as expected.
*/

/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/no-unsafe-argument */

import {expect} from 'bun:test'
import '../../bun'

const element: HTMLElement = document.body

expect(element).toBeInTheDOM()
expect(element).toBeInTheDOM(document.body)
expect(element).toBeInTheDocument()
expect(element).toBeVisible()
expect(element).toBeEmpty()
expect(element).toBeDisabled()
expect(element).toBeEnabled()
expect(element).toBeInvalid()
expect(element).toBeRequired()
expect(element).toBeValid()
expect(element).toContainElement(document.body)
expect(element).toContainElement(null)
expect(element).toContainHTML('body')
expect(element).toHaveAttribute('attr')
expect(element).toHaveAttribute('attr', true)
expect(element).toHaveAttribute('attr', 'yes')
expect(element).toHaveClass()
expect(element).toHaveClass('cls1')
expect(element).toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
expect(element).toHaveClass('cls1', {exact: true})
expect(element).toHaveDisplayValue('str')
expect(element).toHaveDisplayValue(['str1', 'str2'])
expect(element).toHaveDisplayValue(/str/)
expect(element).toHaveDisplayValue([/str1/, 'str2'])
expect(element).toHaveFocus()
expect(element).toHaveFormValues({foo: 'bar', baz: 1})
expect(element).toHaveStyle('display: block')
expect(element).toHaveStyle({display: 'block', width: 100})
expect(element).toHaveTextContent('Text')
expect(element).toHaveTextContent(/Text/)
expect(element).toHaveTextContent('Text', {normalizeWhitespace: true})
expect(element).toHaveTextContent(/Text/, {normalizeWhitespace: true})
expect(element).toHaveValue()
expect(element).toHaveValue('str')
expect(element).toHaveValue(['str1', 'str2'])
expect(element).toHaveValue(1)
expect(element).toHaveValue(null)
expect(element).toBeChecked()
expect(element).toHaveDescription('some description')
expect(element).toHaveDescription(/some description/)
expect(element).toHaveDescription(expect.stringContaining('partial'))
expect(element).toHaveDescription()
expect(element).toHaveAccessibleDescription('some description')
expect(element).toHaveAccessibleDescription(/some description/)
expect(element).toHaveAccessibleDescription(expect.stringContaining('partial'))
expect(element).toHaveAccessibleDescription()
expect(element).toHaveAccessibleName('a label')
expect(element).toHaveAccessibleName(/a label/)
expect(element).toHaveAccessibleName(expect.stringContaining('partial label'))
expect(element).toHaveAccessibleName()
expect(element).toHaveErrorMessage(
'Invalid time: the time must be between 9:00 AM and 5:00 PM',
)
expect(element).toHaveErrorMessage(/invalid time/i)
expect(element).toHaveErrorMessage(expect.stringContaining('Invalid time'))

expect(element).not.toBeInTheDOM()
expect(element).not.toBeInTheDOM(document.body)
expect(element).not.toBeInTheDocument()
expect(element).not.toBeVisible()
expect(element).not.toBeEmpty()
expect(element).not.toBeEmptyDOMElement()
expect(element).not.toBeDisabled()
expect(element).not.toBeEnabled()
expect(element).not.toBeInvalid()
expect(element).not.toBeRequired()
expect(element).not.toBeValid()
expect(element).not.toContainElement(document.body)
expect(element).not.toContainElement(null)
expect(element).not.toContainHTML('body')
expect(element).not.toHaveAttribute('attr')
expect(element).not.toHaveAttribute('attr', true)
expect(element).not.toHaveAttribute('attr', 'yes')
expect(element).not.toHaveClass()
expect(element).not.toHaveClass('cls1')
expect(element).not.toHaveClass('cls1', 'cls2', 'cls3', 'cls4')
expect(element).not.toHaveClass('cls1', {exact: true})
expect(element).not.toHaveDisplayValue('str')
expect(element).not.toHaveDisplayValue(['str1', 'str2'])
expect(element).not.toHaveDisplayValue(/str/)
expect(element).not.toHaveDisplayValue([/str1/, 'str2'])
expect(element).not.toHaveFocus()
expect(element).not.toHaveFormValues({foo: 'bar', baz: 1})
expect(element).not.toHaveStyle('display: block')
expect(element).not.toHaveTextContent('Text')
expect(element).not.toHaveTextContent(/Text/)
expect(element).not.toHaveTextContent('Text', {normalizeWhitespace: true})
expect(element).not.toHaveTextContent(/Text/, {normalizeWhitespace: true})
expect(element).not.toHaveValue()
expect(element).not.toHaveValue('str')
expect(element).not.toHaveValue(['str1', 'str2'])
expect(element).not.toHaveValue(1)
expect(element).not.toBeChecked()
expect(element).not.toHaveDescription('some description')
expect(element).not.toHaveDescription()
expect(element).not.toHaveAccessibleDescription('some description')
expect(element).not.toHaveAccessibleDescription()
expect(element).not.toHaveAccessibleName('a label')
expect(element).not.toHaveAccessibleName()
expect(element).not.toBePartiallyChecked()
expect(element).not.toHaveErrorMessage()
expect(element).not.toHaveErrorMessage('Pikachu!')

// @ts-expect-error The types accidentally allowed any property by falling back to "any"
expect(element).nonExistentProperty()
9 changes: 9 additions & 0 deletions types/__tests__/bun/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"types": ["bun", "web"]
},
"include": ["*.ts"]
}
11 changes: 11 additions & 0 deletions types/bun.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {type expect} from 'bun:test'
import {type TestingLibraryMatchers} from './matchers'

export {}
declare module 'bun:test' {
interface Matchers<T = any>
extends TestingLibraryMatchers<
ReturnType<typeof expect.stringContaining>,
T
> {}
}

0 comments on commit c17239d

Please sign in to comment.