Skip to content

Commit 3d47cab

Browse files
authored
Merge pull request #125 from JohnsonChin1009/test/acpFare
test: added unit testing for acpFare.ts
2 parents 144b011 + 5eae770 commit 3d47cab

1 file changed

Lines changed: 290 additions & 0 deletions

File tree

test/unit/acpFare.test.ts

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
jest.mock("../../src/configs/acpConfigs", () => ({
2+
baseAcpConfig: {
3+
baseFare: {
4+
contractAddress: "0xMockedBaseFare",
5+
decimals: 18,
6+
},
7+
},
8+
AcpContractConfig: {},
9+
}));
10+
11+
jest.mock("viem", () => ({
12+
...jest.requireActual("viem"),
13+
createPublicClient: jest.fn(),
14+
}));
15+
16+
import { Address, createPublicClient } from "viem";
17+
import {
18+
Fare,
19+
FareAmount,
20+
FareBigInt,
21+
FareAmountBase,
22+
wethFare,
23+
ethFare,
24+
} from "../../src/acpFare";
25+
import AcpError from "../../src/acpError";
26+
27+
describe("AcpFare Unit Testing", () => {
28+
// Create mock config to avoid circular dependency
29+
const mockBaseAcpConfig = {
30+
baseFare: new Fare("0xBaseFare" as Address, 18),
31+
chain: { id: 8453 },
32+
rpcUrl: "https://test.rpc",
33+
};
34+
35+
describe("Fare Class", () => {
36+
describe("Constructor", () => {
37+
it("should initialize with correct parameters", () => {
38+
const fare = new Fare("0x1234" as Address, 18);
39+
40+
expect(fare.contractAddress).toBe("0x1234");
41+
expect(fare.decimals).toBe(18);
42+
});
43+
});
44+
45+
describe("formatAmount", () => {
46+
it("should format amount with 18 decimals", () => {
47+
const fare = new Fare("0x1234" as Address, 18);
48+
const result = fare.formatAmount(1);
49+
50+
expect(result).toBe(1000000000000000000n); // 1 * 10^18
51+
});
52+
53+
it("should format amount with 6 decimals", () => {
54+
const fare = new Fare("0x1234" as Address, 6);
55+
const result = fare.formatAmount(1);
56+
57+
expect(result).toBe(1000000n); // 1 * 10^6
58+
});
59+
60+
it("should format decimal amounts", () => {
61+
const fare = new Fare("0x1234" as Address, 18);
62+
const result = fare.formatAmount(1.5);
63+
64+
expect(result).toBe(1500000000000000000n); // 1.5 * 10^18
65+
});
66+
});
67+
68+
describe("fromContractAddress", () => {
69+
it("should return baseFare when address matches config", async () => {
70+
const result = await Fare.fromContractAddress(
71+
mockBaseAcpConfig.baseFare.contractAddress,
72+
mockBaseAcpConfig as any,
73+
);
74+
expect(result).toBe(mockBaseAcpConfig.baseFare);
75+
});
76+
77+
it("should create new Fare by reading decimals from contract", async () => {
78+
const mockAddress = "0xCustomAddress" as Address;
79+
80+
const mockDecimals = 6;
81+
82+
const mockReadContract = jest.fn().mockResolvedValue(mockDecimals);
83+
(createPublicClient as jest.Mock).mockReturnValue({
84+
readContract: mockReadContract,
85+
});
86+
87+
const result = await Fare.fromContractAddress(
88+
mockAddress,
89+
mockBaseAcpConfig as any,
90+
);
91+
92+
expect(result).toBeInstanceOf(Fare);
93+
expect(result.contractAddress).toBe(mockAddress);
94+
expect(result.decimals).toBe(mockDecimals);
95+
expect(mockReadContract).toHaveBeenCalledWith({
96+
address: mockAddress,
97+
abi: expect.any(Array),
98+
functionName: "decimals",
99+
});
100+
});
101+
});
102+
});
103+
104+
describe("FareAmount Class", () => {
105+
let fare: Fare;
106+
107+
beforeEach(() => {
108+
fare = new Fare("0xToken" as Address, 18);
109+
});
110+
111+
describe("Constructor", () => {
112+
it("should create FareAmount with whole number", () => {
113+
const fareAmount = new FareAmount(100, fare);
114+
115+
expect(fareAmount.amount).toBe(100000000000000000000n);
116+
expect(fareAmount.fare).toBe(fare);
117+
});
118+
119+
it("should truncate to 6 decimals", () => {
120+
const fareAmount = new FareAmount(1.123456789, fare);
121+
122+
expect(fareAmount.amount).toBe(1123456000000000000n);
123+
});
124+
125+
it("should handle numbers with less than 6 decimals", () => {
126+
const fareAmount = new FareAmount(5, fare);
127+
128+
expect(fareAmount.amount).toBe(5000000000000000000n);
129+
});
130+
131+
it("should handle numbers without decimals", () => {
132+
const fareAmount = new FareAmount(5, fare);
133+
134+
expect(fareAmount.amount).toBe(5000000000000000000n);
135+
});
136+
});
137+
138+
describe("add", () => {
139+
it("should add two FareAmounts with same token", () => {
140+
const fareAmount1 = new FareAmount(10, fare);
141+
const fareAmount2 = new FareAmount(5, fare);
142+
143+
const result = fareAmount1.add(fareAmount2);
144+
145+
expect(result.fare).toBe(fare);
146+
});
147+
148+
it("should throw error when adding FareAmounts with different tokens", () => {
149+
const fare1 = new Fare("0xToken1" as Address, 18);
150+
const fare2 = new Fare("0xToken2" as Address, 18);
151+
152+
const fareAmount1 = new FareAmount(10, fare1);
153+
const fareAmount2 = new FareAmount(5, fare2);
154+
155+
expect(() => fareAmount1.add(fareAmount2)).toThrow(
156+
"Token addresses do not match",
157+
);
158+
});
159+
160+
it("should add FareAmount with FareBigInt", () => {
161+
const fareAmount = new FareAmount(10, fare);
162+
const fareBigInt = new FareBigInt(5000000000000000000n, fare);
163+
164+
const result = fareAmount.add(fareBigInt);
165+
166+
expect(result).toBeInstanceOf(FareBigInt);
167+
expect(result.amount).toBe(15000000000000000000n);
168+
});
169+
});
170+
});
171+
172+
describe("FareBigInt Class", () => {
173+
let fare: Fare;
174+
175+
beforeEach(() => {
176+
fare = new Fare("0xToken" as Address, 18);
177+
});
178+
179+
describe("Constructor", () => {
180+
it("should create FareBigInt with bigint amount", () => {
181+
const fareBigInt = new FareBigInt(1000000000000000000n, fare);
182+
183+
expect(fareBigInt.amount).toBe(1000000000000000000n);
184+
185+
expect(fareBigInt.fare).toBe(fare);
186+
});
187+
});
188+
189+
describe("add", () => {
190+
it("should add two FareBigInts with same token", () => {
191+
const fareBigInt1 = new FareBigInt(10000000000000000000n, fare);
192+
const fareBigInt2 = new FareBigInt(5000000000000000000n, fare);
193+
194+
const result = fareBigInt1.add(fareBigInt2);
195+
196+
expect(result).toBeInstanceOf(FareBigInt);
197+
expect(result.amount).toBe(15000000000000000000n);
198+
expect(result.fare).toBe(fare);
199+
});
200+
201+
it("should throw AcpError when adding FareBigInts with different tokens", () => {
202+
const fare1 = new Fare("0xToken1" as Address, 18);
203+
const fare2 = new Fare("0xToken2" as Address, 18);
204+
const fareBigInt1 = new FareBigInt(10000000000000000000n, fare1);
205+
const fareBigInt2 = new FareBigInt(5000000000000000000n, fare2);
206+
207+
expect(() => fareBigInt1.add(fareBigInt2)).toThrow(AcpError);
208+
expect(() => fareBigInt1.add(fareBigInt2)).toThrow(
209+
"Token addresses do not match",
210+
);
211+
});
212+
213+
it("should add FareBigInt with FareAmount", () => {
214+
const fareBigInt = new FareBigInt(10000000000000000000n, fare);
215+
const fareAmount = new FareAmount(5, fare);
216+
const result = fareBigInt.add(fareAmount);
217+
218+
expect(result).toBeInstanceOf(FareBigInt);
219+
expect(result.amount).toBe(15000000000000000000n);
220+
});
221+
});
222+
});
223+
224+
describe("FareAmountBase Class", () => {
225+
describe("fromContractAddress", () => {
226+
it("should create FareAmount when amount is number", async () => {
227+
const mockAddress = "0xToken" as Address;
228+
const mockDecimals = 18;
229+
230+
const mockReadContract = jest.fn().mockResolvedValue(mockDecimals);
231+
(createPublicClient as jest.Mock).mockReturnValue({
232+
readContract: mockReadContract,
233+
});
234+
235+
const result = await FareAmountBase.fromContractAddress(
236+
100,
237+
mockAddress,
238+
mockBaseAcpConfig,
239+
);
240+
241+
expect(result).toBeInstanceOf(FareAmount);
242+
expect(result.amount).toBe(100000000000000000000n);
243+
});
244+
245+
it("should create FareBigInt when amount is bigint", async () => {
246+
const mockAddress = "0xToken" as Address;
247+
const mockDecimals = 18;
248+
249+
const mockReadContract = jest.fn().mockResolvedValue(mockDecimals);
250+
(createPublicClient as jest.Mock).mockReturnValue({
251+
readContract: mockReadContract,
252+
});
253+
254+
const result = await FareAmountBase.fromContractAddress(
255+
100000000000000000000n,
256+
mockAddress,
257+
mockBaseAcpConfig,
258+
);
259+
260+
expect(result).toBeInstanceOf(FareBigInt);
261+
expect(result.amount).toBe(100000000000000000000n);
262+
});
263+
264+
it("should use baseFare when address matches config", async () => {
265+
const result = await FareAmountBase.fromContractAddress(
266+
10,
267+
mockBaseAcpConfig.baseFare.contractAddress,
268+
mockBaseAcpConfig,
269+
);
270+
271+
expect(result.fare).toBe(mockBaseAcpConfig.baseFare);
272+
});
273+
});
274+
});
275+
276+
describe("Exported Constants", () => {
277+
it("should export wethFare with correct address and decimals", () => {
278+
expect(wethFare).toBeInstanceOf(Fare);
279+
expect(wethFare.contractAddress).toBe(
280+
"0x4200000000000000000000000000000000000006",
281+
);
282+
expect(wethFare.decimals).toBe(18);
283+
});
284+
285+
it("should export ethFare with correct address and decimals", () => {
286+
expect(ethFare).toBeInstanceOf(Fare);
287+
expect(ethFare.decimals).toBe(18);
288+
});
289+
});
290+
});

0 commit comments

Comments
 (0)