Skip to content

Commit 3c9e961

Browse files
committed
feat: migrate packages/cashscript jest to vitest
- replace jest with vitest - remove jest references no longer used - add vitest configuration file in package - refactor extend functions so that they work with vitest - rename jest extensions file as `VitestExtensions.ts` - add vitest types
1 parent 47f163d commit 3c9e961

37 files changed

+241
-215
lines changed

packages/cashscript/jest.config.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/cashscript/jest.setup.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

packages/cashscript/jest/package.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/cashscript/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"prepare": "yarn build",
4343
"prepublishOnly": "yarn test && yarn lint",
4444
"pretest": "yarn build:test",
45-
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest"
45+
"test": "vitest run"
4646
},
4747
"dependencies": {
4848
"@bitauth/libauth": "^3.1.0-next.2",
@@ -56,13 +56,12 @@
5656
"semver": "^7.7.2"
5757
},
5858
"devDependencies": {
59-
"@jest/globals": "^29.7.0",
6059
"@psf/bch-js": "^6.8.0",
6160
"@types/pako": "^2.0.3",
6261
"@types/semver": "^7.5.8",
6362
"eslint": "^8.54.0",
64-
"jest": "^29.7.0",
65-
"typescript": "^5.9.2"
63+
"typescript": "^5.9.2",
64+
"vitest": "^3.2.4"
6665
},
6766
"gitHead": "bf02a4b641d5d03c035d052247a545109c17b708"
6867
}

packages/cashscript/src/test/JestExtensions.ts

Lines changed: 0 additions & 134 deletions
This file was deleted.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { DebugResults } from '../debugging.js';
2+
import { vi, expect } from 'vitest';
3+
4+
interface Debuggable {
5+
debug(): DebugResults | Promise<DebugResults>;
6+
}
7+
8+
interface ExpectationResult {
9+
pass: boolean
10+
message: () => string
11+
// If you pass these, they will automatically appear inside a diff when
12+
// the matcher does not pass, so you don't need to print the diff yourself
13+
actual?: unknown
14+
expected?: unknown
15+
}
16+
17+
export function toLog(
18+
// FIXME: improve type definition
19+
this: any,
20+
transaction: Debuggable,
21+
match?: RegExp | string,
22+
): ExpectationResult {
23+
const loggerSpy = vi.spyOn(console, 'log');
24+
const { utils, isNot } = this;
25+
26+
// Clear any previous calls (if spy reused accidentally)
27+
loggerSpy.mockClear();
28+
29+
// silence actual stdout output
30+
loggerSpy.mockImplementation(() => { });
31+
32+
try {
33+
executeDebug(transaction);
34+
} catch (error) {
35+
if (error instanceof OldTransactionBuilderError) throw error;
36+
}
37+
38+
// We concatenate all the logs into a single string - if no logs are present, we set received to undefined
39+
const receivedBase = loggerSpy.mock.calls.reduce((acc, [log]) => `${acc}\n${log}`, '').trim();
40+
const received = receivedBase === '' ? undefined : receivedBase;
41+
42+
const matcherHint = utils.matcherHint('toLog', 'received', 'expected', { isNot: isNot });
43+
const expectedText = `Expected: ${isNot ? 'not ' : ''}${utils.printExpected(match)}`;
44+
const receivedText = `Received: ${utils.printReceived(received)}`;
45+
const message = (): string => `${matcherHint}\n\n${expectedText}\n${receivedText}`;
46+
47+
try {
48+
// We first check if the expected string is present in any of the individual console.log calls
49+
expect(loggerSpy).toHaveBeenCalledWith(match ? expect.stringMatching(match) : expect.anything());
50+
} catch {
51+
try {
52+
// We add this extra check to allow expect().toLog() to check multiple console.log calls in a single test
53+
// (e.g. for log ordering), which would fail the first check because that compares the individual console.log calls
54+
expect(receivedBase).toMatch(match ? match : expect.anything());
55+
} catch {
56+
return { message, pass: false };
57+
}
58+
} finally {
59+
// Restore the original console.log implementation
60+
loggerSpy.mockRestore();
61+
}
62+
63+
return { message, pass: true };
64+
}
65+
66+
export function toFailRequireWith(
67+
this: any,
68+
transaction: Debuggable,
69+
match: RegExp | string,
70+
): ExpectationResult {
71+
const { utils, isNot } = this;
72+
try {
73+
executeDebug(transaction);
74+
75+
const matcherHint = utils.matcherHint('.toFailRequireWith', undefined, match.toString(), { isNot: isNot });
76+
const message = (): string => `${matcherHint}\n\nContract function did not fail a require statement.`;
77+
return { message, pass: false };
78+
} catch (transactionError: any) {
79+
if (transactionError instanceof OldTransactionBuilderError) throw transactionError;
80+
81+
const matcherHint = utils.matcherHint('toFailRequireWith', 'received', 'expected', { isNot: isNot });
82+
const expectedText = `Expected pattern: ${isNot ? 'not ' : ''}${utils.printExpected(match)}`;
83+
const receivedText = `Received string: ${utils.printReceived(transactionError?.message ?? '')}`;
84+
const message = (): string => `${matcherHint}\n\n${expectedText}\n${receivedText}`;
85+
86+
try {
87+
expect(transactionError?.message ?? '').toMatch(match);
88+
return { message, pass: true };
89+
} catch {
90+
return { message, pass: false };
91+
}
92+
}
93+
}
94+
95+
96+
export function toFailRequire(
97+
this: any,
98+
transaction: Debuggable,
99+
): ExpectationResult {
100+
const { utils } = this;
101+
try {
102+
executeDebug(transaction);
103+
const message = (): string => 'Contract function did not fail a require statement.';
104+
return { message, pass: false };
105+
} catch (transactionError: any) {
106+
if (transactionError instanceof OldTransactionBuilderError) throw transactionError;
107+
108+
const receivedText = `Received string: ${utils.printReceived(transactionError?.message ?? '')}`;
109+
const message = (): string => `Contract function failed a require statement.\n${receivedText}`;
110+
return { message, pass: true };
111+
}
112+
}
113+
114+
115+
// Wrapper function with custom error in case people use it with the old transaction builder
116+
// This is a temporary solution until we fully remove the old transaction builder from the SDK
117+
const executeDebug = (transaction: Debuggable): void => {
118+
const debugResults = transaction.debug();
119+
120+
if (debugResults instanceof Promise) {
121+
debugResults.catch(() => { });
122+
throw new OldTransactionBuilderError();
123+
}
124+
};
125+
126+
class OldTransactionBuilderError extends Error {
127+
constructor() {
128+
super('The CashScript VitestExtensions do not support the old transaction builder since v0.11.0. Please use the new TransactionBuilder class.');
129+
this.name = 'OldTransactionBuilderError';
130+
}
131+
}

packages/cashscript/test/Contract.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import hodlVaultArtifact from './fixture/hodl_vault.artifact.js';
1717
import mecenasArtifact from './fixture/mecenas.artifact.js';
1818
import deprecatedMecenasArtifact from './fixture/deprecated/mecenas-v0.6.0.json' with { type: 'json' };
1919
import boundedBytesArtifact from './fixture/bounded_bytes.artifact.js';
20+
import { describe, expect, it, beforeEach } from 'vitest';
2021

2122
describe('Contract', () => {
2223
describe('new', () => {

packages/cashscript/test/TransactionBuilder.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import twtArtifact from './fixture/transfer_with_timeout.artifact.js';
1919
import { TransactionBuilder } from '../src/TransactionBuilder.js';
2020
import { gatherUtxos, getTxOutputs } from './test-util.js';
2121
import { generateWcTransactionObjectFixture } from './fixture/walletconnect/fixtures.js';
22+
import { describe, expect, it, beforeAll } from 'vitest';
2223

2324
describe('Transaction Builder', () => {
2425
const provider = process.env.TESTS_USE_CHIPNET

packages/cashscript/test/debugging-old-artifacts.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Contract, MockNetworkProvider, randomUtxo, SignatureTemplate, TransactionBuilder } from '../src/index.js';
22
import { alicePkh, alicePriv, alicePub, bobPriv } from './fixture/vars.js';
3+
import { describe, expect, it } from 'vitest';
34

45
const artifact = {
56
contractName: 'P2PKH',

0 commit comments

Comments
 (0)