This document describes the testing infrastructure and how to run tests for the Graphiti extension.
- Vitest - Fast, Vite-native test runner
- @testing-library/react - React component testing utilities
- @testing-library/jest-dom - Custom DOM matchers
- jsdom - Browser environment simulation
- @vitest/coverage-v8 - Code coverage reporting
# Run all tests
npm test
# Run tests with UI
npm run test:ui
# Run tests with coverage report
npm run test:coverageVitest runs in watch mode by default. Press q to quit or h for help.
Tests are organized alongside the source code in __tests__ directories:
src/
├── utils/
│ ├── __tests__/
│ │ ├── crypto.test.ts # Crypto utility tests
│ │ ├── storage.test.ts # Storage tests
│ │ ├── tag-colors.test.ts # Tag color tests
│ │ ├── logger.test.ts # Logger tests
│ │ └── api.integration.test.ts # API integration tests
├── popup/
│ └── __tests__/
│ └── App.integration.test.tsx # Popup component tests
└── sidepanel/
└── __tests__/
└── App.integration.test.tsx # Sidepanel component tests
Unit tests verify individual functions in isolation.
Tests cryptographic functions including:
hexToBytes/bytesToHex- Hex conversionsha256- SHA-256 hashingbase64UrlEncode/base64UrlDecode- Base64URL encodinggenerateUrlHashTag- UTF-16 URL hash tag generationdecryptAuthToken- XOR decryptionparseAuthToken- Auth token parsing
Key test: UTF-16 encoding verification
it('should generate a 10-character hash tag', async () => {
const url = 'https://example.com';
const result = await generateUrlHashTag(url);
expect(result.length).toBe(10);
});Tests the Storage singleton:
- Session CRUD operations
- Bookmark operations
- Tag operations with normalization
- Profile caching with TTL
- Drawing storage
Tests consistent tag coloring:
- Deterministic color assignment
- Hash distribution across color palette
- Style generation
Integration tests verify component interactions.
Tests API layer with mocked network:
- NexusClient queries
- PubkyAPISDK operations
- Post creation and deletion
- URL hash tag usage
Tests React components:
- Authentication flow
- Bookmark actions
- Post creation
- Navigation between views
Chrome extension APIs are mocked in src/test/setup.ts:
(globalThis as any).chrome = {
storage: mockChromeStorage,
runtime: mockChromeRuntime,
tabs: mockChromeTabs,
sidePanel: mockChromeSidePanel,
};External dependencies are mocked with Vitest:
vi.mock('../logger', () => ({
logger: {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
},
}));Coverage thresholds are configured in vitest.config.ts:
coverage: {
thresholds: {
statements: 60,
branches: 50,
functions: 60,
lines: 60,
},
}Run with coverage:
npm run test:coverageCoverage reports are generated in coverage/ directory.
Runs before all tests to:
- Configure jest-dom matchers
- Set up Chrome API mocks
- Initialize crypto.subtle for Node.js
Provides:
mockStorage- Chrome storage mockmockRuntime- Runtime mockmockTabs- Tabs API mocksetupStorageMock(data)- Helper to set initial storage state
import { describe, it, expect, vi, beforeEach } from 'vitest';
describe('MyFunction', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should do something', () => {
expect(myFunction()).toBe(expected);
});
});it('should handle async operations', async () => {
const result = await asyncFunction();
expect(result).toBeDefined();
});import { render, screen, fireEvent } from '@testing-library/react';
it('should render component', async () => {
render(<MyComponent />);
await waitFor(() => {
expect(screen.getByText('Expected Text')).toBeInTheDocument();
});
});npx vitest src/utils/__tests__/crypto.test.tsnpx vitest -t "should generate"npx vitest --inspect-brkTests can be run in CI with:
npm test -- --runThis exits after running all tests (non-watch mode).