chore: typecheck web3.js tests (#29422)

* fix: web3.js test typescript errors

Fixes the typescript errors throughout the
web3.js test suite

* fix: node14 test

AbortController is a default in node16 but needs
to be imported for node14

* fix: additional typescript errors

Adds the tests to the tsconfig to auto-include mocha
and fixes remaining typescript errors

* fix: graphql-tools to work with typescript

version of graphql-tools initially installed has incompatible
types preventing ./scripts/typegen.sh from passing when tests
are added to the include path of tsconfig.json

* Don't build typedefs for tests

Co-authored-by: steveluscher <me+github@steveluscher.com>
This commit is contained in:
TJDawson10 2022-12-29 18:02:21 -05:00 committed by GitHub
parent 84e0d12f91
commit 9679bc6d1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 2279 additions and 772 deletions

1489
web3.js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -42,16 +42,16 @@
"clean": "rimraf ./coverage ./lib",
"codecov": "set -ex; npm run test:cover; cat ./coverage/lcov.info | codecov",
"dev": "cross-env NODE_ENV=development rollup -c",
"doc": "set -ex; typedoc --treatWarningsAsErrors",
"doc": "set -ex; typedoc --tsconfig ./tsconfig.library.json --treatWarningsAsErrors",
"type:gen": "./scripts/typegen.sh",
"lint": "set -ex; npm run pretty; eslint . --ext .js,.ts",
"lint:fix": "npm run pretty:fix && eslint . --fix --ext .js,.ts",
"type:check": "tsc -p tsconfig.json --noEmit",
"type:check": "tsc -p tsconfig.library.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
"ok": "run-s lint test doc type:check",
"pretty": "prettier --check '{,{src,test}/**/}*.{j,t}s'",
"pretty:fix": "prettier --write '{,{src,test}/**/}*.{j,t}s'",
"re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git",
"test": "cross-env NODE_ENV=test TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\", \"target\": \"es2019\" }' ts-mocha --require esm './test/**/*.test.ts'",
"test": "cross-env NODE_ENV=test TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\", \"target\": \"es2019\" }' ts-mocha -p ./tsconfig.tests.json --require esm './test/**/*.test.ts'",
"test:cover": "nyc --reporter=lcov npm run test",
"test:live": "TEST_LIVE=1 npm run test",
"test:live-with-test-validator": "start-server-and-test 'solana-test-validator --reset --quiet' http://localhost:8899/health test:live"
@ -113,7 +113,7 @@
"eslint-plugin-prettier": "^4.2.1",
"esm": "^3.2.25",
"mocha": "^10.1.0",
"mockttp": "^2.0.1",
"mockttp": "^3.6.2",
"mz": "^2.7.0",
"node-abort-controller": "^3.0.1",
"npm-run-all": "^4.1.5",

View File

@ -2,7 +2,6 @@ import alias from '@rollup/plugin-alias';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import * as fs from 'fs';
import json from '@rollup/plugin-json';
import path from 'path';
import nodeResolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';

View File

@ -4,4 +4,5 @@ export default {
input: './declarations/index.d.ts',
output: [{file: 'lib/index.d.ts', format: 'es'}],
plugins: [dts()],
external: ['http', 'https'],
};

View File

@ -1,6 +1,7 @@
import fs from 'mz/fs';
import {expect, use} from 'chai';
import chaiAsPromised from 'chai-as-promised';
import {fail} from 'assert';
import {
Connection,
@ -160,10 +161,15 @@ if (process.env.TEST_LIVE) {
])
).value;
const expectedReturnData = new Uint8Array([1, 2, 3]);
var decodedData = Buffer.from(returnData.data[0], returnData.data[1]);
expect(err).to.be.null;
expect(returnData.programId).to.eql(program.publicKey.toString());
expect(decodedData).to.eql(expectedReturnData);
if (returnData) {
var decodedData = Buffer.from(returnData.data[0], returnData.data[1]);
expect(err).to.be.null;
expect(returnData.programId).to.eql(program.publicKey.toString());
expect(decodedData).to.eql(expectedReturnData);
} else {
fail('return data must be defined!');
}
});
it('deprecated - simulate transaction without signature verification', async () => {

View File

@ -551,7 +551,7 @@ describe('Subscriptions', () => {
});
});
describe('upon the socket connection reopening', () => {
let fatalPriorUnubscribe;
let fatalPriorUnubscribe: () => void;
beforeEach(() => {
fatalPriorUnubscribe = fatalUnsubscribe;
stubbedSocket.call.resetHistory();
@ -699,7 +699,7 @@ describe('Subscriptions', () => {
});
});
describe('upon the socket connection reopening', () => {
let fatalPriorSubscription;
let fatalPriorSubscription: () => void;
beforeEach(() => {
fatalPriorSubscription = fatalSubscription;
stubbedSocket.call.resetHistory();

View File

@ -5,9 +5,9 @@ import {expect, use} from 'chai';
import chaiAsPromised from 'chai-as-promised';
import {Agent as HttpAgent} from 'http';
import {Agent as HttpsAgent} from 'https';
import {AbortController} from 'node-abort-controller';
import {match, mock, spy, useFakeTimers, SinonFakeTimers} from 'sinon';
import sinonChai from 'sinon-chai';
import {fail} from 'assert';
import {
Authorized,
@ -25,10 +25,11 @@ import {
AddressLookupTableProgram,
SYSTEM_INSTRUCTION_LAYOUTS,
NONCE_ACCOUNT_LENGTH,
MessageAddressTableLookup,
} from '../src';
import invariant from '../src/utils/assert';
import {toBuffer} from '../src/utils/to-buffer';
import {MOCK_PORT, url} from './url';
import {MOCK_PORT, url, Node14Controller, nodeVersion} from './url';
import {
AccountInfo,
BLOCKHASH_CACHE_TIMEOUT_MS,
@ -171,10 +172,15 @@ describe('Connection', function () {
it('should allow middleware to augment request', async () => {
let connection = new Connection(url, {
fetchMiddleware: (url, options, fetch) => {
options.headers = Object.assign(options.headers, {
Authorization: 'Bearer 123',
});
fetch(url, options);
if (options) {
options.headers = Object.assign(options.headers!, {
Authorization: 'Bearer 123',
});
fetch(url, options);
} else {
fail('options must be defined!');
}
},
});
@ -192,7 +198,7 @@ describe('Connection', function () {
}
describe('override HTTP agent', () => {
let previousBrowserEnv;
let previousBrowserEnv: string | undefined;
beforeEach(() => {
previousBrowserEnv = process.env.BROWSER;
delete process.env.BROWSER;
@ -254,7 +260,9 @@ describe('Connection', function () {
it('should not attribute fetch errors to the middleware', async () => {
let connection = new Connection(url, {
fetchMiddleware: (url, _options, fetch) => {
fetch(url, 'An `Object` was expected here; this is a `TypeError`.');
fetch(url, {
body: 'An `Object` was expected here; this is a `TypeError`.',
});
},
});
const error = await expect(connection.getVersion()).to.be.rejected;
@ -1248,7 +1256,8 @@ describe('Connection', function () {
it('rejects if called with an already-aborted `abortSignal`', () => {
const mockSignature =
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt';
const abortController = new AbortController();
const abortController: any =
nodeVersion >= 16 ? new AbortController() : Node14Controller();
abortController.abort();
expect(
connection.confirmTransaction({
@ -1263,7 +1272,8 @@ describe('Connection', function () {
it('rejects upon receiving an abort signal', async () => {
const mockSignature =
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt';
const abortController = new AbortController();
const abortController: any =
nodeVersion >= 16 ? new AbortController() : Node14Controller();
// Keep the subscription from ever returning data.
await mockRpcMessage({
method: 'signatureSubscribe',
@ -1334,7 +1344,10 @@ describe('Connection', function () {
const mockSignature =
'LPJ18iiyfz3G1LpNNbcBnBtaS4dVBdPHKrnELqikjER2DcvB4iyTgz43nKQJH3JQAJHuZdM1xVh5Cnc5Hc7LrqC';
let resolveResultPromise: (result: SignatureResult) => void;
let resolveResultPromise = function (result: SignatureResult): any {
return result;
};
await mockRpcMessage({
method: 'signatureSubscribe',
params: [mockSignature, {commitment: 'finalized'}],
@ -1344,7 +1357,7 @@ describe('Connection', function () {
});
// Simulate a failure to fetch the block height.
let rejectBlockheightPromise: () => void;
let rejectBlockheightPromise = function (): void {};
await mockRpcResponse({
method: 'getBlockHeight',
params: [],
@ -1375,7 +1388,9 @@ describe('Connection', function () {
const mockSignature =
'LPJ18iiyfz3G1LpNNbcBnBtaS4dVBdPHKrnELqikjER2DcvB4iyTgz43nKQJH3JQAJHuZdM1xVh5Cnc5Hc7LrqC';
let resolveResultPromise: (result: SignatureResult) => void;
let resolveResultPromise = function (result: SignatureResult): any {
return result;
};
await mockRpcMessage({
method: 'signatureSubscribe',
params: [mockSignature, {commitment: 'finalized'}],
@ -1414,7 +1429,8 @@ describe('Connection', function () {
it('rejects if called with an already-aborted `abortSignal`', () => {
const mockSignature =
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt';
const abortController = new AbortController();
const abortController: any =
nodeVersion >= 16 ? new AbortController() : Node14Controller();
abortController.abort();
expect(
connection.confirmTransaction({
@ -1430,7 +1446,8 @@ describe('Connection', function () {
it('rejects upon receiving an abort signal', async () => {
const mockSignature =
'w2Zeq8YkpyB463DttvfzARD7k9ZxGEwbsEw4boEK7jDp3pfoxZbTdLFSsEPhzXhpCcjGi2kHtHFobgX49MMhbWt';
const abortController = new AbortController();
const abortController: any =
nodeVersion >= 16 ? new AbortController() : Node14Controller();
// Keep the subscription from ever returning data.
await mockRpcMessage({
method: 'signatureSubscribe',
@ -1455,7 +1472,9 @@ describe('Connection', function () {
const mockSignature =
'4oCEqwGrMdBeMxpzuWiukCYqSfV4DsSKXSiVVCh1iJ6pS772X7y219JZP3mgqBz5PhsvprpKyhzChjYc3VSBQXzG';
let resolveResultPromise: (result: SignatureResult) => void;
let resolveResultPromise = function (result: SignatureResult): any {
return result;
};
await mockRpcMessage({
method: 'signatureSubscribe',
params: [mockSignature, {commitment: 'finalized'}],
@ -1666,7 +1685,9 @@ describe('Connection', function () {
const mockSignature =
'LPJ18iiyfz3G1LpNNbcBnBtaS4dVBdPHKrnELqikjER2DcvB4iyTgz43nKQJH3JQAJHuZdM1xVh5Cnc5Hc7LrqC';
let resolveResultPromise: (result: SignatureResult) => void;
let resolveResultPromise = function (result: SignatureResult): any {
return result;
};
await mockRpcMessage({
method: 'signatureSubscribe',
params: [mockSignature, {commitment: 'finalized'}],
@ -1676,7 +1697,7 @@ describe('Connection', function () {
});
// Simulate a failure to fetch the nonce account.
let rejectNonceAccountFetchPromise: () => void;
let rejectNonceAccountFetchPromise = function (): void {};
await mockRpcResponse({
method: 'getAccountInfo',
params: [],
@ -1762,7 +1783,9 @@ describe('Connection', function () {
const mockSignature =
'LPJ18iiyfz3G1LpNNbcBnBtaS4dVBdPHKrnELqikjER2DcvB4iyTgz43nKQJH3JQAJHuZdM1xVh5Cnc5Hc7LrqC';
let resolveResultPromise: (result: SignatureResult) => void;
let resolveResultPromise = function (result: SignatureResult): any {
return result;
};
await mockRpcMessage({
method: 'signatureSubscribe',
params: [mockSignature, {commitment: 'finalized'}],
@ -5391,9 +5414,9 @@ describe('Connection', function () {
);
await connection.confirmTransaction({
blockhash: transaction.recentBlockhash,
lastValidBlockHeight: transaction.lastValidBlockHeight,
signature,
blockhash: transaction.recentBlockhash!,
lastValidBlockHeight: transaction.lastValidBlockHeight!,
signature: signature,
});
const response = (await connection.getSignatureStatus(signature)).value;
@ -5733,8 +5756,8 @@ describe('Connection', function () {
}
});
let signature;
let addressTableLookups;
let signature: TransactionSignature;
let addressTableLookups: MessageAddressTableLookup[];
it('send and confirm', async () => {
const {blockhash, lastValidBlockHeight} =
await connection.getLatestBlockhash();
@ -5802,7 +5825,7 @@ describe('Connection', function () {
);
});
let transactionSlot;
let transactionSlot: number;
it('getTransaction', async () => {
// fetch v0 transaction
const fetchedTransaction = await connection.getTransaction(signature, {

View File

@ -53,7 +53,7 @@ export const mockRpcBatchResponse = async ({
});
await mockServer
.post('/')
.forPost('/')
.withJsonBodyIncluding(request)
.thenReply(200, JSON.stringify(response));
};
@ -86,7 +86,7 @@ export const mockRpcResponse = async ({
if (!mockServer) return;
await mockServer
.post('/')
.forPost('/')
.withJsonBodyIncluding({
jsonrpc: '2.0',
method,
@ -128,7 +128,7 @@ const latestBlockhash = async ({
commitment?: Commitment;
}) => {
const blockhash = uniqueBlockhash();
const params = [];
const params: Array<Object> = [];
if (commitment) {
params.push({commitment});
}
@ -154,7 +154,7 @@ const recentBlockhash = async ({
commitment?: Commitment;
}) => {
const blockhash = uniqueBlockhash();
const params = [];
const params: Array<Object> = [];
if (commitment) {
params.push({commitment});
}

View File

@ -292,6 +292,7 @@ describe('Transaction', () => {
foundIndex = ii;
return true;
}
return;
});
return foundIndex;
})(),
@ -342,6 +343,7 @@ describe('Transaction', () => {
foundIndex = ii;
return true;
}
return;
});
return foundIndex;
})(),

View File

@ -1,8 +1,16 @@
import {AbortController as AbortControllerPolyfill} from 'node-abort-controller';
/**
* The connection url to use when running unit tests against a live cluster
*/
export const MOCK_PORT = 9999;
declare var process: {
env: {
TEST_LIVE: string;
};
version: string;
};
export const url = process.env.TEST_LIVE
? 'http://localhost:8899/'
: 'http://localhost:9999/';
@ -11,5 +19,11 @@ export const wsUrl = process.env.TEST_LIVE
? 'ws://localhost:8900/'
: 'ws://localhost:9999/';
export const nodeVersion = Number(process.version.split('.')[0]);
export const Node14Controller = function () {
return new AbortControllerPolyfill();
};
//export const url = 'https://api.devnet.solana.com/';
//export const url = 'http://api.devnet.solana.com/';

View File

@ -1,5 +1,5 @@
{
"extends": "./tsconfig.json",
"extends": "./tsconfig.library.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"stripInternal": true

View File

@ -1,22 +1,9 @@
{
"compilerOptions": {
"target": "esnext",
"allowJs": true,
"declaration": true,
"declarationDir": "declarations",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"baseUrl": "src",
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedParameters": true,
"noUnusedLocals": true
"composite": true
},
"include": ["src"]
"references": [
{"path": "./tsconfig.library.json"},
{"path": "./tsconfig.tests.json"}
]
}

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"declaration": true,
"declarationDir": "declarations"
},
"extends": "./tsconfig.shared.json",
"include": ["src"]
}

View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"module": "esnext",
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"strict": true,
"target": "esnext"
}
}

View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"declaration": false
},
"extends": "./tsconfig.shared.json",
"include": ["test"]
}

File diff suppressed because it is too large Load Diff