Skip to content

Commit

Permalink
add unit tests for Dataset (#874)
Browse files Browse the repository at this point in the history
* test: add unit tests for Dataset
  • Loading branch information
jialudev authored Dec 26, 2024
1 parent 22bbb13 commit c11a74a
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 7 deletions.
28 changes: 23 additions & 5 deletions frontend/setupTests.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { config } from '@vue/test-utils';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import CsgButton from '@/components/shared/CsgButton.vue';
import CsgButton from '@/components/shared/CsgButton.vue';
import SvgIcon from '@/components/shared/SvgIcon.vue';
import FlashMessage from '@/components/shared/FlashMessage.vue';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
import { createI18n } from 'vue-i18n';
import { createPinia } from 'pinia'
import en from '@/locales/en.js'
import zh from '@/locales/zh.js'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import '@/assets/stylesheets/element-plus/_variables.css'
import '@/assets/stylesheets/markdown.css'
import '@/style.css'

const pinia = createPinia();
const i18n = createI18n({
Expand All @@ -19,16 +24,29 @@ const i18n = createI18n({
}
});

config.global.plugins = [ElementPlus, i18n, pinia];

// register global components
config.global.components = {
SvgIcon,
CsgButton,
FlashMessage,
...ElementPlusIconsVue
};

// gllbal mock
config.global.plugins = [
[ElementPlus, {
locale: zhCn,
}],
i18n,
pinia
];

const DEFAULT_TAGS = []
const CSGHUB_SERVER = 'http://localhost:8080'

config.global.provide = {
defaultTags: DEFAULT_TAGS,
csghubServer: CSGHUB_SERVER,
nameRule: /^(?=.{2,64}$)(?!.*[-_.]{2})[a-zA-Z][a-zA-Z0-9_.-]*[a-zA-Z0-9]+$/
};

// Mock window.location
const mockLocation = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { describe, it, expect, beforeEach } from "vitest";
import { mount } from "@vue/test-utils";
import DatasetRelationsCard from "@/components/datasets/DatasetRelationsCard.vue";
import RepoItem from "@/components/shared/RepoItem.vue";

const createWrapper = (props) => {
return mount(DatasetRelationsCard, {
props: {
namespacePath: 'test/namespace',
datasets: [],
...props
}
});
};

describe("DatasetRelationsCard", () => {
it("mounts correctly", () => {
const wrapper = createWrapper();
expect(wrapper.vm).toBeDefined();
});

it("renders correctly with props", () => {
const datasets = [{
id: 1,
name: 'Dataset 1',
path: 'user/dataset-1',
updated_at: '2024-03-20 10:00:00',
downloads: 100
}, {
id: 2,
name: 'Dataset 2',
path: 'user/dataset-2',
updated_at: '2024-03-20 10:00:00',
downloads: 200
}];

const wrapper = createWrapper({ datasets });

// Test title and count display
expect(wrapper.find('h3').text()).toContain('Associated Datasets2');
expect(wrapper.find('h3 .text-gray-500').text().trim()).toBe('2');

// Test RepoItem components rendering
const repoItems = wrapper.findAllComponents(RepoItem);
expect(repoItems.length).toBe(datasets.length);

// Verify RepoItem props
const firstRepoItem = repoItems[0];
expect(firstRepoItem.props('repo')).toEqual(datasets[0]);
expect(firstRepoItem.props('repoType')).toBe('dataset');
expect(firstRepoItem.props('cardType')).toBe('relations');
});

it("renders correctly with empty datasets", () => {
const wrapper = createWrapper({ datasets: [] });
expect(wrapper.findAllComponents(RepoItem).length).toBe(0);
expect(wrapper.find('h3 .text-gray-500').text().trim()).toBe('0');
});
});
150 changes: 150 additions & 0 deletions frontend/src/components/__tests__/datasets/DatasetSettings.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import { mount } from "@vue/test-utils";
import DatasetSettings from "@/components/datasets/DatasetSettings.vue";
import { createPinia, setActivePinia } from 'pinia';

// Mock the API response
vi.mock('../../../packs/useFetchApi', () => ({
default: (url) => ({
post: () => ({
json: () => Promise.resolve({
data: { value: { msg: 'Success' } },
error: { value: null }
})
}),
put: () => ({
json: () => Promise.resolve({
data: { value: { msg: 'Success' } },
error: { value: null }
})
}),
delete: () => ({
json: () => Promise.resolve({
data: { value: null },
error: { value: null }
})
}),
get: () => ({
json: () => Promise.resolve({
data: {
value: {
data: {
content: btoa('test content'),
sha: 'test-sha'
}
}
},
error: { value: null }
})
}),
json: () => {
if (url === '/tags') {
return Promise.resolve({
data: {
value: {
data: [
{ name: 'tag1', category: 'industry', scope: 'dataset', show_name: 'Tag 1' },
{ name: 'tag2', category: 'industry', scope: 'dataset', show_name: 'Tag 2' }
]
}
},
error: { value: null }
})
}
return Promise.resolve({
data: { value: null },
error: { value: null }
})
}
})
}));

const createWrapper = (props = {}) => {
return mount(DatasetSettings, {
props: {
path: "test/dataset",
datasetNickname: "Test Dataset",
datasetDesc: "Test Description",
default_branch: "main",
tagList: [],
tags: {
task_tags: [],
other_tags: [],
industry_tags: []
},
...props
},
global: {
plugins: [createPinia()],
mocks: {
$t: (key) => key
}
}
});
};

describe("DatasetSettings", () => {
beforeEach(() => {
setActivePinia(createPinia());
});

it("mounts correctly", () => {
const wrapper = createWrapper();
expect(wrapper.vm).toBeDefined();
});

it("displays dataset path correctly", () => {
const wrapper = createWrapper();
expect(wrapper.find('.bg-gray-50').text()).toBe("test/dataset");
});

it("updates dataset nickname", async () => {
const wrapper = createWrapper();
await wrapper.find('input').setValue('New Dataset Name');
await wrapper.findAll('button').find(btn => btn.text() === 'all.update').trigger('click');
expect(wrapper.vm.theDatasetNickname).toBe('New Dataset Name');
});

it("updates dataset description", async () => {
const wrapper = createWrapper();
const textarea = wrapper.find('textarea');
await textarea.setValue('New Description');
const updateButtons = wrapper.findAll('button');
await updateButtons[1].trigger('click');
expect(wrapper.vm.theDatasetDesc).toBe('New Description');
});

it("handles tag selection correctly", async () => {
const wrapper = createWrapper({
tagList: [{ name: "tag1", show_name: "Tag 1" }]
});
await wrapper.vm.selectTag({ name: "tag1", show_name: "Tag 1" });
expect(wrapper.vm.selectedTags).toHaveLength(1);
});

it("removes tag when close icon is clicked", async () => {
const wrapper = createWrapper();
await wrapper.setData({
selectedTags: [{ name: "tag1", show_name: "Tag 1" }]
});
await wrapper.vm.removeTag("tag1");
expect(wrapper.vm.selectedTags).toHaveLength(0);
});

it.skip("handles visibility change", async () => {
const wrapper = createWrapper();
const select = wrapper.find('.el-select');
await select.trigger('click');
const options = wrapper.findAll('.el-option');
await options[0].trigger('click');
expect(wrapper.vm.visibilityName).toBe('Private');
});

it("validates delete dataset input", async () => {
const wrapper = createWrapper();
const deleteInput = wrapper.findAll('input').at(-1);
await deleteInput.setValue('test/dataset');
const deleteButton = wrapper.find('#confirmDelete');
expect(deleteButton.classes()).toContain('bg-error-600');
});
});
Loading

0 comments on commit c11a74a

Please sign in to comment.