Skip to content

Commit

Permalink
Merge pull request #462 from danditomaso/feat/add-support-for-unit-te…
Browse files Browse the repository at this point in the history
…sting

feat: adding unit/ui testing support
  • Loading branch information
danditomaso authored Feb 26, 2025
2 parents 25cd448 + c39ef59 commit 3db2ede
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 11 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ jobs:
- name: Install Dependencies
run: bun install

- name: Run tests
run: bun run test:run

- name: Build Package
run: bun run build
3 changes: 3 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:

- name: Install Dependencies
run: bun install

- name: Run tests
run: bun run test:run

- name: Build Package
run: bun run build
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:

- name: Install Dependencies
run: bun install

- name: Run tests
run: bun run test:run

- name: Build Package
run: bun run build
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:

- name: Install Dependencies
run: bun install

- name: Run tests
run: bun run test:run

- name: Build Package
run: bun run build
Expand Down
113 changes: 104 additions & 9 deletions bun.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"check:fix": "pnpm check --write src/",
"format": "biome format --write src/",
"dev": "vite dev --open",
"test": "vitest",
"test:ui": "vitest --ui",
"test:run": "vitest run",
"preview": "vite preview",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ $(ls ./dist/output/)",
"postinstall": "npx simple-git-hooks"
Expand Down Expand Up @@ -74,6 +77,7 @@
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@tailwindcss/postcss": "^4.0.7",
"@testing-library/react": "^16.2.0",
"@types/chrome": "^0.0.304",
"@types/js-cookie": "^3.0.6",
"@types/node": "^22.13.4",
Expand All @@ -84,13 +88,15 @@
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"gzipper": "^8.2.0",
"happy-dom": "^17.1.4",
"postcss": "^8.5.1",
"simple-git-hooks": "^2.11.1",
"tailwind-merge": "^3.0.1",
"tailwindcss": "^4.0.7",
"tailwindcss-animate": "^1.0.7",
"tar": "^7.4.3",
"typescript": "^5.7.3",
"vite": "^6.1.1"
"vite": "^6.1.1",
"vitest": "^3.0.6"
}
}
64 changes: 64 additions & 0 deletions src/core/utils/debounce.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { debounce } from "./debounce";

describe("debounce", () => {
beforeEach(() => {
vi.useFakeTimers();
});

afterEach(() => {
vi.restoreAllMocks();
});

it("delays executing the callback until after wait time has elapsed", () => {
const mockCallback = vi.fn();
const debouncedFunction = debounce(mockCallback, 500);

debouncedFunction();
expect(mockCallback).not.toHaveBeenCalled();

vi.advanceTimersByTime(300);
expect(mockCallback).not.toHaveBeenCalled();

vi.advanceTimersByTime(200);
expect(mockCallback).toHaveBeenCalledTimes(1);
});

it("only executes the callback once if called multiple times within wait period", () => {
const mockCallback = vi.fn();
const debouncedFunction = debounce(mockCallback, 500);

debouncedFunction();
debouncedFunction();
debouncedFunction();

vi.advanceTimersByTime(500);
expect(mockCallback).toHaveBeenCalledTimes(1);
});

it("resets the timer when called again during wait period", () => {
const mockCallback = vi.fn();
const debouncedFunction = debounce(mockCallback, 500);

debouncedFunction();

vi.advanceTimersByTime(300);
debouncedFunction();

vi.advanceTimersByTime(300);
expect(mockCallback).not.toHaveBeenCalled();

vi.advanceTimersByTime(200);
expect(mockCallback).toHaveBeenCalledTimes(1);
});

it("passes arguments to the callback function", () => {
const mockCallback = vi.fn();
const debouncedFunction = debounce(mockCallback, 500);

debouncedFunction("test", 123);

vi.advanceTimersByTime(500);
expect(mockCallback).toHaveBeenCalledWith("test", 123);
});
});
70 changes: 70 additions & 0 deletions src/core/utils/ip.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { describe, expect, it } from "vitest";
import { convertIntToIpAddress, convertIpAddressToInt } from "./ip";

describe("IP Address Conversion Functions", () => {
describe("convertIntToIpAddress", () => {
it("converts 0 to 0.0.0.0", () => {
expect(convertIntToIpAddress(0)).toBe("0.0.0.0");
});

it("converts 16_777_343 to 127.0.0.1", () => {
expect(convertIntToIpAddress(16_777_343)).toBe("127.0.0.1");
});

it("converts 16_820_416 to 192.168.0.1", () => {
expect(convertIntToIpAddress(16_820_416)).toBe("192.168.0.1");
});

it("converts 4_294_967_295 to 255.255.255.255", () => {
expect(convertIntToIpAddress(4_294_967_295)).toBe("255.255.255.255");
});
});

describe("convertIpAddressToInt", () => {
it("converts 0.0.0.0 to 0", () => {
expect(convertIpAddressToInt("0.0.0.0")).toBe(0);
});

it("converts 127.0.0.1 to 16_777_343", () => {
expect(convertIpAddressToInt("127.0.0.1")).toBe(16_777_343);
});

it("converts 192.168.0.1 to 16_820_416", () => {
expect(convertIpAddressToInt("192.168.0.1")).toBe(16_820_416);
});

it("converts 255.255.255.255 to 4_294_967_295", () => {
expect(convertIpAddressToInt("255.255.255.255")).toBe(4_294_967_295);
});

it("handles non-standard formats", () => {
expect(convertIpAddressToInt("1.2.3.4")).toBe(67_305_985);
});

it("handles invalid IP addresses gracefully", () => {
expect(convertIpAddressToInt("300.1.2.3")).not.toBeNull();
expect(typeof convertIpAddressToInt("300.1.2.3")).toBe("number");
});
});

describe("bidirectional conversion", () => {
it("can convert back and forth", () => {
const testIps = [
"0.0.0.0",
"127.0.0.1",
"192.168.1.1",
"10.0.0.1",
"255.255.255.255",
];

for (const ip of testIps) {
const int = convertIpAddressToInt(ip);
expect(int).not.toBeNull();
if (int !== null) {
const convertedBack = convertIntToIpAddress(int);
expect(convertedBack).toBe(ip);
}
}
});
});
});
44 changes: 44 additions & 0 deletions src/core/utils/randId.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { randId } from "./randId";

describe("randId", () => {
beforeEach(() => {
vi.restoreAllMocks();
});

it("returns a number", () => {
const result = randId();
expect(typeof result).toBe("number");
});

it("returns an integer", () => {
const result = randId();
expect(Number.isInteger(result)).toBe(true);
});

it("uses Math.random to generate the number", () => {
const mockRandom = vi.spyOn(Math, "random").mockReturnValue(0.5);
const result = randId();

expect(mockRandom).toHaveBeenCalled();
expect(result).toBe(Math.floor(0.5 * 1e9));
});

it("returns a value between 0 and 1e9 (exclusive)", () => {
const result = randId();
expect(result).toBeGreaterThanOrEqual(0);
expect(result).toBeLessThan(1e9);
});

it("returns different values on subsequent calls", () => {
vi.spyOn(Math, "random").mockRestore();

const results = new Set();

for (let i = 0; i < 100; i++) {
results.add(randId());
}

expect(results.size).toBeGreaterThan(95);
});
});
12 changes: 12 additions & 0 deletions src/core/utils/test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { render } from "@testing-library/react";
import type { ReactElement } from "react";

function customRender(ui: ReactElement, options = {}) {
return render(ui, {
// wrapper: ({ children }) => <MapProvider>{children}</MapProvider>,
...options,
});
}

export * from "@testing-library/react";
export { customRender as render };
7 changes: 6 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react';
import { execSync } from 'node:child_process';
import path from 'path';
Expand Down Expand Up @@ -26,5 +26,10 @@ export default defineConfig({
},
server: {
port: 3000
},
test: {
environment: 'happy-dom',
globals: true,
include: ['**/*.{test,spec}.{ts,tsx}'],
}
});

0 comments on commit 3db2ede

Please sign in to comment.