Skip to content

Commit

Permalink
Merge remote-tracking branch 'github/main' into csghub__ut-datasets
Browse files Browse the repository at this point in the history
  • Loading branch information
jialudev committed Dec 26, 2024
2 parents 9356bfa + 22bbb13 commit 33f7519
Show file tree
Hide file tree
Showing 12 changed files with 533 additions and 144 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import EvaluationDetail from '../../evaluations/EvaluationDetail.vue'

const createResponse = (data, errorMsg = null) => ({
data: { value: { data } },
error: { value: errorMsg ? { msg: errorMsg } : null }
})

const mockApiResponses = {
'/tags?scope=dataset&category=evaluation': createResponse([
{ name: 'tag1', show_name: 'Tag 1' }
]),
'/evaluations/1': createResponse({
task_name: 'task1',
submit_time: '2021-10-01',
repo_ids: ['repo1'],
task_desc: 'desc1',
datasets: [{ repo_id: 'namespace1/repo1', tags: [{ name: 'tag1' }] }],
download_url: 'test.zip'
})
}

vi.mock('../../../packs/useFetchApi', () => ({
default: (url) => ({
json: () => Promise.resolve(mockApiResponses[url] || createResponse([]))
})
}))

describe('EvaluationDetail', () => {
let wrapper

beforeEach(() => {
wrapper = mount(EvaluationDetail, {
props: {
evaluationId: '1'
}
})
})

it('renders evaluation details correctly', async () => {
const dateElement = wrapper.find('.text-gray-700.text-base')
expect(wrapper.find('.text-2xl').text()).toBe('task1')
expect(dateElement.text()).toBe('2021-10-01')
expect(wrapper.text()).includes('desc1')
})

it('displays download button when download_url is present', async () => {
const downloadBtn = wrapper.find('a.btn-primary')
expect(downloadBtn.exists()).toBe(true)
expect(downloadBtn.attributes('href')).toBe('test.zip')
})

it('groups datasets by categories correctly', async () => {
const groupedDatasets = wrapper.vm.groupedDatasets
expect(groupedDatasets).toHaveLength(1)
expect(groupedDatasets[0].name).toBe('tag1')
expect(groupedDatasets[0].datasets[0]).toBe('repo1')
})

it('formats table data correctly', async () => {
wrapper.vm.evaluationResult = {
summary: {
column: [{ key: 'score', customizeRender: true }],
data: [
{
dataset: 'dataset1',
metric: 'metric1',
score: '0.95'
}
]
}
}
wrapper.vm.scoresKey = 'score'
await wrapper.vm.$nextTick()

const tableData = wrapper.vm.getTableData('all')
expect(tableData).toHaveLength(1)
expect(tableData[0]).toEqual({
dataset: 'dataset1',
metric: 'metric1',
score: '0.95'
})
})
})
158 changes: 158 additions & 0 deletions frontend/src/components/__tests__/evaluations/NewEvaluation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import NewEvaluation from '../../evaluations/NewEvaluation.vue'

const MOCK_USERNAME = 'testuser'
const MOCK_MODEL_PATH = `${MOCK_USERNAME}/testmodel`
const MOCK_DATASET_PATH = `${MOCK_USERNAME}/testdataset`
const MOCK_CLUSTER_ID = 'cluster1'
const MOCK_EVALUATION_PATH = `${MOCK_USERNAME}/testevaluation`

const MOCK_RESOURCE = {
id: 1,
order_detail_id: 1,
name: 'gpu-resource',
type: 'gpu',
is_available: true,
pay_mode: 'minute',
price: 1000
}

const MOCK_TRANSFORMED_RESOURCE = {
label: 'all.minutePay',
options: [
{
id: 1,
order_detail_id: 1,
name: 'gpu-resource',
type: 'gpu',
is_available: true,
pay_mode: 'minute',
price: 1000,
label: 'gpu-resource 10all.hourUnit'
}
]
}

const createResponse = (data, errorMsg = null) => ({
data: { value: { data } },
error: { value: errorMsg ? { msg: errorMsg } : null }
})

const mockApiResponses = {
[`/runtime_framework/models?search=test&deploy_type=4`]: createResponse([
{ path: MOCK_MODEL_PATH }
]),
'/cluster': createResponse([
{ cluster_id: MOCK_CLUSTER_ID, region: 'region1' }
]),
[`/space_resources?cluster_id=${MOCK_CLUSTER_ID}`]: createResponse([
MOCK_RESOURCE
]),
[`/models/${MOCK_MODEL_PATH}/runtime_framework?deploy_type=4`]:
createResponse([{ id: 1, frame_name: 'pytorch' }]),
'/tags?scope=dataset&category=evaluation': createResponse([
{ name: 'tag1', show_name: 'Tag 1' }
]),
'/datasets?tag_category=runtime_framework&tag_name=pytorch&tag_category=evaluation&tag_name=tag1':
createResponse([{ path: MOCK_DATASET_PATH }])
}

vi.mock('../../../stores/UserStore', () => ({
default: () => ({ username: MOCK_USERNAME })
}))

vi.mock('../../../packs/useFetchApi', () => ({
default: (url) => ({
json: () => Promise.resolve(mockApiResponses[url] || createResponse([])),
post: () => ({
json: () =>
Promise.resolve(createResponse({ path: MOCK_EVALUATION_PATH }))
})
})
}))

describe('NewEvaluation', () => {
let wrapper

beforeEach(() => {
vi.clearAllMocks()
wrapper = mount(NewEvaluation)
})

describe('Initial State', () => {
it('mounts and initializes with shared resource type', () => {
expect(wrapper.exists()).toBe(true)
expect(wrapper.vm.dataForm.evaluation_resource_type).toBe('shared')
})

it('loads initial data', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.vm.evaluationClusters.length).toBeGreaterThan(0)
})
})

describe('Form Validation', () => {
const validateForm = () => {
return new Promise((resolve) => {
wrapper.vm.$refs.dataFormRef.validate((valid) => resolve(valid))
})
}

it('fails validation with empty required fields', async () => {
expect(await validateForm()).toBe(false)
})

it('fails validation with invalid model_id format', async () => {
wrapper.vm.dataForm.model_id = 'invalid/format/'
await wrapper.vm.$nextTick()
expect(await validateForm()).toBe(false)
})
})

describe('Resource Type UI', () => {
const getClusterSelect = () => wrapper.find('[data-test="cluster-select"]')

it('shows/hides dedicated resource fields based on type selection', async () => {
wrapper.vm.dataForm.evaluation_resource_type = 'dedicated'
await wrapper.vm.$nextTick()
expect(getClusterSelect().isVisible()).toBe(true)

wrapper.vm.dataForm.evaluation_resource_type = 'shared'
await wrapper.vm.$nextTick()
expect(getClusterSelect().isVisible()).toBe(false)
})
})

describe('API Interactions', () => {
it('fetches and formats models', async () => {
await wrapper.vm.fetchModels('test')
expect(wrapper.vm.models).toEqual([
{ key: MOCK_MODEL_PATH, value: MOCK_MODEL_PATH }
])
})

it('fetches resources for selected cluster', async () => {
wrapper.vm.dataForm.evaluation_cluster = MOCK_CLUSTER_ID
await wrapper.vm.fetchResources()
expect(wrapper.vm.evaluationResources).toEqual([
MOCK_TRANSFORMED_RESOURCE
])
})
})

describe('Form Submission', () => {
it('submits form and redirects on success', async () => {
wrapper.vm.dataForm = {
name: 'Test Evaluation',
model_id: MOCK_MODEL_PATH,
evaluation_framework: 1,
evaluation_dataset: [MOCK_DATASET_PATH],
evaluation_resource_type: 'shared'
}

await wrapper.vm.handleSubmit()
expect(window.location.href).toBe('/resource-console')
})
})
})
95 changes: 95 additions & 0 deletions frontend/src/components/__tests__/user_settings/Menu.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { describe, it, expect, beforeEach, vi, afterEach, afterAll } from 'vitest'
import { mount } from '@vue/test-utils'
import Menu from '../../user_settings/Menu.vue'

let userStoreData = {
username: 'test',
nickname: 'testn',
email: '[email protected]',
avatar: 'test_avatar.com'
}
vi.mock('../../../stores/UserStore', () => ({
default: () => (userStoreData)
}))

describe('Menu', () => {
let wrapper

beforeEach(() => {
vi.clearAllMocks()
wrapper = mount(Menu)
})

describe('Initial State', () => {
it('mounts with correct default props', () => {
expect(wrapper.exists()).toBe(true)
expect(wrapper.vm.hasSave).toBe(true)
})
})

describe('template render with email', () => {
it('renders access token navbar', () => {
const link = wrapper.find('a[href="/settings/access-token"]')
expect(link.exists()).toBe(true);
})
it('renders ssh key navbar', () => {
const link = wrapper.find('a[href="/settings/ssh-keys"]')
expect(link.exists()).toBe(true);
})
})

describe('template render without email', () => {
beforeEach(() => {
userStoreData = { username: 'test', nickname: 'testn', avatar: 'test_avatar.com' };
wrapper = mount(Menu)
})
it('renders access token navbar', async () => {
const link = wrapper.find('a[href="/settings/access-token"]')
expect(link.exists()).toBe(false);
})
it('renders ssh key navbar', () => {
const link = wrapper.find('a[href="/settings/ssh-keys"]')
expect(link.exists()).toBe(false);
})
})

describe('click on avatar to jump with saved true', () => {
it('jumps to user profile', async () => {
const avatarDiv = wrapper.find('#user_settings_avatar_div')
await avatarDiv.trigger('click')
expect(window.location.href).toBe(`/profile/${userStoreData.username}`)
})
})

describe('click on avatar to jump with saved false', () => {
beforeEach(() => {
wrapper = mount(Menu, {
props: {
hasSave: false
}
})
})

it('pops up confirm dialog', async () => {
const avatarDiv = wrapper.find('#user_settings_avatar_div')
await avatarDiv.trigger('click')
expect(wrapper.vm.showDialog).toBe(true)
})

it('hide dialog after click on cancel', async () => {
const avatarDiv = wrapper.find('#user_settings_avatar_div')
await avatarDiv.trigger('click')
const cancelBtn = wrapper.find('#user_settings_dialog_cancel')
await cancelBtn.trigger('click')
expect(wrapper.vm.showDialog).toBe(false)
})

it('jumps to user profile after click on confirm', async () => {
const avatarDiv = wrapper.find('#user_settings_avatar_div')
await avatarDiv.trigger('click')
const confirmBtn = wrapper.find('#user_settings_dialog_confirm')
await confirmBtn.trigger('click')
expect(window.location.href).toBe(`/profile/${userStoreData.username}`)
})
})
})
Loading

0 comments on commit 33f7519

Please sign in to comment.