diff --git a/CHANGELOG.md b/CHANGELOG.md index e45ffd5..0ca4ca6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added +- Added support for the Bun.js test runner. + +### Changed +- Updated `README.md` with examples and instructions for using the Bun matchers. + ## [0.9.0] - 2025-07-07 ### Added diff --git a/README.md b/README.md index 0bff10f..f4ae41a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # test-utils -This package contains useful testing utilities, such as unit test matchers (for jest and chai) and other useful functions, such as `randomAddress`. +This package contains useful testing utilities, such as unit test matchers (for jest, chai, and bun) and other useful functions, such as `randomAddress`. ## Installation @@ -14,11 +14,43 @@ npm i --save-dev @ton/test-utils ## Usage -To use the test matchers, just install either jest or chai and import this package like so: +To use the test matchers, just install either jest, chai, or bun and import this package like so: ```typescript import "@ton/test-utils"; ``` +### Examples + +#### Jest +```typescript +import { expect } from '@jest/globals'; +import "@ton/test-utils"; + +test('cell comparison', () => { + expect(cell1).toEqualCell(cell2); +}); +``` + +#### Chai +```typescript +import { expect } from 'chai'; +import "@ton/test-utils"; + +it('cell comparison', () => { + expect(cell1).to.equalCell(cell2); +}); +``` + +#### Bun +```typescript +import { expect, test } from 'bun:test'; +import "@ton/test-utils"; + +test('cell comparison', () => { + expect(cell1).toEqualCell(cell2); +}); +``` + ### Transaction matcher notice The transaction matcher (`.toHaveTransaction`) can only perform matching on transactions with descriptions of type `generic`. When matching an array of transactions, all transactions of other types will be filtered out. When matching a single transaction of non-generic type, an exception will be thrown. diff --git a/package.json b/package.json index baee181..809b91e 100644 --- a/package.json +++ b/package.json @@ -17,23 +17,28 @@ "@ton/core": "^0.49.2", "@ton/crypto": "^3.2.0", "@ton/toolchain": "the-ton-tech/toolchain#v1.4.0", + "@types/bun": "^1.2.19", "@types/chai": "^4.3.4", "@types/jest": "^29.4.4", "chai": "^4.3.7", "eslint": "^9.28.0", "jest": "^29.5.0", "ts-jest": "^29.0.5", - "typescript": "^4.9.5" + "typescript": "^5.9.2" }, "peerDependencies": { "@jest/globals": "*", "@ton/core": ">=0.49.2", + "@types/bun": ">=1.0.0", "chai": "*" }, "peerDependenciesMeta": { "@jest/globals": { "optional": true }, + "@types/bun": { + "optional": true + }, "chai": { "optional": true } @@ -46,6 +51,7 @@ "lint": "eslint . --max-warnings 0", "lint:fix": "eslint . --max-warnings 0 --fix", "test": "jest", + "test:bun": "bun test", "build": "rm -rf dist && tsc" }, "packageManager": "yarn@3.6.1" diff --git a/src/index.ts b/src/index.ts index ba848eb..553a201 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export { import './test/jest'; import './test/chai'; +import './test/bun'; export { contractsMeta, ContractsMeta } from './utils/ContractsMeta'; diff --git a/src/test/bun.ts b/src/test/bun.ts new file mode 100644 index 0000000..fe931c0 --- /dev/null +++ b/src/test/bun.ts @@ -0,0 +1,71 @@ +import type { MatcherFunction } from 'expect'; +import { Address, Cell, Slice } from '@ton/core'; + +import { FlatTransactionComparable, compareTransactionForTest } from './transaction'; +import { CompareResult } from './interface'; +import { compareAddressForTest, compareCellForTest, compareSliceForTest } from './comparisons'; +import { compareThrownExitCodeForTest } from './exitCode'; + +function extractResult(result: CompareResult) { + return { + pass: result.pass, + message: () => { + if (result.pass) { + return result.negMessage(); + } else { + return result.posMessage(); + } + }, + }; +} + +function wrapComparer( + comparer: (subject: unknown, cmp: T) => CompareResult | Promise, +): MatcherFunction<[cmp: T]> { + return function (actual, cmp) { + const result = comparer(actual, cmp); + if (result instanceof Promise) { + return result.then(extractResult); + } + return extractResult(result); + }; +} + +const toHaveTransaction = wrapComparer(compareTransactionForTest); +const toEqualCell = wrapComparer(compareCellForTest); +const toEqualAddress = wrapComparer(compareAddressForTest); +const toEqualSlice = wrapComparer(compareSliceForTest); +const toThrowExitCode = wrapComparer(compareThrownExitCodeForTest); + +try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const bunTest = require('bun:test'); + + if (bunTest && bunTest.expect) + bunTest.expect.extend({ + toHaveTransaction, + toEqualCell, + toEqualAddress, + toEqualSlice, + toThrowExitCode, + }); + // eslint-disable-next-line no-empty +} catch (_) {} + +interface TonMatchers { + toHaveTransaction(cmp: FlatTransactionComparable): T; + toEqualCell(cell: Cell): T; + toEqualAddress(address: Address): T; + toEqualSlice(slice: Slice): T; + + /** + * @example + * await expect(() => blockchain.runGetMethod(contract.address, 'test')).toThrowExitCode(11); + */ + toThrowExitCode(exitCode: number): Promise; +} + +declare module 'bun:test' { + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + interface Matchers extends TonMatchers {} +} diff --git a/yarn.lock b/yarn.lock index 23e7a58..02c0d79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1015,6 +1015,7 @@ __metadata: "@ton/core": ^0.49.2 "@ton/crypto": ^3.2.0 "@ton/toolchain": "the-ton-tech/toolchain#v1.4.0" + "@types/bun": ^1.2.19 "@types/chai": ^4.3.4 "@types/jest": ^29.4.4 chai: ^4.3.7 @@ -1022,14 +1023,17 @@ __metadata: jest: ^29.5.0 node-inspect-extracted: ^2.0.0 ts-jest: ^29.0.5 - typescript: ^4.9.5 + typescript: ^5.9.2 peerDependencies: "@jest/globals": "*" "@ton/core": ">=0.49.2" + "@types/bun": ">=1.0.0" chai: "*" peerDependenciesMeta: "@jest/globals": optional: true + "@types/bun": + optional: true chai: optional: true languageName: unknown @@ -1100,6 +1104,15 @@ __metadata: languageName: node linkType: hard +"@types/bun@npm:^1.2.19": + version: 1.2.19 + resolution: "@types/bun@npm:1.2.19" + dependencies: + bun-types: 1.2.19 + checksum: 175d73e404bd5ee336ce2e392c2632195938d8258692193161df5b865c665b0e835521f144d12d450519349ba14e2821bf0e142d8714cb3886f4f9f0672af87a + languageName: node + linkType: hard + "@types/chai@npm:^4.3.4": version: 4.3.4 resolution: "@types/chai@npm:4.3.4" @@ -1772,6 +1785,17 @@ __metadata: languageName: node linkType: hard +"bun-types@npm:1.2.19": + version: 1.2.19 + resolution: "bun-types@npm:1.2.19" + dependencies: + "@types/node": "*" + peerDependencies: + "@types/react": ^19 + checksum: 646e2cb9a74ffbd2b103324d215da2db998a8075b512a3847acceb7042ffa0c9f66288a536af3788d44cc4ca54b2ba2292bb2f034c875d1f7efe1e18ff20c11b + languageName: node + linkType: hard + "cacache@npm:^17.0.0": version: 17.1.3 resolution: "cacache@npm:17.1.3" @@ -5834,23 +5858,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.9.5": - version: 4.9.5 - resolution: "typescript@npm:4.9.5" +"typescript@npm:^5.9.2": + version: 5.9.2 + resolution: "typescript@npm:5.9.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db + checksum: f619cf6773cfe31409279711afd68cdf0859780006c50bc2a7a0c3227f85dea89a3b97248846326f3a17dad72ea90ec27cf61a8387772c680b2252fd02d8497b languageName: node linkType: hard -"typescript@patch:typescript@^4.9.5#~builtin": - version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=289587" +"typescript@patch:typescript@^5.9.2#~builtin": + version: 5.9.2 + resolution: "typescript@patch:typescript@npm%3A5.9.2#~builtin::version=5.9.2&hash=14eedb" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 1f8f3b6aaea19f0f67cba79057674ba580438a7db55057eb89cc06950483c5d632115c14077f6663ea76fd09fce3c190e6414bb98582ec80aa5a4eaf345d5b68 + checksum: e42a701947325500008334622321a6ad073f842f5e7d5e7b588a6346b31fdf51d56082b9ce5cef24312ecd3e48d6c0d4d44da7555f65e2feec18cf62ec540385 languageName: node linkType: hard