Skip to content

Commit

Permalink
tests: mock for catalog store (#263)
Browse files Browse the repository at this point in the history
* tests: mock for catalog store

* simplify
  • Loading branch information
feloy authored Feb 12, 2024
1 parent d4c50ae commit f7cf100
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 25 deletions.
146 changes: 121 additions & 25 deletions packages/frontend/src/pages/Recipe.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import '@testing-library/jest-dom/vitest';
import { vi, test, expect, beforeEach } from 'vitest';
import { screen, render } from '@testing-library/svelte';
import catalog from '../../../backend/src/ai-user-test.json';
import Recipe from './Recipe.svelte';
import userEvent from '@testing-library/user-event';
import type { Catalog } from '@shared/src/models/ICatalog';
import * as catalogStore from '/@/stores/catalog';
import { readable, writable } from 'svelte/store';

const mocks = vi.hoisted(() => {
return {
Expand Down Expand Up @@ -32,35 +34,139 @@ vi.mock('../utils/client', async () => {
};
});

vi.mock('/@/stores/catalog', async () => {
return {
catalog: vi.fn(),
};
});

const initialCatalog: Catalog = {
categories: [],
models: [
{
id: 'model1',
name: 'Model 1',
description: 'Readme for model 1',
hw: 'CPU',
registry: 'Hugging Face',
popularity: 3,
license: '?',
url: 'https://model1.example.com',
},
{
id: 'model2',
name: 'Model 2',
description: 'Readme for model 2',
hw: 'CPU',
registry: 'Civital',
popularity: 3,
license: '?',
url: '',
},
],
recipes: [
{
id: 'recipe 1',
name: 'Recipe 1',
readme: 'readme 1',
categories: [],
models: ['model1', 'model2'],
description: 'description 1',
repository: 'repo 1',
},
{
id: 'recipe 2',
name: 'Recipe 2',
readme: 'readme 2',
categories: [],
description: 'description 2',
repository: 'repo 2',
},
],
};

const updatedCatalog: Catalog = {
categories: [],
models: [
{
id: 'model1',
name: 'Model 1',
description: 'Readme for model 1',
hw: 'CPU',
registry: 'Hugging Face',
popularity: 3,
license: '?',
url: 'https://model1.example.com',
},
{
id: 'model2',
name: 'Model 2',
description: 'Readme for model 2',
hw: 'CPU',
registry: 'Civital',
popularity: 3,
license: '?',
url: '',
},
],
recipes: [
{
id: 'recipe 1',
name: 'New Recipe Name',
readme: 'readme 1',
categories: [],
models: ['model1', 'model2'],
description: 'description 1',
repository: 'repo 1',
},
{
id: 'recipe 2',
name: 'Recipe 2',
readme: 'readme 2',
categories: [],
description: 'description 2',
repository: 'repo 2',
},
],
};

beforeEach(() => {
vi.resetAllMocks();
});

test('should display recipe information', async () => {
const recipe = catalog.recipes.find(r => r.id === 'recipe 1');
expect(recipe).not.toBeUndefined();
vi.mocked(catalogStore).catalog = readable<Catalog>(initialCatalog);
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
render(Recipe, {
recipeId: 'recipe 1',
});

mocks.getCatalogMock.mockResolvedValue(catalog);
screen.getByText('Recipe 1');
screen.getByText('readme 1');
});

test('should display updated recipe information', async () => {
const customCatalog = writable<Catalog>(initialCatalog);
vi.mocked(catalogStore).catalog = customCatalog;
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
render(Recipe, {
recipeId: 'recipe 1',
});
await new Promise(resolve => setTimeout(resolve, 200));

screen.getByText(recipe!.name);
screen.getByText(recipe!.readme);
screen.getByText('Recipe 1');
screen.getByText('readme 1');

customCatalog.set(updatedCatalog);
await new Promise(resolve => setTimeout(resolve, 10));
screen.getByText('New Recipe Name');
});

test('should display default model information', async () => {
const recipe = catalog.recipes.find(r => r.id === 'recipe 1');
expect(recipe).not.toBeUndefined();

mocks.getCatalogMock.mockResolvedValue(catalog);
vi.mocked(catalogStore).catalog = readable<Catalog>(initialCatalog);
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
render(Recipe, {
recipeId: 'recipe 1',
});
await new Promise(resolve => setTimeout(resolve, 200));

const modelInfo = screen.getByLabelText('model-selected');
expect(modelInfo.textContent).equal('Model 1');
Expand All @@ -71,15 +177,11 @@ test('should display default model information', async () => {
});

test('should open/close application details panel when clicking on toggle button', async () => {
const recipe = catalog.recipes.find(r => r.id === 'recipe 1');
expect(recipe).not.toBeUndefined();

mocks.getCatalogMock.mockResolvedValue(catalog);
vi.mocked(catalogStore).catalog = readable<Catalog>(initialCatalog);
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
render(Recipe, {
recipeId: 'recipe 1',
});
await new Promise(resolve => setTimeout(resolve, 200));

const panelOpenDetails = screen.getByLabelText('toggle application details');
expect(panelOpenDetails).toHaveClass('hidden');
Expand All @@ -101,15 +203,12 @@ test('should open/close application details panel when clicking on toggle button
});

test('should call runApplication execution when run application button is clicked', async () => {
const recipe = catalog.recipes.find(r => r.id === 'recipe 1');
expect(recipe).not.toBeUndefined();
vi.mocked(catalogStore).catalog = readable<Catalog>(initialCatalog);
mocks.pullApplicationMock.mockResolvedValue(undefined);
mocks.getCatalogMock.mockResolvedValue(catalog);
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
render(Recipe, {
recipeId: 'recipe 1',
});
await new Promise(resolve => setTimeout(resolve, 200));

const btnRunApplication = screen.getByRole('button', { name: 'Run application' });
await userEvent.click(btnRunApplication);
Expand All @@ -118,10 +217,7 @@ test('should call runApplication execution when run application button is clicke
});

test('should send telemetry data', async () => {
const recipe = catalog.recipes.find(r => r.id === 'recipe 1');
expect(recipe).not.toBeUndefined();

mocks.getCatalogMock.mockResolvedValue(catalog);
vi.mocked(catalogStore).catalog = readable<Catalog>(initialCatalog);
mocks.getPullingStatusesMock.mockResolvedValue(new Map());
mocks.pullApplicationMock.mockResolvedValue(undefined);

Expand Down
18 changes: 18 additions & 0 deletions packages/frontend/src/stores/catalog.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/**********************************************************************
* Copyright (C) 2024 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/

import type { Readable } from 'svelte/store';
import { readable } from 'svelte/store';
import { MSG_NEW_CATALOG_STATE } from '@shared/Messages';
Expand Down

0 comments on commit f7cf100

Please sign in to comment.