From 565260ee1460aada4e1f87ec0d9df2f814c73fd8 Mon Sep 17 00:00:00 2001 From: Tagaishi Date: Sat, 2 Sep 2023 06:58:16 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Update=20vitest=20test=20for=20Piho?= =?UTF-8?q?le=20as=20sdk=20changed=20(#1352)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✅ Update vitest test for Pihole as sdk changed * ✅ Added test + bug discovered related to it --- src/tools/server/sdk/pihole/piHole.spec.ts | 142 ++++++++++++++++++++- src/tools/server/sdk/pihole/piHole.ts | 2 +- 2 files changed, 139 insertions(+), 5 deletions(-) diff --git a/src/tools/server/sdk/pihole/piHole.spec.ts b/src/tools/server/sdk/pihole/piHole.spec.ts index 4df9964c9..3828c9d38 100644 --- a/src/tools/server/sdk/pihole/piHole.spec.ts +++ b/src/tools/server/sdk/pihole/piHole.spec.ts @@ -161,6 +161,7 @@ describe('PiHole API client', () => { const warningLogSpy = vi.spyOn(Consola, 'warn'); let calledCount = 0; + let countTriedRequests = 0; fetchMock.mockResponse((request) => { if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') { @@ -170,6 +171,13 @@ describe('PiHole API client', () => { }); } + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){ + countTriedRequests += 1; + return JSON.stringify({ + status: 'enabled', + }); + } + return Promise.reject(new Error(`Bad url: ${request.url}`)); }); @@ -181,6 +189,7 @@ describe('PiHole API client', () => { // Assert expect(summary).toBe(true); expect(calledCount).toBe(1); + expect(countTriedRequests).toBe(1); expect(errorLogSpy).not.toHaveBeenCalled(); expect(warningLogSpy).not.toHaveBeenCalled(); @@ -188,12 +197,13 @@ describe('PiHole API client', () => { errorLogSpy.mockRestore(); }); - it('enable - return false when state change is not as expected', async () => { + it('enable - return true when state change is as expected after 10 retries', async () => { // arrange const errorLogSpy = vi.spyOn(Consola, 'error'); const warningLogSpy = vi.spyOn(Consola, 'warn'); let calledCount = 0; + let countTriedRequests = 0; fetchMock.mockResponse((request) => { if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') { @@ -203,6 +213,19 @@ describe('PiHole API client', () => { }); } + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){ + countTriedRequests += 1; + if(countTriedRequests < 10) { + return JSON.stringify({ + status: 'disabled', + }); + } + + return JSON.stringify({ + status: 'enabled', + }); + } + return Promise.reject(new Error(`Bad url: ${request.url}`)); }); @@ -212,8 +235,9 @@ describe('PiHole API client', () => { const summary = await client.enable(); // Assert - expect(summary).toBe(false); + expect(summary).toBe(true); expect(calledCount).toBe(1); + expect(countTriedRequests).toBe(10); expect(errorLogSpy).not.toHaveBeenCalled(); expect(warningLogSpy).not.toHaveBeenCalled(); @@ -227,6 +251,7 @@ describe('PiHole API client', () => { const warningLogSpy = vi.spyOn(Consola, 'warn'); let calledCount = 0; + let countTriedRequests = 0; fetchMock.mockResponse((request) => { if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') { @@ -236,6 +261,13 @@ describe('PiHole API client', () => { }); } + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){ + countTriedRequests += 1; + return JSON.stringify({ + status: 'disabled', + }); + } + return Promise.reject(new Error(`Bad url: ${request.url}`)); }); @@ -247,6 +279,7 @@ describe('PiHole API client', () => { // Assert expect(summary).toBe(true); expect(calledCount).toBe(1); + expect(countTriedRequests).toBe(1); expect(errorLogSpy).not.toHaveBeenCalled(); expect(warningLogSpy).not.toHaveBeenCalled(); @@ -254,12 +287,13 @@ describe('PiHole API client', () => { errorLogSpy.mockRestore(); }); - it('disable - return false when state change is not as expected', async () => { + it('disable - return true when state change is as expected after 10 retries', async () => { // arrange const errorLogSpy = vi.spyOn(Consola, 'error'); const warningLogSpy = vi.spyOn(Consola, 'warn'); let calledCount = 0; + let countTriedRequests = 0; fetchMock.mockResponse((request) => { if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') { @@ -269,6 +303,19 @@ describe('PiHole API client', () => { }); } + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){ + countTriedRequests += 1; + if(countTriedRequests < 10) { + return JSON.stringify({ + status: 'enabled', + }); + } + + return JSON.stringify({ + status: 'disabled', + }); + } + return Promise.reject(new Error(`Bad url: ${request.url}`)); }); @@ -278,8 +325,95 @@ describe('PiHole API client', () => { const summary = await client.disable(); // Assert - expect(summary).toBe(false); + expect(summary).toBe(true); expect(calledCount).toBe(1); + expect(countTriedRequests).toBe(10); + + expect(errorLogSpy).not.toHaveBeenCalled(); + expect(warningLogSpy).not.toHaveBeenCalled(); + + errorLogSpy.mockRestore(); + }); + + it('enable - throw error when state change is not as expected', async () => { + // arrange + const errorLogSpy = vi.spyOn(Consola, 'error'); + const warningLogSpy = vi.spyOn(Consola, 'warn'); + + let calledCount = 0; + let countTriedRequests = 0; + + fetchMock.mockResponse((request) => { + if (request.url === 'http://pi.hole/admin/api.php?enable&auth=nice') { + calledCount += 1; + return JSON.stringify({ + status: 'disabled', + }); + } + + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice'){ + countTriedRequests += 1; + return JSON.stringify({ + status: 'disabled', + }); + } + + return Promise.reject(new Error(`Bad url: ${request.url}`)); + }); + + const client = new PiHoleClient('http://pi.hole', 'nice'); + + // Act & Assert + await expect(() => client.enable()).rejects.toThrowErrorMatchingInlineSnapshot( + '"Although PiHole received the command, it failed to update it\'s status: [object Object]"' + ); + + // Assert + expect(calledCount).toBe(1); + expect(countTriedRequests).toBe(10); + + expect(errorLogSpy).not.toHaveBeenCalled(); + expect(warningLogSpy).not.toHaveBeenCalled(); + + errorLogSpy.mockRestore(); + }); + + it('disable - throw error when state change is not as expected', async () => { + // arrange + const errorLogSpy = vi.spyOn(Consola, 'error'); + const warningLogSpy = vi.spyOn(Consola, 'warn'); + + let calledCount = 0; + let countTriedRequests = 0; + + fetchMock.mockResponse((request) => { + if (request.url === 'http://pi.hole/admin/api.php?disable&auth=nice') { + calledCount += 1; + return JSON.stringify({ + status: 'enabled', + }); + } + + if (request.url === 'http://pi.hole/admin/api.php?summaryRaw&auth=nice') { + countTriedRequests += 1; + return JSON.stringify({ + status: 'enabled', + }); + } + + return Promise.reject(new Error(`Bad url: ${request.url}`)); + }); + + const client = new PiHoleClient('http://pi.hole', 'nice'); + + // Act & Assert + await expect(() => client.disable()).rejects.toThrowErrorMatchingInlineSnapshot( + '"Although PiHole received the command, it failed to update it\'s status: [object Object]"' + ); + + // Assert + expect(calledCount).toBe(1); + expect(countTriedRequests).lessThanOrEqual(10); expect(errorLogSpy).not.toHaveBeenCalled(); expect(warningLogSpy).not.toHaveBeenCalled(); diff --git a/src/tools/server/sdk/pihole/piHole.ts b/src/tools/server/sdk/pihole/piHole.ts index fcd22b605..b7772a60a 100644 --- a/src/tools/server/sdk/pihole/piHole.ts +++ b/src/tools/server/sdk/pihole/piHole.ts @@ -65,7 +65,7 @@ export class PiHoleClient { for(let loops = 0; loops < 10; loops++){ const summary = await this.getSummary() if (summary.status === action + 'd'){ - return json as PiHoleApiStatusChangeResponse; + return { status: summary.status } as PiHoleApiStatusChangeResponse; } await new Promise ((resolve) => { setTimeout(resolve, 50)}); }