Skip to content

Commit 8453d8a

Browse files
authored
increase coverage (#19)
* increase coverage * increase coverage
1 parent 66c5559 commit 8453d8a

File tree

10 files changed

+2124
-3
lines changed

10 files changed

+2124
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Token Pools Calldata Generator
22

33
[![CI](https://github.com/smartcontractkit/token-pools-calldata/actions/workflows/ci.yml/badge.svg)](https://github.com/smartcontractkit/token-pools-calldata/actions/workflows/ci.yml)
4-
[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](LICENSE)
4+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
55
[![Node: >=22.0.0](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen)](package.json)
66
[![pnpm](https://img.shields.io/badge/maintained%20with-pnpm-cc00ff.svg)](https://pnpm.io/)
77

jest.config.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ export default {
66
transform: {
77
'^.+\\.ts$': 'ts-jest',
88
},
9-
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.d.ts', '!src/test/**', '!src/typechain/**'],
9+
collectCoverageFrom: [
10+
'src/**/*.ts',
11+
'!src/**/*.d.ts',
12+
'!src/test/**',
13+
'!src/typechain/**',
14+
// CLI entry point is integration code - tested via E2E, not unit tests
15+
'!src/cli.ts',
16+
],
1017
coverageDirectory: 'coverage',
1118
coverageReporters: ['text', 'lcov', 'html', 'json-summary'],
1219
coverageThreshold: {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
},
2626
"keywords": [],
2727
"author": "",
28-
"license": "ISC",
28+
"license": "MIT",
2929
"devDependencies": {
3030
"@typechain/ethers-v6": "^0.5.1",
3131
"@types/jest": "^30.0.0",
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/**
2+
* Tests for OutputService
3+
* Covers high-level output operations for CLI commands
4+
*/
5+
6+
import { OutputService } from '../../output/OutputService';
7+
import { OutputWriterFactory } from '../../output/OutputWriter';
8+
import {
9+
SafeOperationType,
10+
SafeTransactionBuilderJSON,
11+
SAFE_TX_BUILDER_VERSION,
12+
} from '../../types/safe';
13+
import { OUTPUT_FORMAT } from '../../config';
14+
15+
// Mock the OutputWriter module
16+
jest.mock('../../output/OutputWriter', () => {
17+
const mockCalldataWriter = {
18+
write: jest.fn().mockResolvedValue(undefined),
19+
};
20+
const mockJsonWriter = {
21+
write: jest.fn().mockResolvedValue(undefined),
22+
};
23+
return {
24+
CalldataWriter: jest.fn(() => mockCalldataWriter),
25+
JsonWriter: jest.fn(() => mockJsonWriter),
26+
OutputWriterFactory: {
27+
createCalldataWriter: jest.fn(() => mockCalldataWriter),
28+
createJsonWriter: jest.fn(() => mockJsonWriter),
29+
},
30+
};
31+
});
32+
33+
describe('OutputService', () => {
34+
let service: OutputService;
35+
let mockCalldataWriter: { write: jest.Mock };
36+
let mockJsonWriter: { write: jest.Mock };
37+
38+
const mockTransaction = {
39+
to: '0x779877A7B0D9E8603169DdbD7836e478b4624789',
40+
value: '0',
41+
data: '0x1234567890abcdef',
42+
operation: SafeOperationType.Call,
43+
};
44+
45+
const mockSafeJson: SafeTransactionBuilderJSON = {
46+
version: '1.18.0',
47+
chainId: '84532',
48+
createdAt: Date.now(),
49+
meta: {
50+
name: 'Test Transaction',
51+
description: 'Test Description',
52+
txBuilderVersion: SAFE_TX_BUILDER_VERSION,
53+
createdFromSafeAddress: '0x5419c6d83473d1c653e7b51e8568fafedce94f01',
54+
createdFromOwnerAddress: '0x0000000000000000000000000000000000000000',
55+
},
56+
transactions: [
57+
{
58+
to: '0x779877A7B0D9E8603169DdbD7836e478b4624789',
59+
value: '0',
60+
data: '0x1234567890abcdef',
61+
operation: SafeOperationType.Call,
62+
contractMethod: {
63+
inputs: [],
64+
name: 'testFunction',
65+
payable: false,
66+
},
67+
contractInputsValues: null,
68+
},
69+
],
70+
};
71+
72+
beforeEach(() => {
73+
jest.clearAllMocks();
74+
service = new OutputService();
75+
mockCalldataWriter = OutputWriterFactory.createCalldataWriter() as unknown as {
76+
write: jest.Mock;
77+
};
78+
mockJsonWriter = OutputWriterFactory.createJsonWriter() as unknown as { write: jest.Mock };
79+
});
80+
81+
describe('writeCalldata', () => {
82+
it('should write single transaction calldata to console', async () => {
83+
await service.writeCalldata(mockTransaction);
84+
85+
expect(OutputWriterFactory.createCalldataWriter).toHaveBeenCalled();
86+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(mockTransaction.data, {
87+
type: 'console',
88+
});
89+
});
90+
91+
it('should write single transaction calldata to file', async () => {
92+
const outputPath = 'output/calldata.txt';
93+
await service.writeCalldata(mockTransaction, outputPath);
94+
95+
expect(OutputWriterFactory.createCalldataWriter).toHaveBeenCalled();
96+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(mockTransaction.data, {
97+
type: 'file',
98+
path: outputPath,
99+
});
100+
});
101+
102+
it('should write multiple transactions calldata to console', async () => {
103+
const transactions = [mockTransaction, { ...mockTransaction, data: '0xabcdef1234567890' }];
104+
105+
await service.writeCalldata(transactions);
106+
107+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(
108+
`${mockTransaction.data}\n0xabcdef1234567890`,
109+
{ type: 'console' },
110+
);
111+
});
112+
113+
it('should write multiple transactions calldata to file', async () => {
114+
const transactions = [
115+
mockTransaction,
116+
{ ...mockTransaction, data: '0xabcdef1234567890' },
117+
{ ...mockTransaction, data: '0x9999999999999999' },
118+
];
119+
const outputPath = 'output/batch.txt';
120+
121+
await service.writeCalldata(transactions, outputPath);
122+
123+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(
124+
`${mockTransaction.data}\n0xabcdef1234567890\n0x9999999999999999`,
125+
{ type: 'file', path: outputPath },
126+
);
127+
});
128+
129+
it('should handle empty transaction array', async () => {
130+
const transactions: (typeof mockTransaction)[] = [];
131+
132+
await service.writeCalldata(transactions);
133+
134+
expect(mockCalldataWriter.write).toHaveBeenCalledWith('', { type: 'console' });
135+
});
136+
});
137+
138+
describe('writeSafeJson', () => {
139+
it('should write Safe JSON to console', async () => {
140+
await service.writeSafeJson(mockSafeJson);
141+
142+
expect(OutputWriterFactory.createJsonWriter).toHaveBeenCalled();
143+
expect(mockJsonWriter.write).toHaveBeenCalledWith(JSON.stringify(mockSafeJson), {
144+
type: 'console',
145+
});
146+
});
147+
148+
it('should write Safe JSON to file', async () => {
149+
const outputPath = 'output/safe.json';
150+
await service.writeSafeJson(mockSafeJson, outputPath);
151+
152+
expect(OutputWriterFactory.createJsonWriter).toHaveBeenCalled();
153+
expect(mockJsonWriter.write).toHaveBeenCalledWith(JSON.stringify(mockSafeJson), {
154+
type: 'file',
155+
path: outputPath,
156+
});
157+
});
158+
159+
it('should handle Safe JSON with multiple transactions', async () => {
160+
const multiTxSafeJson: SafeTransactionBuilderJSON = {
161+
...mockSafeJson,
162+
transactions: [
163+
mockSafeJson.transactions[0]!,
164+
{
165+
...mockSafeJson.transactions[0]!,
166+
data: '0xsecondtx',
167+
},
168+
],
169+
};
170+
171+
await service.writeSafeJson(multiTxSafeJson);
172+
173+
expect(mockJsonWriter.write).toHaveBeenCalledWith(JSON.stringify(multiTxSafeJson), {
174+
type: 'console',
175+
});
176+
});
177+
});
178+
179+
describe('write', () => {
180+
it('should route to writeSafeJson when format is safe-json', async () => {
181+
const outputPath = 'output/safe.json';
182+
183+
await service.write(OUTPUT_FORMAT.SAFE_JSON, mockTransaction, mockSafeJson, outputPath);
184+
185+
expect(OutputWriterFactory.createJsonWriter).toHaveBeenCalled();
186+
expect(mockJsonWriter.write).toHaveBeenCalled();
187+
});
188+
189+
it('should route to writeCalldata when format is calldata', async () => {
190+
const outputPath = 'output/calldata.txt';
191+
192+
await service.write(OUTPUT_FORMAT.CALLDATA, mockTransaction, null, outputPath);
193+
194+
expect(OutputWriterFactory.createCalldataWriter).toHaveBeenCalled();
195+
expect(mockCalldataWriter.write).toHaveBeenCalled();
196+
});
197+
198+
it('should throw error when safe-json format but no safeJson provided', async () => {
199+
await expect(
200+
service.write(OUTPUT_FORMAT.SAFE_JSON, mockTransaction, null, 'output/safe.json'),
201+
).rejects.toThrow('Safe JSON format requested but no Safe JSON provided');
202+
});
203+
204+
it('should write to console when no outputPath provided for calldata', async () => {
205+
await service.write(OUTPUT_FORMAT.CALLDATA, mockTransaction, null, undefined);
206+
207+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(mockTransaction.data, {
208+
type: 'console',
209+
});
210+
});
211+
212+
it('should write to console when no outputPath provided for safe-json', async () => {
213+
await service.write(OUTPUT_FORMAT.SAFE_JSON, mockTransaction, mockSafeJson, undefined);
214+
215+
expect(mockJsonWriter.write).toHaveBeenCalledWith(JSON.stringify(mockSafeJson), {
216+
type: 'console',
217+
});
218+
});
219+
220+
it('should handle multiple transactions with calldata format', async () => {
221+
const transactions = [mockTransaction, mockTransaction];
222+
223+
await service.write(OUTPUT_FORMAT.CALLDATA, transactions, null, 'output/batch.txt');
224+
225+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(
226+
`${mockTransaction.data}\n${mockTransaction.data}`,
227+
{ type: 'file', path: 'output/batch.txt' },
228+
);
229+
});
230+
231+
it('should ignore safeJson when format is calldata', async () => {
232+
await service.write(
233+
OUTPUT_FORMAT.CALLDATA,
234+
mockTransaction,
235+
mockSafeJson, // Provided but should be ignored
236+
'output/calldata.txt',
237+
);
238+
239+
expect(mockCalldataWriter.write).toHaveBeenCalledWith(mockTransaction.data, {
240+
type: 'file',
241+
path: 'output/calldata.txt',
242+
});
243+
expect(mockJsonWriter.write).not.toHaveBeenCalled();
244+
});
245+
});
246+
});

0 commit comments

Comments
 (0)