{contract.isFetching
? "fetching..."
: contract.sending
@@ -22,7 +23,11 @@
-
+
{contract.number}² = {contract.square(contract.number)}
+
+
diff --git a/src/routes/notification/+page.svelte b/src/routes/notification/+page.svelte
new file mode 100644
index 0000000..8a7307a
--- /dev/null
+++ b/src/routes/notification/+page.svelte
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/tests/e2e/demo.t.ts b/tests/e2e/demo.t.ts
index 5b1b7c8..7524261 100644
--- a/tests/e2e/demo.t.ts
+++ b/tests/e2e/demo.t.ts
@@ -40,9 +40,9 @@ test("connect button should be visible and clickable", async ({ page }) => {
await expect(disconnectButton).toBeVisible();
});
-test('disconnect wallet functionality', async ({ page }) => {
+test("disconnect wallet functionality", async ({ page }) => {
// Navigate to the home page
- await page.goto('/');
+ await page.goto("/");
// Find and click the connect button
const connectButton = page.locator("#connect-wallet");
diff --git a/tests/e2e/notification.t.ts b/tests/e2e/notification.t.ts
new file mode 100644
index 0000000..bb599bb
--- /dev/null
+++ b/tests/e2e/notification.t.ts
@@ -0,0 +1,53 @@
+import { expect, test } from "@playwright/test";
+
+test.describe("Notification Page", () => {
+ test.beforeEach(async ({ page }) => {
+ // Navigate to the notification page before each test
+ await page.goto("/notification");
+ });
+
+ test("should display notification when clicking the button", async ({ page }) => {
+ // Find and click the notification button
+ const notifButton = page.getByRole("button", { name: "Notif" });
+ await expect(notifButton).toBeVisible();
+ await notifButton.click();
+
+ // Wait for and verify the notification appears
+ const notification = page.getByText("Notification!");
+ await expect(notification).toBeVisible();
+
+ // Verify the notification has the correct styles (info type)
+ const notificationContainer = page.locator('[role="status"].notification-info');
+ await expect(notificationContainer).toBeVisible();
+ await expect(notificationContainer).toHaveClass(/top-0/);
+
+ // Wait for notification to disappear (default timeout is 3000ms)
+ await expect(notification).toBeHidden({ timeout: 5000 });
+ });
+
+ test("notification should have correct position", async ({ page }) => {
+ // Click the notification button
+ await page.getByRole("button", { name: "Notif" }).click();
+
+ // Get the notification container
+ const notificationContainer = page.locator('[role="status"].notification-info');
+
+ // Verify it appears at the top-center (default position)
+ await expect(notificationContainer).toHaveClass(/top-0/);
+ });
+
+ test("should handle multiple notifications", async ({ page }) => {
+ // Click the button multiple times
+ const button = page.getByRole("button", { name: "Notif" });
+ await button.click();
+ await button.click();
+ await button.click();
+
+ // Verify multiple notifications are visible
+ const notifications = page.locator('[role="status"].notification-info');
+ await expect(notifications).toHaveCount(3);
+
+ // Wait for all notifications to disappear
+ await expect(notifications).toHaveCount(0, { timeout: 5000 });
+ });
+});
diff --git a/tests/unit/mocks/env/static/public.ts b/tests/unit/mocks/env/static/public.ts
index 59db6f3..e43924e 100644
--- a/tests/unit/mocks/env/static/public.ts
+++ b/tests/unit/mocks/env/static/public.ts
@@ -1,6 +1,6 @@
-export const PUBLIC_CHAINS = 'anvil,baseSepolia'
-export const PUBLIC_POLLING_INTERVAL = '5000'
-export const PUBLIC_ALCHEMY_API_KEY = 'test-key'
-export const PUBLIC_WALLET_CONNECT_PROJECT_ID = 'test-project-id'
-export const PUBLIC_BURNER_WALLET_ONLY_LOCAL = 'true'
-export const PUBLIC_BURNER_WALLET_KEY = 'test-key'
+export const PUBLIC_CHAINS = "anvil,baseSepolia";
+export const PUBLIC_POLLING_INTERVAL = "5000";
+export const PUBLIC_ALCHEMY_API_KEY = "test-key";
+export const PUBLIC_WALLET_CONNECT_PROJECT_ID = "test-project-id";
+export const PUBLIC_BURNER_WALLET_ONLY_LOCAL = "true";
+export const PUBLIC_BURNER_WALLET_KEY = "test-key";
diff --git a/tests/unit/setup.ts b/tests/unit/setup.ts
index a903888..44170bd 100644
--- a/tests/unit/setup.ts
+++ b/tests/unit/setup.ts
@@ -1,34 +1,34 @@
-import { vi } from 'vitest'
-import { Window } from 'happy-dom'
+import { vi } from "vitest";
+import { Window } from "happy-dom";
// Setup global environment
-Object.defineProperty(globalThis, 'window', { value: new Window() })
+Object.defineProperty(globalThis, "window", { value: new Window() });
// Mock deployments JSON if not already defined
-if (!('__DEPLOYMENTS_JSON__' in globalThis)) {
- Object.defineProperty(globalThis, '__DEPLOYMENTS_JSON__', {
+if (!("__DEPLOYMENTS_JSON__" in globalThis)) {
+ Object.defineProperty(globalThis, "__DEPLOYMENTS_JSON__", {
value: {
- '31337': {
- name: 'Anvil',
- chainId: '31337',
+ "31337": {
+ name: "Anvil",
+ chainId: "31337",
contracts: {}
},
- '84532': {
- name: 'Base Sepolia',
- chainId: '84532',
+ "84532": {
+ name: "Base Sepolia",
+ chainId: "84532",
contracts: {}
}
},
configurable: true
- })
+ });
}
// Mock SvelteKit's $env/static/public module
-vi.mock('$env/static/public', () => ({
- PUBLIC_CHAINS: 'anvil,baseSepolia',
- PUBLIC_POLLING_INTERVAL: '5000',
- PUBLIC_ALCHEMY_API_KEY: 'test-key',
- PUBLIC_WALLET_CONNECT_PROJECT_ID: 'test-project-id',
- PUBLIC_BURNER_WALLET_ONLY_LOCAL: 'true',
- PUBLIC_BURNER_WALLET_KEY: 'test-key'
-}))
+vi.mock("$env/static/public", () => ({
+ PUBLIC_CHAINS: "anvil,baseSepolia",
+ PUBLIC_POLLING_INTERVAL: "5000",
+ PUBLIC_ALCHEMY_API_KEY: "test-key",
+ PUBLIC_WALLET_CONNECT_PROJECT_ID: "test-project-id",
+ PUBLIC_BURNER_WALLET_ONLY_LOCAL: "true",
+ PUBLIC_BURNER_WALLET_KEY: "test-key"
+}));
diff --git a/tests/unit/utils.t.ts b/tests/unit/utils.t.ts
index d388e9a..bd90f2e 100644
--- a/tests/unit/utils.t.ts
+++ b/tests/unit/utils.t.ts
@@ -1,79 +1,86 @@
-import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
-import { isEns, isAddress, shorten0xString, replacer, saveBurnerSK, loadBurnerSK } from '../../src/lib/wagmi/ts/utils';
-import { type Address } from 'viem';
+import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
+import {
+ isEns,
+ isAddress,
+ shorten0xString,
+ replacer,
+ saveBurnerSK,
+ loadBurnerSK
+} from "../../src/lib/wagmi/ts/utils";
+import { type Address } from "viem";
declare const global: typeof globalThis;
-describe('Address and ENS utilities', () => {
- describe('isEns', () => {
- it('should return false for null or undefined', () => {
+describe("Address and ENS utilities", () => {
+ describe("isEns", () => {
+ it("should return false for null or undefined", () => {
expect(isEns(null)).toBe(false);
expect(isEns(undefined)).toBe(false);
});
- it('should return true for valid .eth addresses', () => {
- expect(isEns('vitalik.eth')).toBe(true);
- expect(isEns('test-name.eth')).toBe(true);
+ it("should return true for valid .eth addresses", () => {
+ expect(isEns("vitalik.eth")).toBe(true);
+ expect(isEns("test-name.eth")).toBe(true);
});
- it('should return false for non-.eth addresses', () => {
- expect(isEns('vitalik')).toBe(false);
- expect(isEns('test.com')).toBe(false);
+ it("should return false for non-.eth addresses", () => {
+ expect(isEns("vitalik")).toBe(false);
+ expect(isEns("test.com")).toBe(false);
});
});
- describe('isAddress', () => {
- it('should return false for null or undefined', () => {
+ describe("isAddress", () => {
+ it("should return false for null or undefined", () => {
expect(isAddress(null)).toBe(false);
expect(isAddress(undefined)).toBe(false);
});
- it('should return true for valid Ethereum addresses', () => {
- const validAddress = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e' as Address;
+ it("should return true for valid Ethereum addresses", () => {
+ const validAddress = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" as Address;
expect(isAddress(validAddress)).toBe(true);
});
- it('should return false for invalid Ethereum addresses', () => {
- expect(isAddress('0xinvalid')).toBe(false);
- expect(isAddress('not an address')).toBe(false);
+ it("should return false for invalid Ethereum addresses", () => {
+ expect(isAddress("0xinvalid")).toBe(false);
+ expect(isAddress("not an address")).toBe(false);
});
});
- describe('shorten0xString', () => {
- it('should shorten address to format: 0x1234...5678', () => {
- const address = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e';
- expect(shorten0xString(address as `0x${string}`)).toBe('0x742d35C...8f44e');
+ describe("shorten0xString", () => {
+ it("should shorten address to format: 0x1234...5678", () => {
+ const address = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
+ expect(shorten0xString(address as `0x${string}`)).toBe("0x742d35C...8f44e");
});
});
});
-describe('JSON utilities', () => {
- describe('replacer', () => {
- it('should convert BigInt to string', () => {
- const bigIntValue = BigInt('123456789');
- expect(replacer('test', bigIntValue)).toBe('123456789');
+describe("JSON utilities", () => {
+ describe("replacer", () => {
+ it("should convert BigInt to string", () => {
+ const bigIntValue = BigInt("123456789");
+ expect(replacer("test", bigIntValue)).toBe("123456789");
});
- it('should return non-BigInt values as is', () => {
- expect(replacer('test', 123)).toBe(123);
- expect(replacer('test', 'string')).toBe('string');
- expect(replacer('test', { key: 'value' })).toEqual({ key: 'value' });
+ it("should return non-BigInt values as is", () => {
+ expect(replacer("test", 123)).toBe(123);
+ expect(replacer("test", "string")).toBe("string");
+ expect(replacer("test", { key: "value" })).toEqual({ key: "value" });
});
});
});
-describe('Burner wallet utilities', () => {
+describe("Burner wallet utilities", () => {
let localStorageMock: { [key: string]: string };
beforeEach(() => {
localStorageMock = {};
- vi.stubGlobal('window', {
+ vi.stubGlobal("window", {
localStorage: {
getItem: (key: string) => localStorageMock[key] || null,
setItem: (key: string, value: string) => {
localStorageMock[key] = value;
- },
- },
+ }
+ }
});
});
@@ -81,34 +88,34 @@ describe('Burner wallet utilities', () => {
vi.unstubAllGlobals();
});
- describe('saveBurnerSK', () => {
- it('should save private key to localStorage', () => {
- const testKey = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
+ describe("saveBurnerSK", () => {
+ it("should save private key to localStorage", () => {
+ const testKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
saveBurnerSK(testKey as `0x${string}`);
- expect(localStorageMock['wagmiSvelte5.burnerWallet.sk']).toBe(testKey);
+ expect(localStorageMock["wagmiSvelte5.burnerWallet.sk"]).toBe(testKey);
});
- it('should handle undefined window object', () => {
+ it("should handle undefined window object", () => {
(global as { window: unknown }).window = undefined;
- const testKey = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
+ const testKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
expect(() => saveBurnerSK(testKey as `0x${string}`)).not.toThrow();
});
});
- describe('loadBurnerSK', () => {
- it('should load existing private key from localStorage', () => {
- const testKey = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
- localStorageMock['wagmiSvelte5.burnerWallet.sk'] = testKey;
+ describe("loadBurnerSK", () => {
+ it("should load existing private key from localStorage", () => {
+ const testKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
+ localStorageMock["wagmiSvelte5.burnerWallet.sk"] = testKey;
expect(loadBurnerSK()).toBe(testKey);
});
- it('should generate new private key if none exists', () => {
+ it("should generate new private key if none exists", () => {
const result = loadBurnerSK();
expect(result).toMatch(/^0x[a-fA-F0-9]{64}$/);
});
- it('should handle invalid localStorage key', () => {
- localStorageMock['wagmiSvelte5.burnerWallet.sk'] = 'invalid-key';
+ it("should handle invalid localStorage key", () => {
+ localStorageMock["wagmiSvelte5.burnerWallet.sk"] = "invalid-key";
const result = loadBurnerSK();
expect(result).toMatch(/^0x[a-fA-F0-9]{64}$/);
});
diff --git a/turbo.json b/turbo.json
new file mode 100644
index 0000000..fdca7f2
--- /dev/null
+++ b/turbo.json
@@ -0,0 +1,43 @@
+{
+ "$schema": "https://turbo.build/schema.json",
+ "envMode": "strict",
+ "ui": "stream",
+ "tasks": {
+ "format": {
+ "inputs": ["src/**", "test/**"],
+ "outputLogs": "new-only"
+ },
+ "check": {
+ "dependsOn": ["format"],
+ "outputLogs": "new-only"
+ },
+ "build": {
+ "dependsOn": ["check"],
+ "outputLogs": "new-only"
+ },
+ "test": {
+ "dependsOn": ["build"],
+ "cache": false,
+ "outputLogs": "new-only"
+ },
+ "dev": {
+ "cache": false,
+ "persistent": true,
+ "inputs": ["src/**"],
+ "outputLogs": "new-only"
+ },
+ "start": {
+ "dependsOn": ["check"],
+ "cache": false,
+ "persistent": true,
+ "inputs": ["src/**"],
+ "outputLogs": "new-only"
+ },
+ "preview": {
+ "dependsOn": ["build"],
+ "cache": false,
+ "persistent": true,
+ "outputLogs": "new-only"
+ }
+ }
+}
diff --git a/vite.config.ts b/vite.config.ts
index b76d114..02606cc 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -6,5 +6,8 @@ import deploymentsJson from "./deployments.json";
export default defineConfig({
plugins: [sveltekit()],
server: { open: true },
- define: { __DEPLOYMENTS_JSON__: deploymentsJson }
+ define: {
+ __DEPLOYMENTS_JSON__: deploymentsJson,
+ "process.env.NODE_ENV": '"development"'
+ }
});
diff --git a/vitest.config.ts b/vitest.config.ts
index 945bd46..ba96a58 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -1,19 +1,19 @@
-import { defineConfig } from 'vitest/config'
-import { svelte } from '@sveltejs/vite-plugin-svelte'
-import { resolve } from 'path'
+import { defineConfig } from "vitest/config";
+import { svelte } from "@sveltejs/vite-plugin-svelte";
+import { resolve } from "path";
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
test: {
- include: ['tests/unit/**/*.{test,spec,t}.{js,ts}'],
- environment: 'happy-dom',
+ include: ["tests/unit/**/*.{test,spec,t}.{js,ts}"],
+ environment: "happy-dom",
globals: true,
- setupFiles: ['tests/unit/setup.ts'],
+ setupFiles: ["tests/unit/setup.ts"],
testTimeout: 10000,
hookTimeout: 10000,
teardownTimeout: 10000,
isolate: false,
- pool: 'threads',
+ pool: "threads",
environmentOptions: {
happyDOM: {
settings: {
@@ -24,9 +24,9 @@ export default defineConfig({
},
resolve: {
alias: {
- '$env': resolve(__dirname, './tests/unit/mocks/env'),
- '$lib': resolve(__dirname, './src/lib'),
- '@wagmi-svelte5': resolve(__dirname, './src/lib/wagmi/index.ts')
+ $env: resolve(__dirname, "./tests/unit/mocks/env"),
+ $lib: resolve(__dirname, "./src/lib"),
+ "@wagmi-svelte5": resolve(__dirname, "./src/lib/wagmi/index.ts")
}
}
-})
+});