Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,304 changes: 1,298 additions & 6 deletions frontend/package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"description": "",
"dependencies": {
"@rollup/plugin-inject": "^5.0.5",
"crypto-browserify": "^3.12.1",
"d3": "^7.9.0",
"flot": "^0.8.3",
"jquery": "^3.7.1",
Expand All @@ -31,17 +32,21 @@
"shiro-trie": "^0.4.10",
"simple-statistics": "^7.8.7",
"socket.io-client": "^4.8.1",
"stream-browserify": "^3.0.0",
"typescript": "^5.7.2",
"vite": "^5.4.11",
"vite-plugin-commonjs": "^0.10.4"
},
"devDependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@types/d3": "^7.4.3",
"@types/jquery": "^3.5.32",
"@types/jqueryui": "^1.12.23",
"@types/lodash": "^4.17.13",
"@types/moment": "^2.11.29",
"@types/moment-timezone": "^0.5.13",
"jsdom": "^25.0.1",
"prettier": "^3.4.1",
"vitest": "^2.1.8"
}
Expand Down
98 changes: 98 additions & 0 deletions frontend/tests/fixtures/ajax.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { vi } from "vitest";

export const ajaxMock = vi.fn();
export const mockState: Map<
RegExp | string,
{ data: any; error?: never } | { error: any; data?: never }
> = new Map();

type ValueOfMap<T> = T extends Map<any, infer G> ? G : never;

function mockImplementation(
opts: JQuery.AjaxSettings & { url: string }
): JQuery.jqXHR;
function mockImplementation(
maybeOpts: string,
opts?: JQuery.AjaxSettings
): JQuery.jqXHR;
function mockImplementation(
maybeOpts: (JQuery.AjaxSettings & { url: string }) | string,
opts?: JQuery.AjaxSettings
): JQuery.jqXHR {
const url = typeof maybeOpts === "string" ? maybeOpts : maybeOpts.url;
opts = typeof maybeOpts === "string" ? opts : maybeOpts;

const data = [...mockState.entries()].find(([matcher, data]) =>
url.match(matcher)
)?.[1];

if (!data) throw Error(`[mockAjax] route ${url} not handled`);
class AjaxReturnMock implements JQuery.jqXHR {
constructor(private data: ValueOfMap<typeof mockState>) {}

state() {
return "resolved" as "resolved";
}
done(callback: (d: any) => void) {
if (this.data.data) {
callback(this.data.data);
}
return this;
}
fail(callback: (d: any) => void) {
if (this.data.error) {
callback(this.data.error);
}
return this;
}
statusCode() {
return this.data.error ? 500 : 200;
}
get responseText() {
return this.data.error ? "error" : "OK";
}
abort() {}
always(callback: (d: any) => void) {
callback(this.data.data || this.data.error);
return this;
}
progress() {
return this;
}
promise() {
return this;
}
pipe() {
return this;
}
then() {
return this;
}
catch() {
return this;
}
getAllResponseHeaders() {
return "";
}
getResponseHeader() {
return "";
}
overrideMimeType() {
return "";
}
get readyState() {
return 1;
}
setRequestHeader() {
return this;
}
get status() {
return this.data.error ? 500 : 200;
}
get statusText() {
return this.data.error ? "error" : "OK";
}
}
return new AjaxReturnMock(data);
}
ajaxMock.mockImplementation(mockImplementation);
42 changes: 42 additions & 0 deletions frontend/tests/fixtures/socket.io-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export const callbacksByRouteByEvent = {
default: {} as Record<string, (...args: any) => void>,
"/alarm": {} as Record<string, (...args: any) => void>,
};
export const emitResponsesByRouteByEvent = {
default: {} as Record<string, any>,
"/alarm": {} as Record<string, any>,
};
export const sockerIOClientMock = {
connect: (
routeOrOpts: keyof typeof callbacksByRouteByEvent | Record<string, any>,
opts?: Record<string, any>
) => {
const route =
typeof routeOrOpts === "undefined" || typeof routeOrOpts === "object"
? "default"
: routeOrOpts;
switch (route) {
case "default":
return defaultSocket;
case "/alarm":
return alarmSocket;
}
},
};

const makeSocket = (route: keyof typeof callbacksByRouteByEvent) => ({
on(event: string, callback: (...args: any) => void) {
callbacksByRouteByEvent[route][event] = callback;
},
emit(event: string, data: any, callback: (...args: any[]) => void) {
callback(emitResponsesByRouteByEvent[route][event]);
},

trigger(event: string, ...args: any[]) {
const callback = callbacksByRouteByEvent[route][event];
if (callback) callback(...args);
},
});

export const defaultSocket = makeSocket("default");
export const alarmSocket = makeSocket("/alarm");
33 changes: 33 additions & 0 deletions frontend/tests/pluginbase.test.js
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @vitest-environment jsdom
*/

import { describe, expect, it } from "vitest";
import setupBrowser from "./setup/browser";

describe("pluginbase", () => {
it("updates major pill text correctly", async () => {
await setupBrowser();

const bgStatusBefore = document.querySelector(".bgStatus");
const minorPillsBefore = document.querySelector(".minorPills");

window.Nightscout.client.ctx.pluginBase.updatePillText(
{
name: "fake",
label: "Insulin-on-Board",
pluginType: "pill-major",
},
{
value: "123",
label: "TEST",
info: [{ label: "Label", value: "Value" }],
}
);

expect(document.querySelector(".majorPills")).toHaveTextContent("TEST123");

expect(document.querySelector(".minorPills")).toBe(minorPillsBefore);
expect(document.querySelector(".bgStatus")).toBe(bgStatusBefore);
});
});
Loading