Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add browser testing to fuel-gauge #2319

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changeset/fast-donkeys-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
136 changes: 69 additions & 67 deletions packages/account/src/test-utils/launchNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { UTXO_ID_LEN } from '@fuel-ts/abi-coder';
import { randomBytes } from '@fuel-ts/crypto';
import { defaultSnapshotConfigs, defaultConsensusKey, hexlify } from '@fuel-ts/utils';
import type { ChildProcessWithoutNullStreams } from 'child_process';
import { spawn } from 'child_process';
import { randomUUID } from 'crypto';
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs';
import os from 'os';
Expand Down Expand Up @@ -205,76 +204,79 @@ export const launchNode = async ({
snapshotDirToUse = tempDirPath;
}

const child = spawn(
command,
[
'run',
['--ip', ipToUse],
['--port', portToUse],
useInMemoryDb ? ['--db-type', 'in-memory'] : ['--db-path', tempDirPath],
['--min-gas-price', '1'],
poaInstant ? ['--poa-instant', 'true'] : [],
['--consensus-key', consensusKey],
['--snapshot', snapshotDirToUse as string],
'--vm-backtrace',
'--utxo-validation',
'--debug',
...remainingArgs,
].flat(),
{
stdio: 'pipe',
if (!process.env.TEST || process.env.TEST_ENV === 'node') {
const { spawn } = await import('child_process');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that tests running in the browser won't need a polyfill for this this import? If so, cool stuff!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sure does!

const child = spawn(
command,
[
'run',
['--ip', ipToUse],
['--port', portToUse],
useInMemoryDb ? ['--db-type', 'in-memory'] : ['--db-path', tempDirPath],
['--min-gas-price', '1'],
poaInstant ? ['--poa-instant', 'true'] : [],
['--consensus-key', consensusKey],
['--snapshot', snapshotDirToUse as string],
'--vm-backtrace',
'--utxo-validation',
'--debug',
...remainingArgs,
].flat(),
{
stdio: 'pipe',
}
);

if (loggingEnabled) {
child.stderr.pipe(process.stderr);
}
);

if (loggingEnabled) {
child.stderr.pipe(process.stderr);
}

if (debugEnabled) {
child.stdout.pipe(process.stdout);
}

const cleanupConfig: KillNodeParams = {
child,
configPath: tempDirPath,
killFn: treeKill,
state: {
isDead: false,
},
};

// Look for a specific graphql start point in the output.
child.stderr.on('data', (chunk: string) => {
// Look for the graphql service start.
if (chunk.indexOf(graphQLStartSubstring) !== -1) {
// Resolve with the cleanup method.
resolve({
cleanup: () => killNode(cleanupConfig),
ip: ipToUse,
port: portToUse,
snapshotDir: snapshotDirToUse as string,
});
}
if (/error/i.test(chunk)) {
reject(chunk.toString());
if (debugEnabled) {
child.stdout.pipe(process.stdout);
}
});

// Process exit.
process.on('exit', () => killNode(cleanupConfig));

// Catches ctrl+c event.
process.on('SIGINT', () => killNode(cleanupConfig));

// Catches "kill pid" (for example: nodemon restart).
process.on('SIGUSR1', () => killNode(cleanupConfig));
process.on('SIGUSR2', () => killNode(cleanupConfig));

// Catches uncaught exceptions.
process.on('beforeExit', () => killNode(cleanupConfig));
process.on('uncaughtException', () => killNode(cleanupConfig));

child.on('error', reject);
const cleanupConfig: KillNodeParams = {
child,
configPath: tempDirPath,
killFn: treeKill,
state: {
isDead: false,
},
};

// Look for a specific graphql start point in the output.
child.stderr.on('data', (chunk: string) => {
// Look for the graphql service start.
if (chunk.indexOf(graphQLStartSubstring) !== -1) {
// Resolve with the cleanup method.
resolve({
cleanup: () => killNode(cleanupConfig),
ip: ipToUse,
port: portToUse,
snapshotDir: snapshotDirToUse as string,
});
}
if (/error/i.test(chunk)) {
reject(chunk.toString());
}
});

// Process exit.
process.on('exit', () => killNode(cleanupConfig));

// Catches ctrl+c event.
process.on('SIGINT', () => killNode(cleanupConfig));

// Catches "kill pid" (for example: nodemon restart).
process.on('SIGUSR1', () => killNode(cleanupConfig));
process.on('SIGUSR2', () => killNode(cleanupConfig));

// Catches uncaught exceptions.
process.on('beforeExit', () => killNode(cleanupConfig));
process.on('uncaughtException', () => killNode(cleanupConfig));

child.on('error', reject);
}
});

const generateWallets = async (count: number, provider: Provider) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/create-fuels/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ export const runScaffoldCli = async ({
let projectPath = program.args[0] ?? (await promptForProjectPath());
const verboseEnabled = program.opts().verbose ?? false;

if (!process.env.VITEST) {
if (!process.env.TEST) {
await tryInstallFuelUp(verboseEnabled);
}

while (existsSync(projectPath)) {
error(`A folder already exists at ${projectPath}. Please choose a different project name.`);

// Exit the program if we are testing to prevent hanging
if (process.env.VITEST) {
if (process.env.TEST) {
throw new Error();
}

Expand All @@ -87,7 +87,7 @@ export const runScaffoldCli = async ({
error('Please specify a project directory.');

// Exit the program if we are testing to prevent hanging
if (process.env.VITEST) {
if (process.env.TEST) {
throw new Error();
}

Expand Down Expand Up @@ -127,7 +127,7 @@ export const runScaffoldCli = async ({
error('You must include at least one Sway program.');

// Exit the program if we are testing to prevent hanging
if (process.env.VITEST) {
if (process.env.TEST) {
throw new Error();
}

Expand Down
1 change: 1 addition & 0 deletions packages/fuel-gauge/src/call-test-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const U64_MAX = bn(2).pow(64).sub(1);

/**
* @group node
* @group browser
*/
describe('CallTestContract', () => {
it.each([0, 1337, U64_MAX.sub(1)])('can call a contract with u64 (%p)', async (num) => {
Expand Down
15 changes: 13 additions & 2 deletions packages/fuel-gauge/src/coverage-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
FUEL_NETWORK_URL,
} from 'fuels';

import { getSetupContract } from './utils';
import type { CoverageContractAbi } from '../test/typegen/contracts';
import { CoverageContractAbi__factory } from '../test/typegen/contracts';
import binHexlified from '../test/typegen/contracts/CoverageContractAbi.hex';

import { createSetupConfig } from './utils';

const RUST_U8_MAX = 255;
const RUST_U16_MAX = 65535;
Expand All @@ -21,7 +25,11 @@
const B512 =
'0x059bc9c43ea1112f3eb2bd30415de72ed24c1c4416a1316f0f48cc6f958073f42a6d8c12e4829826316d8dcf444498717b5a2fbf27defac367271065f6a1d4a5';

const setupContract = getSetupContract('coverage-contract');
const setupContract = createSetupConfig<CoverageContractAbi>({
contractBytecode: binHexlified,
abi: CoverageContractAbi__factory.abi,
cache: true,
});

let contractInstance: Contract;
let baseAssetId: string;
Expand All @@ -48,8 +56,11 @@

/**
* @group node
* @group browser
*/
describe('Coverage Contract', () => {
console.log(process.env);

Check warning on line 62 in packages/fuel-gauge/src/coverage-contract.test.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected console statement

it('can return outputs', async () => {
// Call contract methods
expect((await contractInstance.functions.get_id().call()).value).toEqual(
Expand Down
11 changes: 9 additions & 2 deletions packages/fuels/src/cli/commands/build/buildSwayProgram.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { spawn } from 'child_process';
import type { spawn } from 'child_process';

import type { FuelsConfig } from '../../types';
import { debug, loggingConfig } from '../../utils/logger';
Expand All @@ -8,9 +8,16 @@ import { onForcExit, onForcError } from './forcHandlers';
export const buildSwayProgram = async (config: FuelsConfig, path: string) => {
debug('Building Sway program', path);

let spawnFn: typeof spawn;

if (!process.env.TEST || process.env.TEST_ENV === 'node') {
const { spawn: spawnChildProcess } = await import('child_process');
spawnFn = spawnChildProcess;
}

return new Promise<void>((resolve, reject) => {
const args = ['build', '-p', path].concat(config.forcBuildFlags);
const forc = spawn(config.forcPath, args, { stdio: 'pipe' });
const forc = spawnFn(config.forcPath, args, { stdio: 'pipe' });

if (loggingConfig.isLoggingEnabled) {
forc.stderr?.pipe(process.stderr);
Expand Down
2 changes: 1 addition & 1 deletion packages/fuels/src/cli/config/loadConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function loadConfig(cwd: string): Promise<FuelsConfig> {
const releaseFlag = forcBuildFlags.find((f) => f === '--release');
const buildMode = releaseFlag ? 'release' : 'debug';

const { forcPath, fuelCorePath } = tryFindBinaries({
const { forcPath, fuelCorePath } = await tryFindBinaries({
forcPath: userConfig.forcPath,
fuelCorePath: userConfig.fuelCorePath,
});
Expand Down
16 changes: 8 additions & 8 deletions packages/utils/src/cli-utils/tryFindBinaries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ const mockAllDeps = (
* @group node
*/
describe('tryFindBinaries', () => {
it(`should use default binaries when not paths supplied`, () => {
it(`should use default binaries when not paths supplied`, async () => {
const { getSystemForc, getSystemFuelCore } = mockAllDeps();

const binaries = tryFindBinaries();
const binaries = await tryFindBinaries();

expect(getSystemForc).toHaveBeenCalledTimes(1);
expect(getSystemForc).toBeCalledWith(undefined);
Expand All @@ -72,13 +72,13 @@ describe('tryFindBinaries', () => {
expect(binaries.fuelCorePath).toEqual('fuel-core');
});

it(`should use custom binaries when paths supplied`, () => {
it(`should use custom binaries when paths supplied`, async () => {
const { getSystemForc, getSystemFuelCore } = mockAllDeps();

const forcPath = '/some/path/to/forc';
const fuelCorePath = '/some/path/to/fuel-core';

const binaries = tryFindBinaries({ forcPath, fuelCorePath });
const binaries = await tryFindBinaries({ forcPath, fuelCorePath });

expect(getSystemForc).toHaveBeenCalledTimes(1);
expect(getSystemForc).toBeCalledWith(forcPath);
Expand All @@ -88,10 +88,10 @@ describe('tryFindBinaries', () => {
expect(binaries.fuelCorePath).toEqual(fuelCorePath);
});

it('should handle undefined paths', () => {
it('should handle undefined paths', async () => {
const { getSystemForc, getSystemFuelCore } = mockAllDeps();

const binaries = tryFindBinaries({ forcPath: undefined, fuelCorePath: undefined });
const binaries = await tryFindBinaries({ forcPath: undefined, fuelCorePath: undefined });

expect(getSystemForc).toHaveBeenCalledTimes(1);
expect(getSystemForc).toBeCalledWith(undefined);
Expand Down Expand Up @@ -121,7 +121,7 @@ describe('tryFindBinaries', () => {
);
});

it(`should warn the user when binaries are outdated`, () => {
it(`should warn the user when binaries are outdated`, async () => {
const compatibleVersion = '1.0.0';
const currentVersion = '0.0.1';
const expectedMessage = [
Expand All @@ -135,7 +135,7 @@ describe('tryFindBinaries', () => {
fuelCoreVersion: currentVersion,
});

tryFindBinaries();
await tryFindBinaries();

expect(getSystemForc).toHaveBeenCalledTimes(1);
expect(getSystemFuelCore).toHaveBeenCalledTimes(1);
Expand Down
10 changes: 7 additions & 3 deletions packages/utils/src/cli-utils/tryFindBinaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import {
* @param paths - paths to the binaries (optional)
* @returns - paths to the resolved binaries
*/
export const tryFindBinaries = (paths: { forcPath?: string; fuelCorePath?: string } = {}) => {
export const tryFindBinaries = async (paths: { forcPath?: string; fuelCorePath?: string } = {}) => {
// Ensure we can get the binary versions
const { error: forcError, systemForcPath, systemForcVersion } = getSystemForc(paths.forcPath);
const {
error: forcError,
systemForcPath,
systemForcVersion,
} = await getSystemForc(paths.forcPath);

const {
error: fuelCoreError,
systemFuelCorePath,
systemFuelCoreVersion,
} = getSystemFuelCore(paths.fuelCorePath);
} = await getSystemFuelCore(paths.fuelCorePath);

if (forcError || fuelCoreError) {
const errors = [
Expand Down
2 changes: 1 addition & 1 deletion packages/versions/scripts/rewriteVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const rewriteVersions = () => {
};

/* istanbul ignore next -- @preserve */
if (!process.env.VITEST) {
if (!process.env.TEST) {
// do not auto-run script when inside vitest
rewriteVersions();
}
9 changes: 8 additions & 1 deletion packages/versions/src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
#!/usr/bin/env node
import { error } from 'console';

import { runVersions } from './cli';

runVersions();
(async () => {
await runVersions();
})().catch((e) => {
error(e);
process.exit(1);
});
Loading
Loading