Skip to content

Commit

Permalink
chore(tests): BaseCommand tests
Browse files Browse the repository at this point in the history
  • Loading branch information
slowbackspace committed Nov 29, 2021
1 parent 9f6105e commit ef2831f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 13 deletions.
Binary file not shown.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"big.js": "^6.1.1",
"cli-ux": "^5.6.4",
"safe-stable-stringify": "^2.2.0",
"stdout-stderr": "^0.1.13",
"tslib": "^1"
},
"devDependencies": {
Expand Down Expand Up @@ -67,6 +68,9 @@
"transaction": {
"description": "Transaction commands"
}
},
"macos": {
"identifier": "io.blockfrost.cardanocli"
}
},
"repository": "blockfrost/blockfrost-cardano-cli",
Expand Down
1 change: 1 addition & 0 deletions src/constants/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const ERROR = {
FLAG_UNSUPPORTED_TESTNET_MAGIC: `Unsupported testnet magic.`,
FLAG_MISSING_OUT_FILE: 'Missing flag: --out-file',
FILE_CANNOT_READ: 'Cannot read a file',
TX_FILE_UNKNOWN_FORMAT: 'Unknown transaction file format.',
Expand Down
36 changes: 23 additions & 13 deletions src/helpers/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,33 @@ export abstract class BaseCommand extends Command {
this.client = null;
}

private async handleTestnetMagic() {
const { flags } = await this.parse(BaseCommand);
// set flags.testnet based on testnet-magic flag if necessary
const testnetMagic = flags['testnet-magic'];
if (testnetMagic) {
if (testnetMagic === TESTNET_MAGIC) {
if (!flags.testnet) {
// insert testnet flag and remove --testnet-magic TESTNET_MAGIC
this.argv.push('--testnet');
const magicIndex = this.argv.findIndex(a => a === '--testnet-magic');
this.argv.splice(magicIndex, 2);
// flags.testnet = true; // probably useless
}
} else {
throw Error(ERROR.FLAG_UNSUPPORTED_TESTNET_MAGIC);
}
}
}

private async parseBaseCommand() {
await this.handleTestnetMagic();
return this.parse(BaseCommand);
}

async getClient() {
if (!this.client) {
const { flags } = await this.parseBaseCommand();

// set flags.testnet based on testnet-magic flag if necessary
const testnetMagic = flags['testnet-magic'];
if (testnetMagic) {
if (testnetMagic === TESTNET_MAGIC) {
flags.testnet = true;
} else {
throw Error(`Unsupported testnet magic.`);
}
}

this.client = createBlockfrostClient(flags.testnet);
}
return this.client;
Expand Down Expand Up @@ -89,7 +98,7 @@ export abstract class BaseCommand extends Command {
return super.catch(err);
}

run = async (): Promise<void> => {
run = async (): Promise<BaseCommand> => {
const { flags } = await this.parseBaseCommand();
const result = await this.doWork();

Expand All @@ -100,7 +109,8 @@ export abstract class BaseCommand extends Command {
}

if (flags['out-file']) {
this.toFile(result);
await this.toFile(result);
}
return this;
};
}
140 changes: 140 additions & 0 deletions src/helpers/__tests__/BaseCommand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { BaseCommand } from '../BaseCommand';
import { stdout } from 'stdout-stderr';
import * as util from 'util';
import * as fs from 'fs';
import * as blockfrostService from '../../services/blockfrost';

import { stringify } from '../../utils/format';
import { TESTNET_MAGIC } from '../../constants';
import { ERROR } from '../../constants/errors';

export class TestCommand extends BaseCommand {
prettyPrint = (data: any) => {
console.log(data.payload);
};

doWork = async () => {
const { flags } = await this.parse(TestCommand);
return {
payload: 'test complete',
flags: flags,
};
};
}

export class TestClientCommand extends BaseCommand {
doWork = async () => {
const { flags } = await this.parse(TestCommand);
const client = await this.getClient();
const client2 = await this.getClient();
const client3 = await this.getClient();
return 'test complete';
};
}

describe('BaseCommand', () => {
const ORIGINAL_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = { ...ORIGINAL_ENV };
});

afterAll(() => {
process.env = ORIGINAL_ENV;
});

it('should prettyPrint response from doWork', async () => {
stdout.start();
await TestCommand.run([]);
stdout.stop();
expect(stdout.output.includes('test complete')).toBe(true);
});

it('should print raw response from doWork', async () => {
stdout.start();

await TestCommand.run(['--json']);

stdout.stop();

const output = stdout.output;
expect(JSON.parse(output)).toMatchObject({
payload: 'test complete',
});
});

it('should save the response to --out-file', async () => {
jest.spyOn(fs, 'writeFileSync').mockImplementation((path, data) => {});
await TestCommand.run(['--out-file', 'filename']);
expect(fs.writeFileSync).toHaveBeenCalledTimes(1);
expect(fs.writeFileSync).toHaveBeenCalledWith(
'filename',
stringify({
payload: 'test complete',
flags: {
'out-file': 'filename',
},
}),
);
});

it('should set --testnet to true if --testnet-magic TESTNET_MAGIC is set', async () => {
stdout.start();
await TestCommand.run(['--json', '--testnet-magic', `${TESTNET_MAGIC}`]);
stdout.stop();
const output = stdout.output;

expect(JSON.parse(output).flags.testnet).toBe(true);
});

it('should throw on unsupported testnet magic in --testnet-magic', async () => {
expect(() => TestCommand.run(['--json', '--testnet-magic', '123'])).rejects.toHaveProperty(
'message',
ERROR.FLAG_UNSUPPORTED_TESTNET_MAGIC,
);
});

it('should create only one BlockfrostApi instance', async () => {
process.env.BLOCKFROST_PROJECT_ID_MAINNET = 'mainnet123';
const spy = jest.spyOn(blockfrostService, 'createBlockfrostClient');
await TestClientCommand.run([]);
expect(spy).toHaveBeenCalledTimes(1);
spy.mockRestore();
});
});

describe('BaseCommand - 2nd part (runs in series)', () => {
// process.env cant be isolated across tests running in parallel,
// but we can put tests in another describe which is run only after previous is finished
const ORIGINAL_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = { ...ORIGINAL_ENV };
});

afterAll(() => {
process.env = ORIGINAL_ENV;
});

it('should print error when BLOCKFROST_PROJECT_ID_MAINNET is not set', async () => {
process.env.BLOCKFROST_PROJECT_ID_MAINNET = undefined;
process.env.BLOCKFROST_PROJECT_ID_TESNET = undefined;
expect(async () => await TestClientCommand.run([])).rejects.toHaveProperty(
'message',
util.format(ERROR.ENV_PROJECT_ID_NOT_SET, 'BLOCKFROST_PROJECT_ID_MAINNET'),
);
// workaround ReferenceError: You are trying to `import` a file after the Jest environment has been torn down
await new Promise(resolve => setTimeout(() => resolve(true), 500));
});

it('should print error when BLOCKFROST_PROJECT_ID_TESTNET is not set', async () => {
process.env.BLOCKFROST_PROJECT_ID_MAINNET = undefined;
process.env.BLOCKFROST_PROJECT_ID_TESNET = undefined;
expect(async () => await TestClientCommand.run(['--testnet'])).rejects.toHaveProperty(
'message',
util.format(ERROR.ENV_PROJECT_ID_NOT_SET, 'BLOCKFROST_PROJECT_ID_TESTNET'),
);
// workaround ReferenceError: You are trying to `import` a file after the Jest environment has been torn down
await new Promise(resolve => setTimeout(() => resolve(true), 500));
});
});
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,7 @@ __metadata:
oclif: 2.0.0-main.10
prettier: ^2.4.1
safe-stable-stringify: ^2.2.0
stdout-stderr: ^0.1.13
ts-jest: ^27.0.7
ts-node: ^10.4.0
tslib: ^1
Expand Down Expand Up @@ -8617,6 +8618,16 @@ __metadata:
languageName: node
linkType: hard

"stdout-stderr@npm:^0.1.13":
version: 0.1.13
resolution: "stdout-stderr@npm:0.1.13"
dependencies:
debug: ^4.1.1
strip-ansi: ^6.0.0
checksum: 3955a0afa9a483188929796fd9fa9417f845c3bfcd92f132b3ae7d2a862f91a846312e4244f07eb4dd4c5bd2fe95035db5db01679e7d3795d3ea0b772fc7a6f7
languageName: node
linkType: hard

"string-length@npm:^4.0.1":
version: 4.0.2
resolution: "string-length@npm:4.0.2"
Expand Down

0 comments on commit ef2831f

Please sign in to comment.