From 616af9d2051afd7c87f7a1abe88f93bf55edf5a4 Mon Sep 17 00:00:00 2001 From: zhendi Date: Thu, 26 Dec 2024 17:07:16 +0800 Subject: [PATCH] add codes unit test --- .../__tests__/codes/CodeRelationsCard.spec.js | 39 ++++++++ .../__tests__/codes/CodeSettings.spect.js | 73 ++++++++++++++ .../__tests__/codes/NewCode.spec.js | 99 +++++++++++++++++++ 3 files changed, 211 insertions(+) create mode 100644 frontend/src/components/__tests__/codes/CodeRelationsCard.spec.js create mode 100644 frontend/src/components/__tests__/codes/CodeSettings.spect.js create mode 100644 frontend/src/components/__tests__/codes/NewCode.spec.js diff --git a/frontend/src/components/__tests__/codes/CodeRelationsCard.spec.js b/frontend/src/components/__tests__/codes/CodeRelationsCard.spec.js new file mode 100644 index 000000000..3b15840e5 --- /dev/null +++ b/frontend/src/components/__tests__/codes/CodeRelationsCard.spec.js @@ -0,0 +1,39 @@ +import { describe, it, expect } from "vitest"; +import { mount } from "@vue/test-utils"; +import CodeRelationsCard from "@/components/codes/CodeRelationsCard.vue"; +import RepoItem from "@/components/shared/RepoItem.vue"; + +const createWrapper = (props) => { + return mount(CodeRelationsCard, { + props: { + namespacePath: 'test/namespace', + codes: [], + ...props + } + }); +}; + +describe("CodeRelationsCard", () => { + it("mounts correctly", () => { + const wrapper = createWrapper(); + expect(wrapper.vm).toBeDefined(); + }); + + it.skip("renders correctly with props", () => { + const codes = [{ + id: 1, + name: 'Code 1', + path: 'user/code-1', + updated_at: '2024-03-20 10:00:00', + downloads: 100 + }, { + id: 2, + name: 'Code 2', + path: 'user/code-2', + updated_at: '2024-03-20 10:00:00', + downloads: 200 + }]; + const wrapper = createWrapper({ codes }); + expect(wrapper.findAllComponents(RepoItem).length).toBe(codes.length); + }); +}); diff --git a/frontend/src/components/__tests__/codes/CodeSettings.spect.js b/frontend/src/components/__tests__/codes/CodeSettings.spect.js new file mode 100644 index 000000000..19159380c --- /dev/null +++ b/frontend/src/components/__tests__/codes/CodeSettings.spect.js @@ -0,0 +1,73 @@ +import { describe, it, expect, beforeEach, vi } from "vitest"; +import { mount } from "@vue/test-utils"; +import CodeSettings from "@/components/codes/CodeSettings.vue"; +import { createPinia, setActivePinia } from 'pinia'; +import { ElMessage } from 'element-plus'; + +vi.mock('element-plus', () => ({ + ElMessage: { + success: vi.fn(), + warning: vi.fn() + } +})); + +// Mock the API response +vi.mock('../../../packs/useFetchApi', () => ({ + default: (url) => ({ + post: () => ({ + json: () => Promise.resolve({ + data: { value: { data: { path: 'testuser/testcode' } } }, + error: { value: null } + }) + }), + json: () => { + return Promise.resolve({ + data: { value: null }, + error: { value: null } + }) + } + }) +})); + +const createWrapper = (props = {}) => { + return mount(CodeSettings, { + props: { + path: "test/code", + codeNickname: "Test Code", + codeDesc: "Test Description", + default_branch: "main", + ...props + }, + }); +}; + +describe("CodeSettings", () => { + beforeEach(() => { + setActivePinia(createPinia()); + }); + + it("mounts correctly", () => { + const wrapper = createWrapper(); + expect(wrapper.vm).toBeDefined(); + }); + + it("displays code path correctly", () => { + const wrapper = createWrapper(); + expect(wrapper.find('.bg-gray-50').text()).toBe("test/code"); + }); + + it.skip("updates code nickname when button is clicked", async () => { + const wrapper = createWrapper(); + await wrapper.setData({ codeNickname: "New Name" }); + await wrapper.find('button').trigger('click'); + expect(ElMessage.success).toHaveBeenCalled(); + }); + + it.skip("shows warning when trying to update empty nickname", async () => { + const wrapper = createWrapper(); + await wrapper.setData({ codeNickname: "" }); + const updateButton = wrapper.findAll('button').find(btn => btn.text() === 'all.update'); + await updateButton.trigger('click'); + expect(ElMessage.warning).toHaveBeenCalled(); + }); +}); diff --git a/frontend/src/components/__tests__/codes/NewCode.spec.js b/frontend/src/components/__tests__/codes/NewCode.spec.js new file mode 100644 index 000000000..fd557cba8 --- /dev/null +++ b/frontend/src/components/__tests__/codes/NewCode.spec.js @@ -0,0 +1,99 @@ +import { describe, it, expect, vi } from 'vitest' +import { mount } from '@vue/test-utils' +import NewCode from '@/components/codes/NewCode.vue' + +const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) + +const createWrapper = (props) => { + return mount(NewCode, { + global: { + provide: { + nameRule: /^[a-zA-Z][a-zA-Z0-9-_.]*[a-zA-Z0-9]$/ + } + }, + props: { + licenses: [['MIT', 'GPL-3.0', 'Apache-2.0']], + ...props + } + }) +} + +const triggerFormButton = async (wrapper) => { + const button = wrapper.findComponent({ name: 'CsgButton' }) + await button.trigger('click') + await delay(300) + await wrapper.vm.$nextTick() +} + +vi.mock('../../../stores/UserStore', () => ({ + default: () => ({ + username: 'testuser', + orgs: [{ path: 'testorg' }] + }) +})) + +vi.mock('../../../packs/useFetchApi', () => ({ + default: () => ({ + post: () => ({ + json: () => + Promise.resolve({ + data: { value: { data: { path: 'testuser/testcode' } } }, + error: { value: null } + }) + }) + }) +})) + +describe('NewCode', () => { + describe('mount', async () => { + it('mounts correctly', () => { + const wrapper = createWrapper() + expect(wrapper.exists()).toBe(true) + }) + }) + + describe('form validation', () => { + it('validates required fields', async () => { + const wrapper = createWrapper() + await triggerFormButton(wrapper) + const formErrors = wrapper.findAll('.el-form-item__error') + expect(formErrors.length).toBeGreaterThan(0) + }) + + it('validates code name length', async () => { + const wrapper = createWrapper() + wrapper.vm.dataForm.name = 'a' // Invalid length + await triggerFormButton(wrapper) + expect(wrapper.find('.el-form-item__error').exists()).toBe(true) + + wrapper.vm.dataForm.name = 'valid-code' // Valid length + await triggerFormButton(wrapper) + expect(wrapper.find('.el-form-item__error').exists()).toBe(false) + }) + + it('validates owner selection', async () => { + const wrapper = createWrapper() + wrapper.vm.dataForm.owner = '' // Invalid owner + await triggerFormButton(wrapper) + expect(wrapper.find('.el-form-item__error').exists()).toBe(true) + }) + }) + + describe('form submission', async () => { + it('shows success message on successful submission', async () => { + const wrapper = createWrapper() + + wrapper.vm.dataForm = { + owner: 'testuser', + name: 'valid-code', + license: 'MIT', + desc: 'Test description', + visibility: 'public' + } + + await triggerFormButton(wrapper) + await new Promise((resolve) => setTimeout(resolve, 300)) + expect(window.location.href).toBe('/codes/testuser/testcode') + }) + }) +})