diff --git a/.vscode/launch.json b/.vscode/launch.json index 2630e36b8..f136587f7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,13 +37,16 @@ "console": "integratedTerminal", }, { - "name": "Jest: current file in 'packages/web3/'", + "name": "Vitest: current file in 'packages/web3/'", "type": "node", "request": "launch", - "env": { "NODE_ENV": "development", "NODE_TLS_REJECT_UNAUTHORIZED": "0", "NODE_EXTRA_CA_CERTS":"~/river-ca-cert.pem" }, - "program": "${workspaceFolder}/node_modules/.bin/jest", - "runtimeArgs": ["--experimental-vm-modules", "--experimental-wasm-modules"], - "args": ["${file}", "--config", "${workspaceFolder}/packages/web3/jest.config.ts", "-i", "--no-cache", "--forceExit"], + "env": { "NODE_ENV": "development" }, + "program": "${workspaceFolder}/node_modules/vitest/vitest.mjs", + "cwd": "${workspaceFolder}/packages/web3", + "autoAttachChildProcesses": true, + "skipFiles": ["/**", "**/node_modules/**"], + "smartStep": true, + "args": ["run", "${fileBasename}", "--config", "vitest.config.ts"], "console": "integratedTerminal", }, { diff --git a/packages/web3/.eslintrc.json b/packages/web3/.eslintrc.json index 528e38b41..714a30d71 100644 --- a/packages/web3/.eslintrc.json +++ b/packages/web3/.eslintrc.json @@ -6,13 +6,12 @@ "plugin:import/typescript", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", - "plugin:prettier/recommended", - "plugin:jest/recommended" + "plugin:prettier/recommended" ], "parser": "@typescript-eslint/parser", "parserOptions": { "project": ["./tsconfig.eslint.json"] }, "plugins": ["@typescript-eslint", "import"], - "ignorePatterns": ["dist/**", ".turbo/**", "node_modules/**", "jest.config.ts"], + "ignorePatterns": ["dist/**", ".turbo/**", "node_modules/**", "vitest.config.ts"], "rules": { "no-console": "error", "import/no-extraneous-dependencies": [ @@ -54,10 +53,6 @@ { "files": ["**/*.test.*"], "rules": { - "jest/no-standalone-expect": "off", - "jest/expect-expect": "off", - "jest/no-conditional-expect": "off", - "jest/no-disabled-tests": "off", "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/no-floating-promises": "off", "@typescript-eslint/no-non-null-assertion": "off", diff --git a/packages/web3/jest-setup.ts b/packages/web3/jest-setup.ts deleted file mode 100644 index 21ea3639d..000000000 --- a/packages/web3/jest-setup.ts +++ /dev/null @@ -1,3 +0,0 @@ -process.env.NODE_ENV = 'test' - -export {} diff --git a/packages/web3/jest.config.ts b/packages/web3/jest.config.ts deleted file mode 100644 index 29f241f65..000000000 --- a/packages/web3/jest.config.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { JestConfigWithTsJest } from 'ts-jest' - -const config: JestConfigWithTsJest = { - preset: 'ts-jest/presets/default-esm', - testEnvironment: './../jest.env.ts', - testEnvironmentOptions: { - browsers: ['chrome', 'firefox', 'safari'], - url: 'https://localhost:5158', - }, - verbose: true, - testTimeout: 60000, - modulePathIgnorePatterns: ['/dist/'], - testPathIgnorePatterns: ['/dist/', '/node_modules/'], - setupFilesAfterEnv: ['jest-extended/all', '/jest-setup.ts'], - extensionsToTreatAsEsm: ['.ts'], - transform: { - '^.+\\.tsx?$': [ - 'ts-jest', - { - useESM: true, - }, - ], - }, - moduleNameMapper: { - 'bn.js': 'bn.js', - // match "hash.js" but not whateverHash.js - viem has many of these which should not be - '\\bhash\\.js\\b': 'hash.js', - '(.+)\\.js': '$1', - }, - collectCoverage: true, - coverageProvider: 'v8', - coverageReporters: ['json', 'html'], -} - -export default config diff --git a/packages/web3/package.json b/packages/web3/package.json index 00dd03a07..3fea35620 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -11,10 +11,10 @@ "clean": "rm -rf dist", "lint": "yarn eslint --format unix ./src", "lint:fix": "yarn lint --fix", - "my-jest": "NODE_EXTRA_CA_CERTS=${HOME}/river-ca-cert.pem yarn node --trace-warnings -r ../../scripts/node-no-warn.js --experimental-vm-modules --experimental-wasm-modules $(yarn bin jest)", - "test": "yarn my-jest", + "test": "vitest run", + "test:watch": "vitest --watch", "test:ci": "yarn test", - "test:debug": "DEBUG=test yarn my-jest", + "test:debug": "DEBUG=test yarn test", "watch": "tsc --watch" }, "dependencies": { @@ -31,7 +31,6 @@ "zod": "^3.21.4" }, "devDependencies": { - "@types/jest": "^29.5.3", "@types/lodash": "^4.14.186", "@types/node": "^20.5.0", "@typescript-eslint/eslint-plugin": "^6.10.0", @@ -40,13 +39,9 @@ "eslint": "^8.53.0", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^27.2.3", - "jest": "^29.6.2", - "jest-extended": "^4.0.1", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", "typed-emitter": "^2.1.0", - "typescript": "^5.1.6" + "typescript": "^5.1.6", + "vitest": "^2.1.5" }, "files": [ "/dist", diff --git a/packages/web3/src/EntitlementCache.test.ts b/packages/web3/src/EntitlementCache.test.ts index 6f4965fa3..71b28546b 100644 --- a/packages/web3/src/EntitlementCache.test.ts +++ b/packages/web3/src/EntitlementCache.test.ts @@ -37,7 +37,7 @@ class StringCacheResult implements CacheResult { } describe('EntitlementsCacheTests', () => { - test('caches repeat positive values', async () => { + it('caches repeat positive values', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 10, negativeCacheTTLSeconds: 10, @@ -59,7 +59,7 @@ describe('EntitlementsCacheTests', () => { expect(cacheHit2).toBe(true) }) - test('caches repeat negative values', async () => { + it('caches repeat negative values', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 10, negativeCacheTTLSeconds: 10, @@ -81,7 +81,7 @@ describe('EntitlementsCacheTests', () => { expect(cacheHit2).toBe(true) }) - test('caches non-boolean positive values', async () => { + it('caches non-boolean positive values', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 10, negativeCacheTTLSeconds: 10, @@ -103,7 +103,7 @@ describe('EntitlementsCacheTests', () => { expect(cacheHit2).toBe(true) }) - test('caches non-boolean falsy keys', async () => { + it('caches non-boolean falsy keys', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 10, negativeCacheTTLSeconds: 10, @@ -125,7 +125,7 @@ describe('EntitlementsCacheTests', () => { expect(cacheHit2).toBe(true) }) - test('positive cache values expire after ttl', async () => { + it('positive cache values expire after ttl', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 1, negativeCacheTTLSeconds: 10, @@ -150,7 +150,7 @@ describe('EntitlementsCacheTests', () => { expect(cacheHit2).toBe(false) }) - test('negative cache values expire after ttl', async () => { + it('negative cache values expire after ttl', async () => { const cache = new EntitlementCache({ positiveCacheTTLSeconds: 10, negativeCacheTTLSeconds: 1, diff --git a/packages/web3/src/Web3Constants.test.ts b/packages/web3/src/Web3Constants.test.ts index 70cf4a4b6..d6a00ce14 100644 --- a/packages/web3/src/Web3Constants.test.ts +++ b/packages/web3/src/Web3Constants.test.ts @@ -5,11 +5,11 @@ const log = debug('web3:test') describe('Web3Constants', () => { ;`` - test('BASE_SEPOLIA', () => { + it('BASE_SEPOLIA', () => { expect(BASE_SEPOLIA).toBe(84532) }) - test('instantiate provider', () => { + it('instantiate provider', () => { log('testing provider instanciation') const p = new LocalhostWeb3Provider('http://localhost:8545') expect(p).toBeDefined() diff --git a/packages/web3/src/entitlement.test.ts b/packages/web3/src/entitlement.test.ts index b4af89f64..da1d9c6ff 100644 --- a/packages/web3/src/entitlement.test.ts +++ b/packages/web3/src/entitlement.test.ts @@ -61,7 +61,7 @@ function makeRandomOperation(depth: number): Operation { } } -test('random', async () => { +it('random', async () => { const operation = makeRandomOperation(0) // it takes a Uint8Array and returns a Uint8Array const controller = new AbortController() @@ -270,7 +270,7 @@ const nftCases = [ }, ] -test.each(nftCases)('erc721Check - $desc', async (props) => { +it.concurrent.each(nftCases)('erc721Check - $desc', async (props) => { const { check, wallets, expectedResult } = props const controller = new AbortController() @@ -489,7 +489,7 @@ const erc1155Cases = [ }, ] -test.each(erc1155Cases)('ERC1155 Check - $desc', async (props) => { +it.concurrent.each(erc1155Cases)('ERC1155 Check - $desc', async (props) => { const { check, wallets, expectedResult } = props const controller = new AbortController() const result = await evaluateTree(controller, wallets, xchainConfig, check) @@ -533,7 +533,7 @@ const ethBalanceCases = [ }, ] -test.each(ethBalanceCases)('Eth Balance Check - $desc', async (props) => { +it.concurrent.each(ethBalanceCases)('Eth Balance Check - $desc', async (props) => { const { check, wallets, expectedResult } = props const controller = new AbortController() const result = await evaluateTree(controller, wallets, xchainConfig, check) @@ -560,7 +560,7 @@ const ethBalanceCasesMinimalEtherChains = [ }, ] -test.each(ethBalanceCasesMinimalEtherChains)( +it.concurrent.each(ethBalanceCasesMinimalEtherChains)( 'Eth Balance Check - Ether chains < xChain supported chains - $desc', async (props) => { const { check, wallets, expectedResult } = props @@ -668,7 +668,7 @@ const erc20Cases = [ }, ] -test.each(erc20Cases)('erc20Check - $desc', async (props) => { +it.concurrent.each(erc20Cases)('erc20Check - $desc', async (props) => { const { check, wallets, expectedResult } = props const controller = new AbortController() const result = await evaluateTree(controller, wallets, xchainConfig, check) @@ -805,7 +805,7 @@ const errorTests = [ }, ] -test.each(errorTests)('error - $desc', async (props) => { +it.concurrent.each(errorTests)('error - $desc', async (props) => { const { check, error } = props const controller = new AbortController() await expect( @@ -833,7 +833,7 @@ const orCases = [ { leftCheck: falseCheck, rightCheck: falseCheck, expectedResult: ethers.constants.AddressZero }, ] -test.each(orCases)('orOperation', async (props) => { +it.concurrent.each(orCases)('orOperation', async (props) => { const { leftCheck, rightCheck, expectedResult } = props const orOperation: OrOperation = { opType: OperationType.LOGICAL, @@ -874,7 +874,7 @@ const slowOrCases = [ }, ] -test.each(slowOrCases)('slowOrOperation', async (props) => { +it.concurrent.each(slowOrCases)('slowOrOperation', async (props) => { const { leftCheck, rightCheck, expectedResult, expectedTime } = props const operation: OrOperation = { opType: OperationType.LOGICAL, @@ -898,7 +898,7 @@ const andCases = [ { leftCheck: falseCheck, rightCheck: falseCheck, expectedResult: ethers.constants.AddressZero }, ] -test.each(andCases)('andOperation', async (props) => { +it.concurrent.each(andCases)('andOperation', async (props) => { const { leftCheck, rightCheck, expectedResult } = props const operation: AndOperation = { opType: OperationType.LOGICAL, @@ -939,7 +939,7 @@ const slowAndCases = [ }, ] -test.each(slowAndCases)('slowAndOperation', async (props) => { +it.concurrent.each(slowAndCases)('slowAndOperation', async (props) => { const { leftCheck, rightCheck, expectedResult, expectedTime } = props const operation: AndOperation = { opType: OperationType.LOGICAL, @@ -957,13 +957,13 @@ test.each(slowAndCases)('slowAndOperation', async (props) => { expect(timeTaken).toBeCloseTo(expectedTime, -2) }) -test('empty', async () => { +it('empty', async () => { const controller = new AbortController() const result = await evaluateTree(controller, [], xchainConfig, undefined) expect(result).toBe(ethers.constants.AddressZero) }) -test('true', async () => { +it('true', async () => { const operation = trueCheck const controller = new AbortController() @@ -971,7 +971,7 @@ test('true', async () => { expect(result).toBe(MOCK_ADDRESS) }) -test('false', async () => { +it('false', async () => { const operation = falseCheck const controller = new AbortController() @@ -979,7 +979,7 @@ test('false', async () => { expect(result).toBe(ethers.constants.AddressZero) }) -test('encode/decode rule data v2', async () => { +it('encode/decode rule data v2', async () => { const randomTree = makeRandomOperation(5) const data = treeToRuleData(randomTree) @@ -991,7 +991,7 @@ test('encode/decode rule data v2', async () => { expect(randomTree.opType === newTree.opType).toBeTruthy() }) -test('decode empty ruledata v2 to NoopRuleData v1', async () => { +it('decode empty ruledata v2 to NoopRuleData v1', async () => { const converted = convertRuleDataV2ToV1(decodeRuleDataV2(EncodedNoopRuleData)) expect(converted.operations).toHaveLength(0) expect(converted.checkOperations).toHaveLength(0) @@ -1003,7 +1003,7 @@ function addressesEqual(a: string, b: string): boolean { return a.toLowerCase() === b.toLowerCase() } -test('encode/decode rule data', async () => { +it('encode/decode rule data', async () => { const randomTree = makeRandomOperation(5) const data = treeToRuleData(randomTree) const v1 = convertRuleDataV2ToV1(data) @@ -1038,27 +1038,27 @@ test('encode/decode rule data', async () => { } }) -describe('threshold params', () => { - test('encode/decode', () => { +describe.concurrent('threshold params', () => { + it('encode/decode', () => { const encodedParams = encodeThresholdParams({ threshold: BigInt(100) }) const decodedParams = decodeThresholdParams(encodedParams) expect(decodedParams).toEqual({ threshold: BigInt(100) }) }) - test('encode invalid params', () => { + it('encode invalid params', () => { expect(() => encodeThresholdParams({ threshold: BigInt(-1) })).toThrow( 'Invalid threshold -1: must be greater than or equal to 0', ) }) }) -describe('erc1155 params', () => { - test('encode invalid params', () => { +describe.concurrent('erc1155 params', () => { + it('encode invalid params', () => { expect(() => encodeERC1155Params({ threshold: BigInt(-1), tokenId: BigInt(100) })).toThrow( 'Invalid threshold -1: must be greater than or equal to 0', ) }) - test('encode/decode', () => { + it('encode/decode', () => { const encodedParams = encodeERC1155Params({ threshold: BigInt(200), tokenId: BigInt(100) }) const decodedParams = decodeERC1155Params(encodedParams) expect(decodedParams).toEqual({ threshold: BigInt(200), tokenId: BigInt(100) }) @@ -1124,8 +1124,8 @@ function assertOperationsEqual(actual: Operation[], expected: Operation[]) { } } -describe('createOperationsTree', () => { - test('empty', () => { +describe.concurrent('createOperationsTree', () => { + it('empty', () => { const checkOp: DecodedCheckOperation[] = [] const tree = createOperationsTree(checkOp) expect(tree).toEqual({ @@ -1139,7 +1139,7 @@ describe('createOperationsTree', () => { assertOperationsEqual(operations, [NoopOperation]) }) - test('custom entitlement check', () => { + it('custom entitlement check', () => { const checkOp: DecodedCheckOperation[] = [ { type: CheckOperationType.ISENTITLED, @@ -1170,7 +1170,7 @@ describe('createOperationsTree', () => { }) }) - test('single check', () => { + it('single check', () => { const checkOp: DecodedCheckOperation[] = [ { type: CheckOperationType.ERC721, @@ -1201,7 +1201,7 @@ describe('createOperationsTree', () => { }) }) - test('two checks', () => { + it('two checks', () => { const checkOp: DecodedCheckOperation[] = [ { type: CheckOperationType.ISENTITLED, @@ -1286,7 +1286,7 @@ describe('createOperationsTree', () => { ]) }) - test('three checks', () => { + it('three checks', () => { const checkOp: DecodedCheckOperation[] = [ { type: CheckOperationType.ISENTITLED, @@ -1411,14 +1411,14 @@ describe('createOperationsTree', () => { }) }) -describe('DecodedCheckOpBuilder', () => { - test('Untyped', () => { +describe.concurrent('DecodedCheckOpBuilder', () => { + it('Untyped', () => { expect(() => { new DecodedCheckOperationBuilder().build() }).toThrow('DecodedCheckOperation requires a type') }) - test('ERC20s', () => { + it('ERC20s', () => { expect(() => { new DecodedCheckOperationBuilder() .setType(CheckOperationType.ERC20) @@ -1459,7 +1459,7 @@ describe('DecodedCheckOpBuilder', () => { } as DecodedCheckOperation) }) - test('ERC721s', () => { + it('ERC721s', () => { expect(() => { new DecodedCheckOperationBuilder() .setType(CheckOperationType.ERC721) @@ -1500,7 +1500,7 @@ describe('DecodedCheckOpBuilder', () => { } as DecodedCheckOperation) }) - test('ERC1155s', () => { + it('ERC1155s', () => { expect(() => { new DecodedCheckOperationBuilder() .setType(CheckOperationType.ERC1155) @@ -1555,7 +1555,7 @@ describe('DecodedCheckOpBuilder', () => { } as DecodedCheckOperation) }) - test('ETH_BALANCE', () => { + it('ETH_BALANCE', () => { expect(() => { new DecodedCheckOperationBuilder().setType(CheckOperationType.ETH_BALANCE).build() }).toThrow('DecodedCheckOperation of type ETH_BALANCE requires a threshold') @@ -1572,7 +1572,7 @@ describe('DecodedCheckOpBuilder', () => { } as DecodedCheckOperation) }) - test('ISENTITLED', () => { + it('ISENTITLED', () => { expect(() => { new DecodedCheckOperationBuilder() .setType(CheckOperationType.ISENTITLED) diff --git a/packages/web3/src/utils.test.ts b/packages/web3/src/utils.test.ts index a1cb727d1..6ab165c2e 100644 --- a/packages/web3/src/utils.test.ts +++ b/packages/web3/src/utils.test.ts @@ -6,7 +6,7 @@ import { } from './Utils' describe('utils.test.ts', () => { - test('channelMetadataJson', async () => { + it('channelMetadataJson', async () => { expect(parseChannelMetadataJSON('{"name":"name","description":"description"}')).toEqual({ name: 'name', description: 'description', @@ -22,7 +22,7 @@ describe('utils.test.ts', () => { }) describe('SpaceAddressFromSpaceId', () => { - test('should convert space id to space address', () => { + it('should convert space id to space address', () => { expect(SpaceIdFromSpaceAddress('0xd645e5b484b4cf6c7aad2e74f58166c28781a6c9')).toEqual( '10d645e5b484b4cf6c7aad2e74f58166c28781a6c90000000000000000000000', ) @@ -36,11 +36,11 @@ describe('utils.test.ts', () => { }) describe('NoEntitledWalletError', () => { - test('instanceof', () => { + it('instanceof', () => { expect(new NoEntitledWalletError()).toBeInstanceOf(NoEntitledWalletError) }) - test('mix of no entitled wallet and other errors should throw', async () => { + it('mix of no entitled wallet and other errors should throw', async () => { const runtimeError = new Error('test') // An AggregateError with a NoEntitledWalletError and a generic runtime error should //throw a new AggregateError with just the runtime error. @@ -52,7 +52,7 @@ describe('utils.test.ts', () => { ).rejects.toThrow(new AggregateError([runtimeError])) }) - test('only no entitled wallet errors should not throw', async () => { + it('only no entitled wallet errors should not throw', async () => { await expect( Promise.any([ Promise.reject(new NoEntitledWalletError()), diff --git a/packages/web3/tsconfig.eslint.json b/packages/web3/tsconfig.eslint.json index b65f24ed5..2dc1ed8a8 100644 --- a/packages/web3/tsconfig.eslint.json +++ b/packages/web3/tsconfig.eslint.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "include": ["src/**/*", "jest.config.ts", "jest-setup.ts", "tests/**/*"] + "include": ["src/**/*", "tests/**/*"] } diff --git a/packages/web3/tsconfig.json b/packages/web3/tsconfig.json index cd190ce8e..9e933f878 100644 --- a/packages/web3/tsconfig.json +++ b/packages/web3/tsconfig.json @@ -2,7 +2,8 @@ "extends": "./../tsconfig.base.json", "compilerOptions": { "baseUrl": "./src" /* Specify the root folder within your source files. */, - "outDir": "./dist" /* Specify an output folder for all emitted files. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + "types": ["vitest/globals"] }, "include": ["src/**/*"] } diff --git a/packages/web3/vitest.config.ts b/packages/web3/vitest.config.ts new file mode 100644 index 000000000..380f402a1 --- /dev/null +++ b/packages/web3/vitest.config.ts @@ -0,0 +1,3 @@ +import { rootConfig } from '../../vitest.config.mjs' + +export default rootConfig diff --git a/yarn.lock b/yarn.lock index c9cda1d9c..9ed325c2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6477,7 +6477,6 @@ __metadata: "@isaacs/ttlcache": ^1.4.1 "@river-build/dlog": "workspace:^" "@river-build/generated": "workspace:^" - "@types/jest": ^29.5.3 "@types/lodash": ^4.14.186 "@types/node": ^20.5.0 "@typescript-eslint/eslint-plugin": ^6.10.0 @@ -6487,18 +6486,14 @@ __metadata: eslint: ^8.53.0 eslint-import-resolver-typescript: ^3.5.5 eslint-plugin-import: ^2.27.5 - eslint-plugin-jest: ^27.2.3 ethers: ^5.7.2 - jest: ^29.6.2 - jest-extended: ^4.0.1 lodash: ^4.17.21 lru-cache: ^11.0.1 nanoid: ^4.0.0 - ts-jest: ^29.1.1 - ts-node: ^10.9.1 typed-emitter: ^2.1.0 typescript: ^5.1.6 viem: ^1.18.2 + vitest: ^2.1.5 zod: ^3.21.4 languageName: unknown linkType: soft