From 5b8b82ab0b7d026dbb22b85ade63799d34ac722b Mon Sep 17 00:00:00 2001 From: hiletmis <31757771+hiletmis@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:13:07 +0300 Subject: [PATCH 1/5] Add CLI tests --- src/__snapshots__/cli.test.ts.snap | 24 ++++++ src/cli.test.ts | 119 +++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 src/__snapshots__/cli.test.ts.snap create mode 100644 src/cli.test.ts diff --git a/src/__snapshots__/cli.test.ts.snap b/src/__snapshots__/cli.test.ts.snap new file mode 100644 index 00000000..57f2b708 --- /dev/null +++ b/src/__snapshots__/cli.test.ts.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`cli tests should match help output 1`] = ` +"cli.js [command] + +Commands: + cli.js print-api3readerproxyv1-address Prints the dApp-specific + Api3ReaderProxyV1 address + cli.js compute-dapp-id Computes the dApp ID for a given dApp + alias and chain ID + +Options: + --version Show version number [boolean] + --help Show help [boolean]" +`; + +exports[`cli tests should print-api3readerproxyv1-address 1`] = ` +"dApp alias: lendle +chain: Mantle +dAPI name: ETH/USD +• Please confirm that https://market.api3.org/mantle/eth-usd points to an active feed. +• Your proxy is at https://mantlescan.xyz/address/0x776E79D916e49BBDb8FEe0F43fF148C2Ed3bE125 +Please confirm that there is a contract deployed at this address before using it." +`; diff --git a/src/cli.test.ts b/src/cli.test.ts new file mode 100644 index 00000000..55599000 --- /dev/null +++ b/src/cli.test.ts @@ -0,0 +1,119 @@ +import { execSync } from 'node:child_process'; + +import { goSync } from '@api3/promise-utils'; + +const CLI_EXECUTABLE = 'dist/src/cli.js'; + +type CommandArg = [string, string | number | boolean]; + +describe('cli tests', () => { + const execCommand = (command: string, ...args: CommandArg[]) => { + const quote = (val: string) => `"${val}"`; + const formattedArgs = args + .map(([c, a]) => { + // if args is array then quote each elem and separate them with space + if (Array.isArray(a)) return `${c} ${a.map((element) => quote(element)).join(' ')}`; + // otherwise just quote each elem and separate them with space + else return `${c} ${quote(String(a))}`; + }) + .join(' '); + const formattedCommand = `${command} ${formattedArgs}`; + const goExecSync = goSync(() => + execSync(`node ${CLI_EXECUTABLE} ${formattedCommand}`, { + stdio: ['pipe', 'pipe', 'pipe'], + }) + ); + if (!goExecSync.success) { + // rethrow the output of the CLI + throw new Error((goExecSync.error as any).reason.stderr.toString().trim()); + } + + const stdout = goExecSync.data?.toString().trim() || ''; + return stdout; + }; + + it('should compute dApp ID', () => { + const output = execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '5000']); + expect(output).toMatch( + 'dApp alias: lendle\nchain: Mantle\n\n• dApp ID: 3006187377348428698321862179080566497381498372321749245241868771911713393091' + ); + }); + + it('should throw an error for an unknown chain id', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '0']); + }).toThrow('⚠️ Chain with ID 0 is not known'); + }); + + it('should throw an error for an unknown dApp alias', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'unsupported-dapp'], ['--chain-id', '5000']); + }).toThrow('⚠️ Could not find any record for alias "unsupported-dapp"'); + }); + + it('should throw an error for unsupported chain ID', () => { + expect(() => { + execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '1']); + }).toThrow('⚠️ dApp alias "lendle" is not available on chain "Ethereum"'); + }); + + it('should return an invalid output if strict is false', () => { + const output = execCommand( + 'compute-dapp-id', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '0'], + ['--strict', false] + ); + expect(output).toMatch( + 'dApp alias: unsupported-dapp\nchain: 0\n\n• dApp ID: 113044575011858809962820051290270246401920929513853405225169263442003318378526' + ); + }); + + it('should match help output', () => { + const output = execCommand('help'); + expect(output).toMatchSnapshot(); + }); + + it('should throw an error for an unknown chain id while checking Api3ReaderProxyV1 address', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '0'], + ['--dapi-name', 'ETH/USD'] + ); + }).toThrow('Chain with ID 0 is not known'); + }); + + it('should throw an error for an unknown dApp alias while checking Api3ReaderProxyV1 address', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'unsupported-dapp'], + ['--chain-id', '5000'], + ['--dapi-name', 'ETH/USD'] + ); + }).toThrow('⚠️ Could not find any record for alias "unsupported-dapp"'); + }); + + it('should throw an error for an unsupported dApi name', () => { + expect(() => { + execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'lendle'], + ['--chain-id', '5000'], + ['--dapi-name', 'UNSUPPORTED/USD'] + ); + }).toThrow(/⚠️ Attempted to read the feed and failed/); + }); + + it('should print-api3readerproxyv1-address', () => { + const output = execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'lendle'], + ['--chain-id', '5000'], + ['--dapi-name', 'ETH/USD'] + ); + expect(output).toMatchSnapshot(); + }); +}); From a55b15c0dada1f73f4ff23515b1675308d441196 Mon Sep 17 00:00:00 2001 From: hiletmis <31757771+hiletmis@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:13:15 +0300 Subject: [PATCH 2/5] Add empty changeset --- .changeset/chatty-buses-drop.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changeset/chatty-buses-drop.md diff --git a/.changeset/chatty-buses-drop.md b/.changeset/chatty-buses-drop.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/chatty-buses-drop.md @@ -0,0 +1,2 @@ +--- +--- From a30c6d6cbc8d3515ecad1c3fd546f24ecfabe07d Mon Sep 17 00:00:00 2001 From: hiletmis <31757771+hiletmis@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:07:40 +0300 Subject: [PATCH 3/5] Refactor CLI tests to improve clarity --- src/__snapshots__/cli.test.ts.snap | 11 +++++++++- src/cli.test.ts | 33 ++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/__snapshots__/cli.test.ts.snap b/src/__snapshots__/cli.test.ts.snap index 57f2b708..e8358137 100644 --- a/src/__snapshots__/cli.test.ts.snap +++ b/src/__snapshots__/cli.test.ts.snap @@ -14,7 +14,7 @@ Options: --help Show help [boolean]" `; -exports[`cli tests should print-api3readerproxyv1-address 1`] = ` +exports[`cli tests should succeed print-api3readerproxyv1-address on mantle 1`] = ` "dApp alias: lendle chain: Mantle dAPI name: ETH/USD @@ -22,3 +22,12 @@ dAPI name: ETH/USD • Your proxy is at https://mantlescan.xyz/address/0x776E79D916e49BBDb8FEe0F43fF148C2Ed3bE125 Please confirm that there is a contract deployed at this address before using it." `; + +exports[`cli tests should succeed print-api3readerproxyv1-address on sonic 1`] = ` +"dApp alias: mach-finance +chain: Sonic +dAPI name: S/USD +• Please confirm that https://market.api3.org/sonic/s-usd points to an active feed. +• Your proxy is at https://sonicscan.org/address/0x2551A2a96988829D2a55c3b02b88E138023D1cE8 +Please confirm that there is a contract deployed at this address before using it." +`; diff --git a/src/cli.test.ts b/src/cli.test.ts index 55599000..4f2086a5 100644 --- a/src/cli.test.ts +++ b/src/cli.test.ts @@ -32,13 +32,6 @@ describe('cli tests', () => { return stdout; }; - it('should compute dApp ID', () => { - const output = execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '5000']); - expect(output).toMatch( - 'dApp alias: lendle\nchain: Mantle\n\n• dApp ID: 3006187377348428698321862179080566497381498372321749245241868771911713393091' - ); - }); - it('should throw an error for an unknown chain id', () => { expect(() => { execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '0']); @@ -69,6 +62,20 @@ describe('cli tests', () => { ); }); + it('should compute dApp ID for lendle on mantle', () => { + const output = execCommand('compute-dapp-id', ['--dapp-alias', 'lendle'], ['--chain-id', '5000']); + expect(output).toMatch( + 'dApp alias: lendle\nchain: Mantle\n\n• dApp ID: 3006187377348428698321862179080566497381498372321749245241868771911713393091' + ); + }); + + it('should compute dApp ID for mach-finance on sonic', () => { + const output = execCommand('compute-dapp-id', ['--dapp-alias', 'mach-finance'], ['--chain-id', '146']); + expect(output).toMatch( + 'dApp alias: mach-finance\nchain: Sonic\n\n• dApp ID: 103191103032841018751746810000516216875988320776131204933373404128958541332502' + ); + }); + it('should match help output', () => { const output = execCommand('help'); expect(output).toMatchSnapshot(); @@ -107,7 +114,7 @@ describe('cli tests', () => { }).toThrow(/⚠️ Attempted to read the feed and failed/); }); - it('should print-api3readerproxyv1-address', () => { + it('should succeed print-api3readerproxyv1-address on mantle', () => { const output = execCommand( 'print-api3readerproxyv1-address', ['--dapp-alias', 'lendle'], @@ -116,4 +123,14 @@ describe('cli tests', () => { ); expect(output).toMatchSnapshot(); }); + + it('should succeed print-api3readerproxyv1-address on sonic', () => { + const output = execCommand( + 'print-api3readerproxyv1-address', + ['--dapp-alias', 'mach-finance'], + ['--chain-id', '146'], + ['--dapi-name', 'S/USD'] + ); + expect(output).toMatchSnapshot(); + }); }); From 56ea5e4248f600c05aa3a559b5c2d67db44f68c2 Mon Sep 17 00:00:00 2001 From: hiletmis <31757771+hiletmis@users.noreply.github.com> Date: Tue, 19 Aug 2025 10:35:34 +0300 Subject: [PATCH 4/5] Refactor execCommand to simplify argument formatting and error message consistency --- src/cli.test.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/cli.test.ts b/src/cli.test.ts index 4f2086a5..596d7dff 100644 --- a/src/cli.test.ts +++ b/src/cli.test.ts @@ -9,15 +9,7 @@ type CommandArg = [string, string | number | boolean]; describe('cli tests', () => { const execCommand = (command: string, ...args: CommandArg[]) => { const quote = (val: string) => `"${val}"`; - const formattedArgs = args - .map(([c, a]) => { - // if args is array then quote each elem and separate them with space - if (Array.isArray(a)) return `${c} ${a.map((element) => quote(element)).join(' ')}`; - // otherwise just quote each elem and separate them with space - else return `${c} ${quote(String(a))}`; - }) - .join(' '); - const formattedCommand = `${command} ${formattedArgs}`; + const formattedCommand = `${command} ${args.map(([c, a]) => `${c} ${quote(String(a))}`).join(' ')}`; const goExecSync = goSync(() => execSync(`node ${CLI_EXECUTABLE} ${formattedCommand}`, { stdio: ['pipe', 'pipe', 'pipe'], @@ -111,7 +103,7 @@ describe('cli tests', () => { ['--chain-id', '5000'], ['--dapi-name', 'UNSUPPORTED/USD'] ); - }).toThrow(/⚠️ Attempted to read the feed and failed/); + }).toThrow('⚠️ Attempted to read the feed and failed'); }); it('should succeed print-api3readerproxyv1-address on mantle', () => { From d65251b3e8731b1a30c163d8001712adf848672f Mon Sep 17 00:00:00 2001 From: hiletmis <31757771+hiletmis@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:04:59 +0300 Subject: [PATCH 5/5] Refactor execCommand formatting --- src/cli.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cli.test.ts b/src/cli.test.ts index 596d7dff..36da66c8 100644 --- a/src/cli.test.ts +++ b/src/cli.test.ts @@ -8,8 +8,7 @@ type CommandArg = [string, string | number | boolean]; describe('cli tests', () => { const execCommand = (command: string, ...args: CommandArg[]) => { - const quote = (val: string) => `"${val}"`; - const formattedCommand = `${command} ${args.map(([c, a]) => `${c} ${quote(String(a))}`).join(' ')}`; + const formattedCommand = [command, ...args.flatMap(([c, a]) => [c, String(a)])].join(' '); const goExecSync = goSync(() => execSync(`node ${CLI_EXECUTABLE} ${formattedCommand}`, { stdio: ['pipe', 'pipe', 'pipe'],