Skip to content

Commit 2682917

Browse files
committed
fix: ensure that getDispute() includes the answer ID 0
1 parent 1de725b commit 2682917

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

kleros-sdk/src/utils/getDispute.ts

+13
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,18 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi
5656

5757
const populatedTemplate = populateTemplate(templateData, data);
5858

59+
// Ensure Refuse to Arbitrate option exists
60+
if (!populatedTemplate.answers?.some((answer) => answer.id && Number(answer.id) === 0)) {
61+
populatedTemplate.answers = [
62+
{
63+
id: "0x0",
64+
title: "Refuse to Arbitrate / Invalid",
65+
description: "Refuse to Arbitrate / Invalid",
66+
reserved: true,
67+
},
68+
...(populatedTemplate.answers || []),
69+
];
70+
}
71+
5972
return populatedTemplate;
6073
};

kleros-sdk/test/getDispute.test.ts

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
2+
import { getDispute } from "../src/utils/getDispute";
3+
import fetchDisputeDetails from "../src/requests/fetchDisputeDetails";
4+
import fetchDisputeTemplateFromId from "../src/requests/fetchDisputeTemplateFromId";
5+
6+
// Mock the dependencies
7+
vi.mock("../src/requests/fetchDisputeDetails");
8+
vi.mock("../src/requests/fetchDisputeTemplateFromId");
9+
10+
describe("getDispute", () => {
11+
const mockDisputeId = 123n;
12+
const mockCoreSubgraph = "https://api.thegraph.com/subgraphs/name/kleros/core";
13+
const mockDtrSubgraph = "https://api.thegraph.com/subgraphs/name/kleros/dtr";
14+
15+
const mockDisputeDetails = {
16+
dispute: {
17+
templateId: 1,
18+
arbitrated: { id: "0x1234" },
19+
arbitrableChainId: 1,
20+
externalDisputeId: 123,
21+
},
22+
};
23+
24+
beforeEach(() => {
25+
vi.resetAllMocks();
26+
});
27+
28+
it("should add Refuse to Arbitrate option when answers array is empty", async () => {
29+
const mockTemplate = {
30+
disputeTemplate: {
31+
templateData: JSON.stringify({
32+
title: "Test Dispute",
33+
description: "Test Description",
34+
question: "Test Question",
35+
answers: [],
36+
policyURI: "/ipfs/test",
37+
arbitratorChainID: "1",
38+
arbitratorAddress: "0x1234567890123456789012345678901234567890",
39+
version: "1.0.0",
40+
}),
41+
templateDataMappings: "",
42+
},
43+
};
44+
45+
vi.mocked(fetchDisputeDetails).mockResolvedValue(mockDisputeDetails);
46+
vi.mocked(fetchDisputeTemplateFromId).mockResolvedValue(mockTemplate);
47+
48+
const result = await getDispute({
49+
disputeId: mockDisputeId,
50+
coreSubgraph: mockCoreSubgraph,
51+
dtrSubgraph: mockDtrSubgraph,
52+
});
53+
54+
expect(result?.answers).toHaveLength(1);
55+
expect(result?.answers[0]).toEqual({
56+
id: "0x0",
57+
title: "Refuse to Arbitrate / Invalid",
58+
description: "Refuse to Arbitrate / Invalid",
59+
reserved: true,
60+
});
61+
});
62+
63+
it("should add Refuse to Arbitrate option when it doesn't exist in answers", async () => {
64+
const mockTemplate = {
65+
disputeTemplate: {
66+
templateData: JSON.stringify({
67+
title: "Test Dispute",
68+
description: "Test Description",
69+
question: "Test Question",
70+
answers: [
71+
{
72+
id: "0x1",
73+
title: "Yes",
74+
description: "Yes Description",
75+
},
76+
{
77+
id: "0x2",
78+
title: "No",
79+
description: "No Description",
80+
},
81+
],
82+
policyURI: "/ipfs/test",
83+
arbitratorChainID: "1",
84+
arbitratorAddress: "0x1234567890123456789012345678901234567890",
85+
version: "1.0.0",
86+
}),
87+
templateDataMappings: "",
88+
},
89+
};
90+
91+
vi.mocked(fetchDisputeDetails).mockResolvedValue(mockDisputeDetails);
92+
vi.mocked(fetchDisputeTemplateFromId).mockResolvedValue(mockTemplate);
93+
94+
const result = await getDispute({
95+
disputeId: mockDisputeId,
96+
coreSubgraph: mockCoreSubgraph,
97+
dtrSubgraph: mockDtrSubgraph,
98+
});
99+
100+
expect(result?.answers).toHaveLength(3);
101+
expect(result?.answers[0]).toEqual({
102+
id: "0x0",
103+
title: "Refuse to Arbitrate / Invalid",
104+
description: "Refuse to Arbitrate / Invalid",
105+
reserved: true,
106+
});
107+
expect(result?.answers[1].id).toBe("0x1");
108+
expect(result?.answers[2].id).toBe("0x2");
109+
});
110+
111+
it("should not add Refuse to Arbitrate option when it already exists with id 0x0", async () => {
112+
const mockTemplate = {
113+
disputeTemplate: {
114+
templateData: JSON.stringify({
115+
title: "Test Dispute",
116+
description: "Test Description",
117+
question: "Test Question",
118+
answers: [
119+
{
120+
id: "0x0",
121+
title: "Refuse to Arbitrate / Invalid",
122+
description: "Refuse to Arbitrate / Invalid",
123+
reserved: true,
124+
},
125+
{
126+
id: "0x1",
127+
title: "Yes",
128+
description: "Yes Description",
129+
},
130+
],
131+
policyURI: "/ipfs/test",
132+
arbitratorChainID: "1",
133+
arbitratorAddress: "0x1234567890123456789012345678901234567890",
134+
version: "1.0.0",
135+
}),
136+
templateDataMappings: "",
137+
},
138+
};
139+
140+
vi.mocked(fetchDisputeDetails).mockResolvedValue(mockDisputeDetails);
141+
vi.mocked(fetchDisputeTemplateFromId).mockResolvedValue(mockTemplate);
142+
143+
const result = await getDispute({
144+
disputeId: mockDisputeId,
145+
coreSubgraph: mockCoreSubgraph,
146+
dtrSubgraph: mockDtrSubgraph,
147+
});
148+
149+
expect(result?.answers).toHaveLength(2);
150+
expect(result?.answers[0].id).toBe("0x0");
151+
expect(result?.answers[1].id).toBe("0x1");
152+
});
153+
154+
it("should not add Refuse to Arbitrate option when it already exists with id 0x00", async () => {
155+
const mockTemplate = {
156+
disputeTemplate: {
157+
templateData: JSON.stringify({
158+
title: "Test Dispute",
159+
description: "Test Description",
160+
question: "Test Question",
161+
answers: [
162+
{
163+
id: "0x00",
164+
title: "Custom Refuse Title",
165+
description: "Custom Refuse Description",
166+
reserved: true,
167+
},
168+
{
169+
id: "0x1",
170+
title: "Yes",
171+
description: "Yes Description",
172+
},
173+
],
174+
policyURI: "/ipfs/test",
175+
arbitratorChainID: "1",
176+
arbitratorAddress: "0x1234567890123456789012345678901234567890",
177+
version: "1.0.0",
178+
}),
179+
templateDataMappings: "",
180+
},
181+
};
182+
183+
vi.mocked(fetchDisputeDetails).mockResolvedValue(mockDisputeDetails);
184+
vi.mocked(fetchDisputeTemplateFromId).mockResolvedValue(mockTemplate);
185+
186+
const result = await getDispute({
187+
disputeId: mockDisputeId,
188+
coreSubgraph: mockCoreSubgraph,
189+
dtrSubgraph: mockDtrSubgraph,
190+
});
191+
192+
expect(result?.answers).toHaveLength(2);
193+
expect(result?.answers[0].id).toBe("0x00");
194+
expect(result?.answers[0].title).toBe("Custom Refuse Title");
195+
expect(result?.answers[1].id).toBe("0x1");
196+
});
197+
198+
it("should throw NotFoundError when dispute details are not found", async () => {
199+
vi.mocked(fetchDisputeDetails).mockResolvedValue({ dispute: null } as any);
200+
201+
await expect(
202+
getDispute({
203+
disputeId: mockDisputeId,
204+
coreSubgraph: mockCoreSubgraph,
205+
dtrSubgraph: mockDtrSubgraph,
206+
})
207+
).rejects.toThrow("Dispute details not found");
208+
});
209+
210+
it("should throw NotFoundError when template is not found", async () => {
211+
vi.mocked(fetchDisputeDetails).mockResolvedValue(mockDisputeDetails);
212+
vi.mocked(fetchDisputeTemplateFromId).mockResolvedValue(undefined);
213+
214+
await expect(
215+
getDispute({
216+
disputeId: mockDisputeId,
217+
coreSubgraph: mockCoreSubgraph,
218+
dtrSubgraph: mockDtrSubgraph,
219+
})
220+
).rejects.toThrow("Template not found");
221+
});
222+
});

0 commit comments

Comments
 (0)