Skip to content

Frontend tests #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 69 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
4011a4b
add tailwind
ken-zlai Sep 24, 2024
f46c568
format code w/ prettier
ken-zlai Sep 24, 2024
6a05ff7
add shadcn
ken-zlai Sep 24, 2024
2a9aad1
add shadcn button
ken-zlai Sep 24, 2024
f96c4fe
use button on home page for simple counter
ken-zlai Sep 24, 2024
570ba5d
npm run format
ken-zlai Sep 24, 2024
2b2bddc
modify typescript rules to ignore specific errors in shadcn components
ken-zlai Sep 24, 2024
53e759e
configure tailwind typography
ken-zlai Sep 24, 2024
8dab5f7
Merge branch 'ken-websvc' into ken-frontend
ken-zlai Sep 25, 2024
71895c7
basic dark mode config
ken-zlai Sep 25, 2024
d0b55ea
ignore warnings from node_modules folder
ken-zlai Sep 25, 2024
1e11bc2
configure testing stuff
ken-zlai Sep 25, 2024
3205caa
readme
ken-zlai Sep 25, 2024
afb9aea
move tests
ken-zlai Sep 25, 2024
05bce39
dark mode should be applied in the app.html
ken-zlai Sep 25, 2024
1c31f4a
create a reusable echart component
ken-zlai Sep 26, 2024
8f5bd92
basic heatmap to start testing
ken-zlai Sep 26, 2024
201dc8e
install echarts
ken-zlai Sep 26, 2024
251a052
fix type issues
ken-zlai Sep 26, 2024
a77da82
add sheet component
ken-zlai Sep 26, 2024
6d3a1e9
use resizeobserver on my echart
ken-zlai Sep 27, 2024
7462ed4
refactor echart for clarity
ken-zlai Sep 27, 2024
b2270f6
use proper type
ken-zlai Sep 27, 2024
cf8c8e6
svelte 5 state
ken-zlai Sep 27, 2024
ea4ba7b
create SplitView.svelte
ken-zlai Sep 27, 2024
db32508
use SplitView to show heatmap/sidebar
ken-zlai Sep 27, 2024
f8060b1
Merge branch 'piyush--apis' into ken-frontend
ken-zlai Sep 30, 2024
fffd0ed
add table component
ken-zlai Sep 30, 2024
ea0cd3c
index to export table elements
ken-zlai Sep 30, 2024
fd3702b
add basic api
ken-zlai Sep 30, 2024
7eb1bea
type for model
ken-zlai Sep 30, 2024
00f3807
format code
ken-zlai Sep 30, 2024
dc76a03
add ModelsResponse
ken-zlai Sep 30, 2024
998956a
render a basic table with models data
ken-zlai Sep 30, 2024
7ab1d5d
change route structure
ken-zlai Sep 30, 2024
79268df
add preview of timeseries data
ken-zlai Sep 30, 2024
8e9327c
add avatar
ken-zlai Sep 30, 2024
1855d2e
zipline logo
ken-zlai Sep 30, 2024
3d76751
Wire up Play frontend + server in docker setup
piyush-zlai Sep 30, 2024
c3f728a
create a layout for the app w/ top and left bar
ken-zlai Sep 30, 2024
578ed5b
move model code to model route
ken-zlai Sep 30, 2024
a284edb
add loading indication on nav
ken-zlai Sep 30, 2024
114511f
Merge branch 'main' into ken-frontend
ken-zlai Sep 30, 2024
7e7d697
Fix based on coder rabbit suggestions
piyush-zlai Sep 30, 2024
557555b
Address feedback
piyush-zlai Oct 1, 2024
5691a3c
Merge remote-tracking branch 'origin/piyush/docker-play' into ken-fro…
ken-zlai Oct 1, 2024
34da3a4
configure frontend to build using nodejs
ken-zlai Oct 1, 2024
811cb65
create a custom build for docker to use that env file
ken-zlai Oct 1, 2024
6b27bd3
add a quick coming soon to the / route
ken-zlai Oct 1, 2024
115faa3
zipline logo routes to / route
ken-zlai Oct 1, 2024
9e63629
quick header for timeseries data
ken-zlai Oct 1, 2024
c7cb4a4
Merge branch 'main' into ken-frontend
ken-zlai Oct 1, 2024
cf2e418
remove old frontend stuff from build.sbt
ken-zlai Oct 1, 2024
463eefe
update docker readme
ken-zlai Oct 1, 2024
5ade424
format
ken-zlai Oct 1, 2024
b26c672
add link to the heatmap preview
ken-zlai Oct 1, 2024
6a75611
add instructions for how to start the backend server first for dev work
ken-zlai Oct 2, 2024
f84133a
add tests for core api functionality
ken-zlai Oct 2, 2024
6c52f28
.env files were ignored in the .gitignore - remove this
ken-zlai Oct 2, 2024
4750136
cleaner way to run docker build
ken-zlai Oct 2, 2024
045858f
Merge branch 'ken-frontend' into frontend-tests
ken-zlai Oct 2, 2024
eb11d7b
create tests that verify backend types for model
ken-zlai Oct 3, 2024
a6b1a47
remove comments
ken-zlai Oct 3, 2024
1f7426a
Merge branch 'main' into frontend-tests
ken-zlai Oct 3, 2024
5eb7ccb
delete old test file
ken-zlai Oct 3, 2024
2c58662
delete old model file
ken-zlai Oct 3, 2024
83f97d6
fix import
ken-zlai Oct 3, 2024
ea9efb0
Merge branch 'main' into frontend-tests
ken-zlai Oct 3, 2024
70578df
Merge branch 'main' into frontend-tests
ken-zlai Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ npm run preview

### Running Tests

> **Important:** You must start the backend before running tests. In the future, we can add scripts to automatically start the backend before any tests are run.

#### All Tests

To run both unit and integration tests together:
Expand Down
62 changes: 62 additions & 0 deletions frontend/src/lib/api/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { get } from './api';
import { error } from '@sveltejs/kit';

// Mock the fetch function
const mockFetch = vi.fn();
global.fetch = mockFetch;

// Mock the error function from @sveltejs/kit
vi.mock('@sveltejs/kit', () => ({
error: vi.fn()
}));

describe('API module', () => {
beforeEach(() => {
vi.resetAllMocks();
});

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

describe('get function', () => {
it('should make a GET request and return parsed JSON data', async () => {
const mockResponse = { data: 'test data' };
mockFetch.mockResolvedValueOnce({
ok: true,
text: () => Promise.resolve(JSON.stringify(mockResponse))
});

const result = await get('test-path');

expect(mockFetch).toHaveBeenCalledWith(
`${import.meta.env.VITE_API_BASE_URL}/api/v1/test-path`,
{ method: 'GET', headers: {} }
);
expect(result).toEqual(mockResponse);
});

it('should return an empty object if the response is empty', async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
text: () => Promise.resolve('')
});

const result = await get('empty-path');

expect(result).toEqual({});
});

it('should throw an error if the response is not ok', async () => {
mockFetch.mockResolvedValueOnce({
ok: false,
status: 404
});

await get('error-path');

expect(error).toHaveBeenCalledWith(404);
});
});
});
75 changes: 75 additions & 0 deletions frontend/src/lib/types/Model/Model.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { describe, it, expect } from 'vitest';
import * as api from '$lib/api/api';
import type { ModelsResponse, TimeSeriesResponse, Model } from '$lib/types/Model/Model';

describe('Model types', () => {
it('should match ModelsResponse type', async () => {
const result = (await api.get('models')) as ModelsResponse;

const expectedKeys = ['offset', 'items'];
expect(Object.keys(result)).toEqual(expect.arrayContaining(expectedKeys));

// Log a warning if there are additional fields
const additionalKeys = Object.keys(result).filter((key) => !expectedKeys.includes(key));
if (additionalKeys.length > 0) {
console.warn(`Additional fields found in ModelsResponse: ${additionalKeys.join(', ')}`);
}

expect(Array.isArray(result.items)).toBe(true);

if (result.items.length > 0) {
const model = result.items[0];
const expectedModelKeys: (keyof Model)[] = [
'name',
'id',
'online',
'production',
'team',
'modelType',
'createTime',
'lastUpdated'
];
expect(Object.keys(model)).toEqual(expect.arrayContaining(expectedModelKeys));

// Log a warning if there are additional fields
const additionalModelKeys = Object.keys(model).filter(
(key) => !expectedModelKeys.includes(key as keyof Model)
);
if (additionalModelKeys.length > 0) {
console.warn(`Additional fields found in Model: ${additionalModelKeys.join(', ')}`);
}
}
});

it('should match TimeSeriesResponse type', async () => {
const modelId = '0';
const result = (await api.get(
`model/${modelId}/timeseries?startTs=1725926400000&endTs=1726106400000&offset=10h&algorithm=psi`
)) as TimeSeriesResponse;

const expectedKeys = ['id', 'items'];
expect(Object.keys(result)).toEqual(expect.arrayContaining(expectedKeys));

// Log a warning if there are additional fields
const additionalKeys = Object.keys(result).filter((key) => !expectedKeys.includes(key));
if (additionalKeys.length > 0) {
console.warn(`Additional fields found in TimeSeriesResponse: ${additionalKeys.join(', ')}`);
}

expect(Array.isArray(result.items)).toBe(true);

if (result.items.length > 0) {
const item = result.items[0];
const expectedItemKeys = ['value', 'ts', 'label'];
expect(Object.keys(item)).toEqual(expect.arrayContaining(expectedItemKeys));

// Log a warning if there are additional fields
const additionalItemKeys = Object.keys(item).filter((key) => !expectedItemKeys.includes(key));
if (additionalItemKeys.length > 0) {
console.warn(
`Additional fields found in TimeSeriesResponse item: ${additionalItemKeys.join(', ')}`
);
}
}
});
});
26 changes: 26 additions & 0 deletions frontend/src/lib/types/Model/Model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export type Model = {
name: string;
id: string;
online: boolean;
production: boolean;
team: string;
modelType: string;
createTime: number;
lastUpdated: number;
};

export type ModelsResponse = {
offset: number;
items: Model[];
};

export type TimeSeriesItem = {
value: number;
ts: number;
label: string | null;
};

export type TimeSeriesResponse = {
id: string;
items: TimeSeriesItem[];
};
2 changes: 1 addition & 1 deletion frontend/src/routes/models/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { PageServerLoad } from './$types';
import type { ModelsResponse } from '$lib/types/Model';
import type { ModelsResponse } from '$lib/types/Model/Model';
import * as api from '$lib/api/api';

export const load: PageServerLoad = async (): Promise<{ models: ModelsResponse }> => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PageServerLoad } from './$types';
import * as api from '$lib/api/api';
import type { TimeSeriesResponse } from '$lib/types/Model';
import type { TimeSeriesResponse } from '$lib/types/Model/Model';

export const load: PageServerLoad = async ({
params
Expand Down
7 changes: 0 additions & 7 deletions frontend/src/test/unit/index.test.ts

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['./src/test/unit/**/*.{test,spec}.{js,ts}']
include: ['./src/**/*.{test,spec}.{js,ts}']
}
});
Loading