adds eslint

This commit is contained in:
geoffsee
2025-06-24 17:29:52 -04:00
committed by Geoff Seemueller
parent 9698fc6f3b
commit 02c3253343
169 changed files with 4896 additions and 4804 deletions

View File

@@ -1,5 +1,5 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getSnapshot } from 'mobx-state-tree';
import AssetService from '../AssetService.ts';
// Mock the vike/server module
@@ -8,26 +8,27 @@ vi.mock('vike/server', () => ({
}));
// Import the mocked renderPage function for assertions
// eslint-disable-next-line import/order
import { renderPage } from 'vike/server';
describe('AssetService', () => {
let assetService;
beforeEach(() => {
// Create a new instance of the service before each test
assetService = AssetService.create();
// Reset mocks
vi.resetAllMocks();
});
describe('Initial state', () => {
it('should have empty env and ctx objects initially', () => {
expect(assetService.env).toEqual({});
expect(assetService.ctx).toEqual({});
});
});
describe('setEnv', () => {
it('should set the environment', () => {
const mockEnv = { ASSETS: { fetch: vi.fn() } };
@@ -35,7 +36,7 @@ describe('AssetService', () => {
expect(assetService.env).toEqual(mockEnv);
});
});
describe('setCtx', () => {
it('should set the execution context', () => {
const mockCtx = { waitUntil: vi.fn() };
@@ -43,18 +44,18 @@ describe('AssetService', () => {
expect(assetService.ctx).toEqual(mockCtx);
});
});
describe('handleSsr', () => {
it('should return null when httpResponse is not available', async () => {
// Setup mock to return a pageContext without httpResponse
vi.mocked(renderPage).mockResolvedValue({});
const url = 'https://example.com';
const headers = new Headers();
const env = {};
const result = await assetService.handleSsr(url, headers, env);
// Verify renderPage was called with correct arguments
expect(renderPage).toHaveBeenCalledWith({
urlOriginal: url,
@@ -62,15 +63,15 @@ describe('AssetService', () => {
fetch: expect.any(Function),
env,
});
// Verify result is null
expect(result).toBeNull();
});
it('should return a Response when httpResponse is available', async () => {
// Create mock stream
const mockStream = new ReadableStream();
// Setup mock to return a pageContext with httpResponse
vi.mocked(renderPage).mockResolvedValue({
httpResponse: {
@@ -79,13 +80,13 @@ describe('AssetService', () => {
getReadableWebStream: () => mockStream,
},
});
const url = 'https://example.com';
const headers = new Headers();
const env = {};
const result = await assetService.handleSsr(url, headers, env);
// Verify renderPage was called with correct arguments
expect(renderPage).toHaveBeenCalledWith({
urlOriginal: url,
@@ -93,72 +94,72 @@ describe('AssetService', () => {
fetch: expect.any(Function),
env,
});
// Verify result is a Response with correct properties
expect(result).toBeInstanceOf(Response);
expect(result.status).toBe(200);
expect(result.headers.get('Content-Type')).toBe('text/html');
});
});
describe('handleStaticAssets', () => {
it('should fetch assets from the environment', async () => {
// Create mock request
const request = new Request('https://example.com/static/image.png');
// Create mock response
const mockResponse = new Response('Mock asset content', {
status: 200,
headers: { 'Content-Type': 'image/png' },
});
// Create mock environment with ASSETS.fetch
const mockEnv = {
ASSETS: {
fetch: vi.fn().mockResolvedValue(mockResponse),
},
};
// Set the environment
assetService.setEnv(mockEnv);
// Call the method
const result = await assetService.handleStaticAssets(request, mockEnv);
// Verify ASSETS.fetch was called with the request
expect(mockEnv.ASSETS.fetch).toHaveBeenCalledWith(request);
// Verify result is the expected response
expect(result).toBe(mockResponse);
});
it('should return a 404 response when an error occurs', async () => {
// Create mock request
const request = new Request('https://example.com/static/not-found.png');
// Create mock environment with ASSETS.fetch that throws an error
const mockEnv = {
ASSETS: {
fetch: vi.fn().mockRejectedValue(new Error('Asset not found')),
},
};
// Set the environment
assetService.setEnv(mockEnv);
// Call the method
const result = await assetService.handleStaticAssets(request, mockEnv);
// Verify ASSETS.fetch was called with the request
expect(mockEnv.ASSETS.fetch).toHaveBeenCalledWith(request);
// Verify result is a 404 Response
expect(result).toBeInstanceOf(Response);
expect(result.status).toBe(404);
// Verify response body
const text = await result.clone().text();
expect(text).toBe('Asset not found');
});
});
});
});

View File

@@ -1,31 +1,28 @@
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {getSnapshot} from 'mobx-state-tree';
import ChatService, {ClientError} from '../ChatService.ts';
import { getSnapshot } from 'mobx-state-tree';
import OpenAI from 'openai';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import ChatSdk from '../../lib/chat-sdk.ts';
import ChatService, { ClientError } from '../ChatService.ts';
// Create mock OpenAI instance
const mockOpenAIInstance = {
models: {
list: vi.fn().mockResolvedValue({
data: [
{ id: 'mlx-model-1' },
{ id: 'mlx-model-2' },
{ id: 'other-model' }
]
})
data: [{ id: 'mlx-model-1' }, { id: 'mlx-model-2' }, { id: 'other-model' }],
}),
},
chat: {
completions: {
create: vi.fn()
}
create: vi.fn(),
},
},
baseURL: 'http://localhost:8000'
baseURL: 'http://localhost:8000',
};
// Mock dependencies
vi.mock('openai', () => {
return {
default: vi.fn().mockImplementation(() => mockOpenAIInstance)
default: vi.fn().mockImplementation(() => mockOpenAIInstance),
};
});
@@ -33,12 +30,12 @@ vi.mock('../../lib/chat-sdk', () => ({
default: {
handleChatRequest: vi.fn(),
buildAssistantPrompt: vi.fn(),
buildMessageChain: vi.fn()
}
buildMessageChain: vi.fn(),
},
}));
vi.mock('../../lib/handleStreamData', () => ({
default: vi.fn().mockReturnValue(() => {})
default: vi.fn().mockReturnValue(() => {}),
}));
describe('ChatService', () => {
@@ -51,7 +48,7 @@ describe('ChatService', () => {
maxTokens: 2000,
systemPrompt: 'You are a helpful assistant.',
openAIApiKey: 'test-api-key',
openAIBaseURL: 'https://api.openai.com/v1'
openAIBaseURL: 'https://api.openai.com/v1',
});
// Create mock environment
@@ -61,14 +58,16 @@ describe('ChatService', () => {
SERVER_COORDINATOR: {
idFromName: vi.fn().mockReturnValue('test-id'),
get: vi.fn().mockReturnValue({
getStreamData: vi.fn().mockResolvedValue(JSON.stringify({
messages: [],
model: 'gpt-4',
systemPrompt: 'You are a helpful assistant.',
preprocessedContext: {}
}))
})
}
getStreamData: vi.fn().mockResolvedValue(
JSON.stringify({
messages: [],
model: 'gpt-4',
systemPrompt: 'You are a helpful assistant.',
preprocessedContext: {},
}),
),
}),
},
};
// Set the environment using the action
@@ -86,7 +85,7 @@ describe('ChatService', () => {
it('should have the correct initial state', () => {
const freshService = ChatService.create({
maxTokens: 2000,
systemPrompt: 'You are a helpful assistant.'
systemPrompt: 'You are a helpful assistant.',
});
expect(freshService.maxTokens).toBe(2000);
@@ -101,7 +100,7 @@ describe('ChatService', () => {
it('should set the environment and initialize OpenAI client with local endpoint', () => {
const localEnv = {
...mockEnv,
OPENAI_API_ENDPOINT: 'http://localhost:8000'
OPENAI_API_ENDPOINT: 'http://localhost:8000',
};
// Reset the mock to track new calls
@@ -112,7 +111,7 @@ describe('ChatService', () => {
expect(chatService.env).toEqual(localEnv);
expect(OpenAI).toHaveBeenCalledWith({
apiKey: localEnv.OPENAI_API_KEY,
baseURL: localEnv.OPENAI_API_ENDPOINT
baseURL: localEnv.OPENAI_API_ENDPOINT,
});
});
@@ -122,7 +121,7 @@ describe('ChatService', () => {
maxTokens: 2000,
systemPrompt: 'You are a helpful assistant.',
openAIApiKey: 'test-api-key',
openAIBaseURL: 'https://api.openai.com/v1'
openAIBaseURL: 'https://api.openai.com/v1',
});
// Reset the mock to track new calls
@@ -133,7 +132,7 @@ describe('ChatService', () => {
expect(service.env).toEqual(mockEnv);
expect(OpenAI).toHaveBeenCalledWith({
apiKey: 'test-api-key',
baseURL: 'https://api.openai.com/v1'
baseURL: 'https://api.openai.com/v1',
});
});
});
@@ -146,7 +145,7 @@ describe('ChatService', () => {
maxTokens: 1000,
systemPrompt: 'You are a helpful assistant.',
model: 'gpt-4',
messages: []
messages: [],
};
// Set active stream
@@ -170,7 +169,7 @@ describe('ChatService', () => {
maxTokens: 0,
systemPrompt: '',
model: '',
messages: []
messages: [],
});
// Set active stream with partial data
@@ -181,7 +180,7 @@ describe('ChatService', () => {
maxTokens: 0,
systemPrompt: '',
model: '',
messages: []
messages: [],
});
});
});
@@ -189,21 +188,21 @@ describe('ChatService', () => {
describe('getSupportedModels', () => {
it('should return local models when using localhost endpoint', async () => {
const originalResponseJson = Response.json;
Response.json = vi.fn().mockImplementation((data) => {
Response.json = vi.fn().mockImplementation(data => {
return {
json: async () => data
json: async () => data,
};
});
const localEnv = {
...mockEnv,
OPENAI_API_ENDPOINT: 'http://localhost:8000'
OPENAI_API_ENDPOINT: 'http://localhost:8000',
};
// Create a new service instance for this test
const localService = ChatService.create({
maxTokens: 2000,
systemPrompt: 'You are a helpful assistant.'
systemPrompt: 'You are a helpful assistant.',
});
localService.setEnv(localEnv);
@@ -211,7 +210,7 @@ describe('ChatService', () => {
// Mock the implementation of getSupportedModels for this test
const originalGetSupportedModels = localService.getSupportedModels;
localService.getSupportedModels = vi.fn().mockResolvedValueOnce({
json: async () => ['mlx-model-1', 'mlx-model-2']
json: async () => ['mlx-model-1', 'mlx-model-2'],
});
const response = await localService.getSupportedModels();
@@ -238,7 +237,7 @@ describe('ChatService', () => {
openai: chatService.openai,
env: mockEnv,
systemPrompt: chatService.systemPrompt,
maxTokens: chatService.maxTokens
maxTokens: chatService.maxTokens,
});
expect(result).toBe(mockResponse);
@@ -263,7 +262,7 @@ describe('ChatService', () => {
// Mock the SERVER_COORDINATOR.get() to return an object with getStreamData
const mockDurableObject = {
getStreamData: vi.fn().mockResolvedValue(null)
getStreamData: vi.fn().mockResolvedValue(null),
};
// Update the mockEnv to use our mock
@@ -271,8 +270,8 @@ describe('ChatService', () => {
...mockEnv,
SERVER_COORDINATOR: {
idFromName: vi.fn().mockReturnValue('test-id'),
get: vi.fn().mockReturnValue(mockDurableObject)
}
get: vi.fn().mockReturnValue(mockDurableObject),
},
};
// Set the environment
@@ -290,15 +289,15 @@ describe('ChatService', () => {
// Create a new service instance for this test
const testService = ChatService.create({
maxTokens: 2000,
systemPrompt: 'You are a helpful assistant.'
systemPrompt: 'You are a helpful assistant.',
});
// Set up minimal environment
testService.setEnv({
SERVER_COORDINATOR: {
idFromName: vi.fn(),
get: vi.fn()
}
get: vi.fn(),
},
});
// Save the original method
@@ -310,10 +309,10 @@ describe('ChatService', () => {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
Connection: 'keep-alive',
},
status: 200,
text: vi.fn().mockResolvedValue('')
text: vi.fn().mockResolvedValue(''),
});
const result = await testService.handleSseStream(streamId);
@@ -349,7 +348,7 @@ describe('ChatService', () => {
type: 'error',
message: 'Test error',
details: { detail: 'test' },
statusCode: 400
statusCode: 400,
});
});
});

View File

@@ -1,7 +1,8 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getSnapshot } from 'mobx-state-tree';
import ContactService from '../ContactService.ts';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import ContactRecord from '../../models/ContactRecord.ts';
import ContactService from '../ContactService.ts';
describe('ContactService', () => {
let contactService;

View File

@@ -1,7 +1,8 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getSnapshot } from 'mobx-state-tree';
import FeedbackService from '../FeedbackService.ts';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import FeedbackRecord from '../../models/FeedbackRecord.ts';
import FeedbackService from '../FeedbackService.ts';
describe('FeedbackService', () => {
let feedbackService;

View File

@@ -1,9 +1,10 @@
import {describe, expect, it} from 'vitest';
import MetricsService from "../MetricsService";
import { describe, expect, it } from 'vitest';
import MetricsService from '../MetricsService';
describe('MetricsService', () => {
it("should create a metrics service", () => {
it('should create a metrics service', () => {
const metricsService = MetricsService.create();
expect(metricsService).toBeTruthy();
})
})
});
});

View File

@@ -1,34 +1,38 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { getSnapshot, Instance } from 'mobx-state-tree';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import TransactionService from '../TransactionService.ts';
// Define types for testing
type TransactionServiceInstance = Instance<typeof TransactionService>;
// Mock global types
vi.stubGlobal('Response', class MockResponse {
status: number;
headers: Headers;
body: any;
vi.stubGlobal(
'Response',
class MockResponse {
status: number;
headers: Headers;
body: any;
constructor(body?: any, init?: ResponseInit) {
this.body = body;
this.status = init?.status || 200;
this.headers = new Headers(init?.headers);
}
constructor(body?: any, init?: ResponseInit) {
this.body = body;
this.status = init?.status || 200;
this.headers = new Headers(init?.headers);
}
clone() {
return this;
}
clone() {
return this;
}
async text() {
return this.body?.toString() || '';
}
async text() {
return this.body?.toString() || '';
}
async json() {
return typeof this.body === 'string' ? JSON.parse(this.body) : this.body;
}
});
async json() {
return typeof this.body === 'string' ? JSON.parse(this.body) : this.body;
}
},
);
describe('TransactionService', () => {
let transactionService: TransactionServiceInstance;
@@ -83,8 +87,9 @@ describe('TransactionService', () => {
it('should throw an error for unknown actions', async () => {
// Call routeAction with an invalid action
await expect(transactionService.routeAction('UNKNOWN_ACTION', ['data']))
.rejects.toThrow('No handler for action: UNKNOWN_ACTION');
await expect(transactionService.routeAction('UNKNOWN_ACTION', ['data'])).rejects.toThrow(
'No handler for action: UNKNOWN_ACTION',
);
});
});
@@ -96,8 +101,8 @@ describe('TransactionService', () => {
// Mock KV_STORAGE
const mockEnv = {
KV_STORAGE: {
put: vi.fn().mockResolvedValue(undefined)
}
put: vi.fn().mockResolvedValue(undefined),
},
};
transactionService.setEnv(mockEnv);
});
@@ -108,31 +113,33 @@ describe('TransactionService', () => {
'mock-address',
'mock-private-key',
'mock-public-key',
'mock-phrase'
'mock-phrase',
]);
global.fetch.mockResolvedValue({
text: vi.fn().mockResolvedValue(mockWalletResponse)
text: vi.fn().mockResolvedValue(mockWalletResponse),
});
// Call the method with test data
const result = await transactionService.handlePrepareTransaction(['donor123', 'bitcoin', '0.01']);
const result = await transactionService.handlePrepareTransaction([
'donor123',
'bitcoin',
'0.01',
]);
// Verify fetch was called with the correct URL
expect(global.fetch).toHaveBeenCalledWith(
'https://wallets.seemueller.io/api/btc/create'
);
expect(global.fetch).toHaveBeenCalledWith('https://wallets.seemueller.io/api/btc/create');
// Verify KV_STORAGE.put was called with the correct data
expect(transactionService.env.KV_STORAGE.put).toHaveBeenCalledWith(
'transactions::prepared::mock-uuid',
expect.stringContaining('mock-address')
expect.stringContaining('mock-address'),
);
// Verify the returned data
expect(result).toEqual({
depositAddress: 'mock-address',
txKey: 'mock-uuid'
txKey: 'mock-uuid',
});
});
@@ -142,29 +149,25 @@ describe('TransactionService', () => {
'mock-address',
'mock-private-key',
'mock-public-key',
'mock-phrase'
'mock-phrase',
]);
global.fetch.mockResolvedValue({
text: vi.fn().mockResolvedValue(mockWalletResponse)
text: vi.fn().mockResolvedValue(mockWalletResponse),
});
// Test with ethereum
await transactionService.handlePrepareTransaction(['donor123', 'ethereum', '0.01']);
expect(global.fetch).toHaveBeenCalledWith(
'https://wallets.seemueller.io/api/eth/create'
);
expect(global.fetch).toHaveBeenCalledWith('https://wallets.seemueller.io/api/eth/create');
// Reset mock and test with dogecoin
vi.resetAllMocks();
global.fetch.mockResolvedValue({
text: vi.fn().mockResolvedValue(mockWalletResponse)
text: vi.fn().mockResolvedValue(mockWalletResponse),
});
await transactionService.handlePrepareTransaction(['donor123', 'dogecoin', '0.01']);
expect(global.fetch).toHaveBeenCalledWith(
'https://wallets.seemueller.io/api/doge/create'
);
expect(global.fetch).toHaveBeenCalledWith('https://wallets.seemueller.io/api/doge/create');
});
});
@@ -177,17 +180,18 @@ describe('TransactionService', () => {
it('should process a valid transaction request', async () => {
// Create a mock request
const mockRequest = {
text: vi.fn().mockResolvedValue('PREPARE_TX,donor123,bitcoin,0.01')
text: vi.fn().mockResolvedValue('PREPARE_TX,donor123,bitcoin,0.01'),
};
// Call the method
const response = await transactionService.handleTransact(mockRequest);
// Verify routeAction was called with the correct parameters
expect(transactionService.routeAction).toHaveBeenCalledWith(
'PREPARE_TX',
['donor123', 'bitcoin', '0.01']
);
expect(transactionService.routeAction).toHaveBeenCalledWith('PREPARE_TX', [
'donor123',
'bitcoin',
'0.01',
]);
// Verify the response
expect(response).toBeInstanceOf(Response);
@@ -200,7 +204,7 @@ describe('TransactionService', () => {
it('should handle errors gracefully', async () => {
// Create a mock request
const mockRequest = {
text: vi.fn().mockResolvedValue('PREPARE_TX,donor123,bitcoin,0.01')
text: vi.fn().mockResolvedValue('PREPARE_TX,donor123,bitcoin,0.01'),
};
// Make routeAction throw an error