Skip to content

Commit

Permalink
test: add web helpers tests
Browse files Browse the repository at this point in the history
  • Loading branch information
louis-jan committed Sep 16, 2024
1 parent 3ffaa1e commit 596ccd3
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ core/test_results.html
coverage
.yarn
.yarnrc
test_results.html
19 changes: 19 additions & 0 deletions testRunner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const jestRunner = require('jest-runner')

class EmptyTestFileRunner extends jestRunner.default {
async runTests(tests, watcher, onStart, onResult, onFailure, options) {
const nonEmptyTests = tests.filter(
(test) => test.context.hasteFS.getSize(test.path) > 0
)
return super.runTests(
nonEmptyTests,
watcher,
onStart,
onResult,
onFailure,
options
)
}
}

module.exports = EmptyTestFileRunner
9 changes: 9 additions & 0 deletions web/helpers/atoms/ApiServer.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

import { hostOptions } from './ApiServer.atom';

test('hostOptions correct values', () => {
expect(hostOptions).toEqual([
{ name: '127.0.0.1', value: '127.0.0.1' },
{ name: '0.0.0.0', value: '0.0.0.0' },
]);
});
8 changes: 8 additions & 0 deletions web/helpers/atoms/App.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

import { mainViewStateAtom } from './App.atom';
import { MainViewState } from '@/constants/screens';

test('mainViewStateAtom initializes with Thread', () => {
const result = mainViewStateAtom.init;
expect(result).toBe(MainViewState.Thread);
});
7 changes: 7 additions & 0 deletions web/helpers/atoms/AppConfig.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

import { hostAtom } from './AppConfig.atom';

test('hostAtom default value', () => {
const result = hostAtom.init;
expect(result).toBe('http://localhost:1337/');
});
8 changes: 8 additions & 0 deletions web/helpers/atoms/Assistant.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

import { assistantsAtom } from './Assistant.atom';

test('assistantsAtom initializes as an empty array', () => {
const initialValue = assistantsAtom.init;
expect(Array.isArray(initialValue)).toBe(true);
expect(initialValue).toHaveLength(0);
});
32 changes: 32 additions & 0 deletions web/helpers/atoms/ChatMessage.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

import { getCurrentChatMessagesAtom } from './ChatMessage.atom';
import { setConvoMessagesAtom, chatMessages, readyThreadsMessagesAtom } from './ChatMessage.atom';

test('getCurrentChatMessagesAtom returns empty array when no active thread ID', () => {
const getMock = jest.fn().mockReturnValue(undefined);
expect(getCurrentChatMessagesAtom.read(getMock)).toEqual([]);
});


test('getCurrentChatMessagesAtom returns empty array when activeThreadId is undefined', () => {
const getMock = jest.fn().mockReturnValue({
activeThreadId: undefined,
chatMessages: {
threadId: [{ id: 1, content: 'message' }],
},
});
expect(getCurrentChatMessagesAtom.read(getMock)).toEqual([]);
});

test('setConvoMessagesAtom updates chatMessages and readyThreadsMessagesAtom', () => {
const getMock = jest.fn().mockReturnValue({});
const setMock = jest.fn();
const threadId = 'thread1';
const messages = [{ id: '1', content: 'Hello' }];

setConvoMessagesAtom.write(getMock, setMock, threadId, messages);

expect(setMock).toHaveBeenCalledWith(chatMessages, { [threadId]: messages });
expect(setMock).toHaveBeenCalledWith(readyThreadsMessagesAtom, { [threadId]: true });
});

14 changes: 14 additions & 0 deletions web/helpers/atoms/HuggingFace.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import { importHuggingFaceModelStageAtom } from './HuggingFace.atom';
import { importingHuggingFaceRepoDataAtom } from './HuggingFace.atom';

test('importHuggingFaceModelStageAtom should have initial value of NONE', () => {
const result = importHuggingFaceModelStageAtom.init;
expect(result).toBe('NONE');
});


test('importingHuggingFaceRepoDataAtom should have initial value of undefined', () => {
const result = importingHuggingFaceRepoDataAtom.init;
expect(result).toBeUndefined();
});
7 changes: 7 additions & 0 deletions web/helpers/atoms/LocalServer.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

import { serverEnabledAtom } from './LocalServer.atom';

test('serverEnabledAtom_initialValue', () => {
const result = serverEnabledAtom.init;
expect(result).toBe(false);
});
7 changes: 7 additions & 0 deletions web/helpers/atoms/Setting.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

import { selectedSettingAtom } from './Setting.atom';

test('selectedSettingAtom has correct initial value', () => {
const result = selectedSettingAtom.init;
expect(result).toBe('My Models');
});
6 changes: 6 additions & 0 deletions web/helpers/atoms/ThreadRightPanel.atom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

import { activeTabThreadRightPanelAtom } from './ThreadRightPanel.atom';

test('activeTabThreadRightPanelAtom can be imported', () => {
expect(activeTabThreadRightPanelAtom).toBeDefined();
});
2 changes: 1 addition & 1 deletion web/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const createJestConfig = nextJest({})

// Add any custom config to be passed to Jest
const config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
Expand All @@ -17,6 +16,7 @@ const config = {
},
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
runner: './testRunner.js',
}

// https://stackoverflow.com/a/72926763/5078746
Expand Down
30 changes: 30 additions & 0 deletions web/services/appService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

import { ExtensionTypeEnum, extensionManager } from '@/extension';
import { appService } from './appService';

test('should return correct system information when monitoring extension is found', async () => {
const mockGpuSetting = { name: 'NVIDIA GeForce GTX 1080', memory: 8192 };
const mockOsInfo = { platform: 'win32', release: '10.0.19041' };
const mockMonitoringExtension = {
getGpuSetting: jest.fn().mockResolvedValue(mockGpuSetting),
getOsInfo: jest.fn().mockResolvedValue(mockOsInfo),
};
extensionManager.get = jest.fn().mockReturnValue(mockMonitoringExtension);

const result = await appService.systemInformation();

expect(mockMonitoringExtension.getGpuSetting).toHaveBeenCalled();
expect(mockMonitoringExtension.getOsInfo).toHaveBeenCalled();
expect(result).toEqual({ gpuSetting: mockGpuSetting, osInfo: mockOsInfo });
});


test('should log a warning when monitoring extension is not found', async () => {
const consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(() => {});
extensionManager.get = jest.fn().mockReturnValue(undefined);

await appService.systemInformation();

expect(consoleWarnMock).toHaveBeenCalledWith('System monitoring extension not found');
consoleWarnMock.mockRestore();
});
47 changes: 47 additions & 0 deletions web/services/eventsService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

import { EventEmitter } from './eventsService';

test('should do nothing when no handlers for event', () => {
const emitter = new EventEmitter();

expect(() => {
emitter.emit('nonExistentEvent', 'test data');
}).not.toThrow();
});


test('should call all handlers for event', () => {
const emitter = new EventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();

emitter.on('testEvent', handler1);
emitter.on('testEvent', handler2);

emitter.emit('testEvent', 'test data');

expect(handler1).toHaveBeenCalledWith('test data');
expect(handler2).toHaveBeenCalledWith('test data');
});


test('should remove handler for event', () => {
const emitter = new EventEmitter();
const handler = jest.fn();

emitter.on('testEvent', handler);
emitter.off('testEvent', handler);

expect(emitter['handlers'].get('testEvent')).not.toContain(handler);
});


test('should add handler for event', () => {
const emitter = new EventEmitter();
const handler = jest.fn();

emitter.on('testEvent', handler);

expect(emitter['handlers'].has('testEvent')).toBe(true);
expect(emitter['handlers'].get('testEvent')).toContain(handler);
});
35 changes: 35 additions & 0 deletions web/services/extensionService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

import { extensionManager } from '@/extension/ExtensionManager';
import { ExtensionTypeEnum } from '@janhq/core';
import { isCoreExtensionInstalled } from './extensionService';

test('isCoreExtensionInstalled returns true when both extensions are installed', () => {
jest.spyOn(extensionManager, 'get').mockImplementation((type) => {
if (type === ExtensionTypeEnum.Conversational || type === ExtensionTypeEnum.Model) return {};
return undefined;
});

expect(isCoreExtensionInstalled()).toBe(true);
});


test('isCoreExtensionInstalled returns false when Model extension is not installed', () => {
jest.spyOn(extensionManager, 'get').mockImplementation((type) => {
if (type === ExtensionTypeEnum.Conversational) return {};
if (type === ExtensionTypeEnum.Model) return undefined;
return undefined;
});

expect(isCoreExtensionInstalled()).toBe(false);
});


test('isCoreExtensionInstalled returns false when Conversational extension is not installed', () => {
jest.spyOn(extensionManager, 'get').mockImplementation((type) => {
if (type === ExtensionTypeEnum.Conversational) return undefined;
if (type === ExtensionTypeEnum.Model) return {};
return undefined;
});

expect(isCoreExtensionInstalled()).toBe(false);
});
15 changes: 15 additions & 0 deletions web/services/restService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


test('restAPI.baseApiUrl set correctly', () => {
const originalEnv = process.env.API_BASE_URL;
process.env.API_BASE_URL = 'http://test-api.com';

// Re-import to get the updated value
jest.resetModules();
const { restAPI } = require('./restService');

expect(restAPI.baseApiUrl).toBe('http://test-api.com');

// Clean up
process.env.API_BASE_URL = originalEnv;
});

0 comments on commit 596ccd3

Please sign in to comment.