From 89cf5931f462fe34f10056edb3c0f22b1f61a108 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 17:30:46 -0700 Subject: [PATCH 1/6] Rename TopBlocked to TopBlockedDomains Signed-off-by: Mcat12 --- .../{TopBlocked.tsx => TopBlockedDomains.tsx} | 24 +++++++++++-------- ...ed.test.tsx => TopBlockedDomains.test.tsx} | 6 ++--- src/types/api.d.ts | 2 +- src/util/__tests__/api.test.tsx | 8 +++---- src/util/api.tsx | 4 ++-- src/views/Dashboard.tsx | 4 ++-- 6 files changed, 26 insertions(+), 22 deletions(-) rename src/components/dashboard/{TopBlocked.tsx => TopBlockedDomains.tsx} (81%) rename src/components/dashboard/__tests__/{TopBlocked.test.tsx => TopBlockedDomains.test.tsx} (89%) diff --git a/src/components/dashboard/TopBlocked.tsx b/src/components/dashboard/TopBlockedDomains.tsx similarity index 81% rename from src/components/dashboard/TopBlocked.tsx rename to src/components/dashboard/TopBlockedDomains.tsx index 5e57c63..6e118f4 100644 --- a/src/components/dashboard/TopBlocked.tsx +++ b/src/components/dashboard/TopBlockedDomains.tsx @@ -15,7 +15,7 @@ import TopTable from "./TopTable"; import i18next from "i18next"; import { TimeRangeContext } from "../common/context/TimeRangeContext"; -export interface TopBlockedData { +export interface TopBlockedDomainsData { totalBlocked: number; topBlocked: Array; } @@ -26,7 +26,9 @@ export interface TopBlockedData { * @param data the API data * @returns {{totalBlocked: number, topBlocked: *}} the parsed data */ -export const transformData = (data: ApiTopBlocked): TopBlockedData => ({ +export const transformData = ( + data: ApiTopBlockedDomains +): TopBlockedDomainsData => ({ totalBlocked: data.blocked_queries, topBlocked: data.top_domains }); @@ -38,7 +40,7 @@ export const transformData = (data: ApiTopBlocked): TopBlockedData => ({ * @returns {function(*): any[]} a function to generate rows of top blocked */ export const generateRows = (t: i18next.TranslationFunction) => ( - data: TopBlockedData + data: TopBlockedDomainsData ) => { return data.topBlocked.map(item => { const percentage = (item.count / data.totalBlocked) * 100; @@ -66,11 +68,11 @@ export const generateRows = (t: i18next.TranslationFunction) => ( }); }; -const TopBlocked = ({ +const TopBlockedDomains = ({ apiCall, t, ...props -}: WithNamespaces & { apiCall: () => Promise }) => ( +}: WithNamespaces & { apiCall: () => Promise }) => ( ); -const TopBlockedContainer = (props: WithNamespaces) => ( +const TopBlockedDomainsContainer = (props: WithNamespaces) => ( {context => ( - context.range - ? api.getTopBlockedDb(context.range) - : api.getTopBlocked() + ? api.getTopBlockedDomainsDb(context.range) + : api.getTopBlockedDomains() } /> )} ); -export default withNamespaces(["common", "dashboard"])(TopBlockedContainer); +export default withNamespaces(["common", "dashboard"])( + TopBlockedDomainsContainer +); diff --git a/src/components/dashboard/__tests__/TopBlocked.test.tsx b/src/components/dashboard/__tests__/TopBlockedDomains.test.tsx similarity index 89% rename from src/components/dashboard/__tests__/TopBlocked.test.tsx rename to src/components/dashboard/__tests__/TopBlockedDomains.test.tsx index 107cd72..8d133ec 100644 --- a/src/components/dashboard/__tests__/TopBlocked.test.tsx +++ b/src/components/dashboard/__tests__/TopBlockedDomains.test.tsx @@ -3,15 +3,15 @@ * Network-wide ad blocking via your own hardware. * * Web Interface - * TopBlocked component test + * TopBlockedDomains component test * * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ import React from "react"; -import { generateRows, transformData } from "../TopBlocked"; +import { generateRows, transformData } from "../TopBlockedDomains"; -const fakeData: ApiTopBlocked = { +const fakeData: ApiTopBlockedDomains = { top_domains: [ { domain: "jaron.info", count: 54316 }, { domain: "candelario.info", count: 47470 }, diff --git a/src/types/api.d.ts b/src/types/api.d.ts index bf3959d..9126139 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -177,7 +177,7 @@ interface ApiTopDomainItem { count: number; } -interface ApiTopBlocked { +interface ApiTopBlockedDomains { top_domains: Array; blocked_queries: number; } diff --git a/src/util/__tests__/api.test.tsx b/src/util/__tests__/api.test.tsx index dafd93e..2e5b8bd 100644 --- a/src/util/__tests__/api.test.tsx +++ b/src/util/__tests__/api.test.tsx @@ -104,7 +104,7 @@ describe("ApiClient", () => { it("should call top blocked endpoint (top_domains?blocked=true)", async () => { config.fakeAPI = false; - await expect(api.getTopBlocked()).resolves.toEqual(getData); + await expect(api.getTopBlockedDomains()).resolves.toEqual(getData); expect(httpClient.get).toHaveBeenCalledWith( "stats/top_domains?blocked=true" ); @@ -112,7 +112,7 @@ describe("ApiClient", () => { it("should call top blocked endpoint (top_blocked)", async () => { config.fakeAPI = true; - await expect(api.getTopBlocked()).resolves.toEqual(getData); + await expect(api.getTopBlockedDomains()).resolves.toEqual(getData); expect(httpClient.get).toHaveBeenCalledWith("stats/top_blocked"); }); @@ -180,7 +180,7 @@ describe("ApiClient", () => { it("should call top blocked DB endpoint (top_domains?blocked=true) with time range", async () => { config.fakeAPI = false; - await expect(api.getTopBlockedDb(range)).resolves.toEqual(getData); + await expect(api.getTopBlockedDomainsDb(range)).resolves.toEqual(getData); expect(httpClient.get).toHaveBeenCalledWith( "stats/database/top_domains?blocked=true&" + rangeParams ); @@ -188,7 +188,7 @@ describe("ApiClient", () => { it("should call top blocked DB endpoint (top_blocked) with time range", async () => { config.fakeAPI = true; - await expect(api.getTopBlockedDb(range)).resolves.toEqual(getData); + await expect(api.getTopBlockedDomainsDb(range)).resolves.toEqual(getData); expect(httpClient.get).toHaveBeenCalledWith( "stats/database/top_blocked?" + rangeParams ); diff --git a/src/util/api.tsx b/src/util/api.tsx index ba95804..11e7ed7 100644 --- a/src/util/api.tsx +++ b/src/util/api.tsx @@ -97,7 +97,7 @@ export class ApiClient { ); }; - getTopBlocked(): Promise { + getTopBlockedDomains(): Promise { // The API uses a GET parameter to differentiate top domains from top // blocked, but the fake API is not able to handle GET parameters right now. const url = this.http.config.fakeAPI @@ -107,7 +107,7 @@ export class ApiClient { return this.http.get(url); } - getTopBlockedDb(range: TimeRange): Promise { + getTopBlockedDomainsDb(range: TimeRange): Promise { // The API uses a GET parameter to differentiate top domains from top // blocked, but the fake API is not able to handle GET parameters right now. const url = this.http.config.fakeAPI diff --git a/src/views/Dashboard.tsx b/src/views/Dashboard.tsx index fec0d0a..a775526 100644 --- a/src/views/Dashboard.tsx +++ b/src/views/Dashboard.tsx @@ -15,7 +15,7 @@ import ClientsGraph from "../components/dashboard/ClientsGraph"; import QueryTypesChart from "../components/dashboard/QueryTypesChart"; import UpstreamsChart from "../components/dashboard/UpstreamsChart"; import TopDomains from "../components/dashboard/TopDomains"; -import TopBlocked from "../components/dashboard/TopBlocked"; +import TopBlockedDomains from "../components/dashboard/TopBlockedDomains"; import TopClients from "../components/dashboard/TopClients"; import api from "../util/api"; import { TimeRangeSelectorContainer } from "../components/dashboard/TimeRangeSelector"; @@ -55,7 +55,7 @@ export default () => (
- +
From 6fd96e11c6ea3acec8e8e374d18d3325d897d953 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 18:16:05 -0700 Subject: [PATCH 2/6] Add TopBlockedClients component Signed-off-by: Mcat12 --- public/i18n/en/dashboard.json | 3 +- .../dashboard/TopBlockedClients.tsx | 107 ++++++++++++++++++ src/types/api.d.ts | 5 + src/util/__tests__/api.test.tsx | 30 +++++ src/util/api.tsx | 34 +++++- 5 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 src/components/dashboard/TopBlockedClients.tsx diff --git a/public/i18n/en/dashboard.json b/public/i18n/en/dashboard.json index 2338e49..fa7328d 100644 --- a/public/i18n/en/dashboard.json +++ b/public/i18n/en/dashboard.json @@ -19,5 +19,6 @@ "No Domains Found": "No Domains Found", "Queries Answered By Destination": "Queries Answered By Destination", "Queries Over {{range}}": "Queries Over {{range}}", - "Clients Over {{range}}": "Clients Over {{range}}" + "Clients Over {{range}}": "Clients Over {{range}}", + "Top Blocked Clients": "Top Blocked Clients" } \ No newline at end of file diff --git a/src/components/dashboard/TopBlockedClients.tsx b/src/components/dashboard/TopBlockedClients.tsx new file mode 100644 index 0000000..b9a4c11 --- /dev/null +++ b/src/components/dashboard/TopBlockedClients.tsx @@ -0,0 +1,107 @@ +/* Pi-hole: A black hole for Internet advertisements + * (c) 2019 Pi-hole, LLC (https://pi-hole.net) + * Network-wide ad blocking via your own hardware. + * + * Web Interface + * Top Clients component + * + * This file is copyright under the latest version of the EUPL. + * Please see LICENSE file for your rights under this license. */ + +import React, { ReactNode } from "react"; +import { WithNamespaces, withNamespaces } from "react-i18next"; +import api from "../../util/api"; +import TopTable from "./TopTable"; +import i18next from "i18next"; +import { TimeRangeContext } from "../common/context/TimeRangeContext"; + +export interface TopBlockedClientsData { + blockedQueries: number; + topClients: Array; +} + +/** + * Transform the API data into the form used in generateRows + * + * @param data The API data + * @returns The parsed data + */ +export const transformData = ( + data: ApiTopBlockedClients +): TopBlockedClientsData => ({ + blockedQueries: data.blocked_queries, + topClients: data.top_clients +}); + +/** + * Create a function to generate rows of top clients + * + * @param t The translation function + * @returns A function to generate rows of top clients + */ +export const generateRows = (t: i18next.TranslationFunction) => ( + data: TopBlockedClientsData +): Array => { + return data.topClients.map(item => { + const percentage = (item.count / data.blockedQueries) * 100; + + return ( + + {item.name !== "" ? item.name : item.ip} + {item.count.toLocaleString()} + +
+
+
+ + + ); + }); +}; + +const TopClients = ({ + apiCall, + t, + ...props +}: WithNamespaces & { apiCall: () => Promise }) => ( + data.topClients.length === 0} + apiCall={apiCall} + apiHandler={transformData} + generateRows={generateRows(t)} + /> +); + +const TopClientsContainer = (props: WithNamespaces) => ( + + {context => ( + + context.range + ? api.getTopBlockedClientsDb(context.range) + : api.getTopBlockedClients() + } + /> + )} + +); + +export default withNamespaces(["common", "dashboard"])(TopClientsContainer); diff --git a/src/types/api.d.ts b/src/types/api.d.ts index 9126139..bd1f2cb 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -192,6 +192,11 @@ interface ApiTopClients { total_queries: number; } +interface ApiTopBlockedClients { + top_clients: Array; + blocked_queries: number; +} + interface ApiClient { name: string; ip: string; diff --git a/src/util/__tests__/api.test.tsx b/src/util/__tests__/api.test.tsx index 2e5b8bd..cff6bd3 100644 --- a/src/util/__tests__/api.test.tsx +++ b/src/util/__tests__/api.test.tsx @@ -121,6 +121,20 @@ describe("ApiClient", () => { expect(httpClient.get).toHaveBeenCalledWith("stats/top_clients"); }); + it("should call top blocked clients endpoint (top_clients?blocked=true)", async () => { + config.fakeAPI = false; + await expect(api.getTopBlockedClients()).resolves.toEqual(getData); + expect(httpClient.get).toHaveBeenCalledWith( + "stats/top_clients?blocked=true" + ); + }); + + it("should call top blocked clients endpoint (top_blocked_clients)", async () => { + config.fakeAPI = true; + await expect(api.getTopBlockedClients()).resolves.toEqual(getData); + expect(httpClient.get).toHaveBeenCalledWith("stats/top_blocked_clients"); + }); + it("should call top history endpoint with params", async () => { const params = { test: "params" }; await expect(api.getHistory(params)).resolves.toEqual(getData); @@ -200,6 +214,22 @@ describe("ApiClient", () => { "stats/database/top_clients?" + rangeParams ); }); + + it("should call top blocked clients DB endpoint (top_clients?blocked=true) with time range", async () => { + config.fakeAPI = false; + await expect(api.getTopBlockedClientsDb(range)).resolves.toEqual(getData); + expect(httpClient.get).toHaveBeenCalledWith( + "stats/database/top_clients?blocked=true&" + rangeParams + ); + }); + + it("should call top blocked clients DB endpoint (top_blocked_clients) with time range", async () => { + config.fakeAPI = true; + await expect(api.getTopBlockedClientsDb(range)).resolves.toEqual(getData); + expect(httpClient.get).toHaveBeenCalledWith( + "stats/database/top_blocked_clients?" + rangeParams + ); + }); }); describe("dns calls", () => { diff --git a/src/util/api.tsx b/src/util/api.tsx index 11e7ed7..0a20452 100644 --- a/src/util/api.tsx +++ b/src/util/api.tsx @@ -97,7 +97,7 @@ export class ApiClient { ); }; - getTopBlockedDomains(): Promise { + getTopBlockedDomains = (): Promise => { // The API uses a GET parameter to differentiate top domains from top // blocked, but the fake API is not able to handle GET parameters right now. const url = this.http.config.fakeAPI @@ -105,9 +105,11 @@ export class ApiClient { : "stats/top_domains?blocked=true"; return this.http.get(url); - } + }; - getTopBlockedDomainsDb(range: TimeRange): Promise { + getTopBlockedDomainsDb = ( + range: TimeRange + ): Promise => { // The API uses a GET parameter to differentiate top domains from top // blocked, but the fake API is not able to handle GET parameters right now. const url = this.http.config.fakeAPI @@ -115,7 +117,7 @@ export class ApiClient { : "stats/database/top_domains?blocked=true&"; return this.http.get(url + timeRangeToParams(range)); - } + }; getTopClients = (): Promise => { return this.http.get("stats/top_clients"); @@ -127,6 +129,30 @@ export class ApiClient { ); }; + getTopBlockedClients = (): Promise => { + // The API uses a GET parameter to differentiate top clients from top + // blocked clients, but the fake API is not able to handle GET parameters + // right now. + const url = this.http.config.fakeAPI + ? "stats/top_blocked_clients" + : "stats/top_clients?blocked=true"; + + return this.http.get(url); + }; + + getTopBlockedClientsDb = ( + range: TimeRange + ): Promise => { + // The API uses a GET parameter to differentiate top clients from top + // blocked clients, but the fake API is not able to handle GET parameters + // right now. + const url = this.http.config.fakeAPI + ? "stats/database/top_blocked_clients?" + : "stats/database/top_clients?blocked=true&"; + + return this.http.get(url + timeRangeToParams(range)); + }; + getHistory = (params: any): Promise => { return this.http.get("stats/history?" + paramsToString(params)); }; From 113eddd2e37b214279d681b3e189a4fd1e35ea92 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 18:16:36 -0700 Subject: [PATCH 3/6] Add top blocked client fake data Signed-off-by: Mcat12 --- scripts/make-fake-data.js | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/scripts/make-fake-data.js b/scripts/make-fake-data.js index 30d0514..c18a0a5 100644 --- a/scripts/make-fake-data.js +++ b/scripts/make-fake-data.js @@ -156,10 +156,10 @@ function upstreams(length) { }; } -function topList(length, max, fakeData) { +function topDomainList(length, max) { const result = []; const numbers = []; - const domains = unique(fakeData, length); + const domains = unique(faker.internet.domainName, length); for (let i = 0; i < length; i++) numbers.push(faker.random.number({ max: max })); @@ -176,11 +176,11 @@ function topList(length, max, fakeData) { return result; } -function topBlocked(length) { +function topBlockedDomains(length) { const totalQueries = faker.random.number(); return { - top_domains: topList(length, totalQueries, faker.internet.domainName), + top_domains: topDomainList(length, totalQueries), blocked_queries: totalQueries }; } @@ -189,13 +189,12 @@ function topDomains(length) { const totalQueries = faker.random.number(); return { - top_domains: topList(length, totalQueries, faker.internet.domainName), + top_domains: topDomainList(length, totalQueries), total_queries: totalQueries }; } -function topClients(length) { - const totalQueries = faker.random.number(); +function topClientList(length, totalQueries) { const top_clients = []; const numbers = []; const clients = unique(faker.internet.ip, length); @@ -213,12 +212,27 @@ function topClients(length) { }); } + return top_clients; +} + +function topClients(length) { + const totalQueries = faker.random.number(); + return { - top_clients: top_clients, + top_clients: topClientList(length, totalQueries), total_queries: totalQueries }; } +function topBlockedClients(length) { + const totalQueries = faker.random.number(); + + return { + top_clients: topClientList(length, totalQueries), + blocked_queries: totalQueries + }; +} + function clientsOverTime(range, size) { const startDate = pastDate(); const clients = unique(faker.internet.ip, size).map(ip => ({ @@ -402,17 +416,19 @@ write("public/fakeAPI/stats/summary", summary()); write("public/fakeAPI/stats/history", history(5000)); write("public/fakeAPI/stats/query_types", queryTypes()); write("public/fakeAPI/stats/upstreams", upstreams(3)); -write("public/fakeAPI/stats/top_blocked", topBlocked(10)); +write("public/fakeAPI/stats/top_blocked", topBlockedDomains(10)); write("public/fakeAPI/stats/top_domains", topDomains(10)); write("public/fakeAPI/stats/top_clients", topClients(10)); +write("public/fakeAPI/stats/top_blocked_clients", topBlockedClients(10)); write("public/fakeAPI/stats/database/overTime/history", historyOverTime(144)); write("public/fakeAPI/stats/database/overTime/clients", clientsOverTime(144, 5)); write("public/fakeAPI/stats/database/summary", summary()); write("public/fakeAPI/stats/database/query_types", queryTypes()); write("public/fakeAPI/stats/database/upstreams", upstreams(3)); -write("public/fakeAPI/stats/database/top_blocked", topBlocked(10)); +write("public/fakeAPI/stats/database/top_blocked", topBlockedDomains(10)); write("public/fakeAPI/stats/database/top_domains", topDomains(10)); write("public/fakeAPI/stats/database/top_clients", topClients(10)); +write("public/fakeAPI/stats/database/top_blocked_clients", topBlockedClients(10)); write("public/fakeAPI/auth", auth()); write("public/fakeAPI/version", getVersionInfo()); From 9ad526ae38757b07470dca4e7954515ef8885c83 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 18:18:38 -0700 Subject: [PATCH 4/6] Add TopBlockedClients to the dashboard and fix layout When the dashboard is not wide enough, the two-column layout becomes one column. Also, the top lists are now two rows of two columns instead of one row of three columns. Signed-off-by: Mcat12 --- src/views/Dashboard.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/views/Dashboard.tsx b/src/views/Dashboard.tsx index a775526..4bb6821 100644 --- a/src/views/Dashboard.tsx +++ b/src/views/Dashboard.tsx @@ -19,6 +19,7 @@ import TopBlockedDomains from "../components/dashboard/TopBlockedDomains"; import TopClients from "../components/dashboard/TopClients"; import api from "../util/api"; import { TimeRangeSelectorContainer } from "../components/dashboard/TimeRangeSelector"; +import TopBlockedClients from "../components/dashboard/TopBlockedClients"; export default () => (
@@ -43,23 +44,28 @@ export default () => (
-
+
-
+
-
+
-
+
-
+
+
+
+
+ +
) : null} From 70e4bb1f8542afc419b33482ea833324dfdd0857 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 18:19:08 -0700 Subject: [PATCH 5/6] Fix white bottom border on the header Signed-off-by: Mcat12 --- src/scss/_custom.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scss/_custom.scss b/src/scss/_custom.scss index 2d4e32d..0c90f45 100644 --- a/src/scss/_custom.scss +++ b/src/scss/_custom.scss @@ -154,6 +154,7 @@ .boxcontainer .app-header { max-width: 1250px; + border-bottom-color: #3c8dbc; } .card-icon { From e106624a58f6b891c5130246d81ccff7619e40e9 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 26 May 2019 20:47:05 -0700 Subject: [PATCH 6/6] Add tests and fix some top blocked clients naming Signed-off-by: Mcat12 --- .../dashboard/TopBlockedClients.tsx | 18 ++++---- .../__tests__/TopBlockedClients.test.tsx | 41 +++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 src/components/dashboard/__tests__/TopBlockedClients.test.tsx diff --git a/src/components/dashboard/TopBlockedClients.tsx b/src/components/dashboard/TopBlockedClients.tsx index b9a4c11..a879015 100644 --- a/src/components/dashboard/TopBlockedClients.tsx +++ b/src/components/dashboard/TopBlockedClients.tsx @@ -3,7 +3,7 @@ * Network-wide ad blocking via your own hardware. * * Web Interface - * Top Clients component + * Top Blocked Clients component * * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ @@ -34,14 +34,14 @@ export const transformData = ( }); /** - * Create a function to generate rows of top clients + * Generate rows of top blocked clients * * @param t The translation function - * @returns A function to generate rows of top clients + * @returns Rows of top blocked clients */ export const generateRows = (t: i18next.TranslationFunction) => ( data: TopBlockedClientsData -): Array => { +): ReactNode => { return data.topClients.map(item => { const percentage = (item.count / data.blockedQueries) * 100; @@ -68,7 +68,7 @@ export const generateRows = (t: i18next.TranslationFunction) => ( }); }; -const TopClients = ({ +const TopBlockedClients = ({ apiCall, t, ...props @@ -89,10 +89,10 @@ const TopClients = ({ /> ); -const TopClientsContainer = (props: WithNamespaces) => ( +const TopBlockedClientsContainer = (props: WithNamespaces) => ( {context => ( - context.range @@ -104,4 +104,6 @@ const TopClientsContainer = (props: WithNamespaces) => ( ); -export default withNamespaces(["common", "dashboard"])(TopClientsContainer); +export default withNamespaces(["common", "dashboard"])( + TopBlockedClientsContainer +); diff --git a/src/components/dashboard/__tests__/TopBlockedClients.test.tsx b/src/components/dashboard/__tests__/TopBlockedClients.test.tsx new file mode 100644 index 0000000..2e46c3d --- /dev/null +++ b/src/components/dashboard/__tests__/TopBlockedClients.test.tsx @@ -0,0 +1,41 @@ +/* Pi-hole: A black hole for Internet advertisements + * (c) 2019 Pi-hole, LLC (https://pi-hole.net) + * Network-wide ad blocking via your own hardware. + * + * Web Interface + * TopBlockedClients component test + * + * This file is copyright under the latest version of the EUPL. + * Please see LICENSE file for your rights under this license. */ + +import React from "react"; +import { generateRows, transformData } from "../TopBlockedClients"; + +const fakeData: ApiTopBlockedClients = { + top_clients: [ + { name: "", ip: "21.43.61.185", count: 37586 }, + { name: "", ip: "224.77.182.60", count: 28664 }, + { name: "", ip: "254.251.126.14", count: 28353 }, + { name: "", ip: "45.236.46.22", count: 26034 }, + { name: "", ip: "134.169.112.176", count: 23587 }, + { name: "", ip: "59.190.76.175", count: 14595 }, + { name: "", ip: "108.137.74.87", count: 11953 }, + { name: "", ip: "127.219.136.176", count: 11715 }, + { name: "", ip: "172.134.110.216", count: 5954 }, + { name: "", ip: "243.77.12.200", count: 4703 } + ], + blocked_queries: 38451 +}; + +it("transforms the API data correctly", async () => { + const data = transformData(fakeData); + + expect(data.blockedQueries).toEqual(fakeData.blocked_queries); + expect(data.topClients).toEqual(fakeData.top_clients); +}); + +it("creates an appropriately sized table", async () => { + const rows = generateRows(key => key)(transformData(fakeData)); + + expect(rows).toHaveLength(fakeData.top_clients.length); +});