diff --git a/frontend/src/components/__tests__/organizations/NewOrganization.spec.js b/frontend/src/components/__tests__/organizations/NewOrganization.spec.js new file mode 100644 index 000000000..75fd95606 --- /dev/null +++ b/frontend/src/components/__tests__/organizations/NewOrganization.spec.js @@ -0,0 +1,79 @@ +import { describe, it, expect, vi } from 'vitest' +import { mount } from '@vue/test-utils' +import NewOrganization from '@/components/organizations/NewOrganization.vue' + +const createWrapper = (props) => { + return mount(NewOrganization, { + global: { + provide: { + nameRule: /^[a-zA-Z][a-zA-Z0-9-_.]*[a-zA-Z0-9]$/ + } + }, + props: { + ...props + } + }) +} + +const triggerFormButton = (wrapper) => { + const button = wrapper.findComponent({ name: 'CsgButton' }) + button.trigger('click') + // here in the true component button click will trigger an async request and will take some time + // but the test code will not wait for the async function end and will go to next step to do the check + // if we do not wait some time here, the test will failed + return new Promise((resolve) => { setTimeout(resolve, 1000) }) +} + +vi.mock('../../../stores/UserStore', () => ({ + default: () => ({ + username: 'testuser', + orgs: [{ path: 'testorg' }] + }) +})) + +vi.mock('@/packs/useFetchApi', () => ({ + default: () => ({ + post: () => ({ + json: () => + Promise.resolve({ + data: { value: { data: { name: 'testorg' } } }, + error: { value: null } + }) + }) + }) +})) + +describe('NewOrganization', () => { + 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) + }) + }) + + describe('form submission', () => { + it('shows success message on successful submission', async () => { + const wrapper = createWrapper() + wrapper.vm.dataForm = { + homepage:'https://test.com"', + logo:'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/d85a3db4-dd51-47a7-919c-2308c7ff4b6b', + owner: 'testuser', + name: 'testorg', + nickname: 'valid-org', + org_type: '企业', + } + await wrapper.vm.$nextTick() + await triggerFormButton(wrapper) + expect(window.location.href).toBe('/organizations/testorg') + }) + }) +}) diff --git a/frontend/src/components/__tests__/organizations/OrganizationDetail.spec.js b/frontend/src/components/__tests__/organizations/OrganizationDetail.spec.js new file mode 100644 index 000000000..bbde819ad --- /dev/null +++ b/frontend/src/components/__tests__/organizations/OrganizationDetail.spec.js @@ -0,0 +1,118 @@ +import { describe, it, expect, vi } from 'vitest' +import { mount } from '@vue/test-utils' +import OrganizationDetail from '@/components/organizations/OrganizationDetail.vue' + +const createWrapper = (props) => { + return mount(OrganizationDetail, { + global: { + provide: { + verified: false + } + }, + props: { + name: 'testorg', + ...props + } + }) +} + +vi.mock('../../../stores/UserStore', () => ({ + default: () => ({ + username: 'testuser', + orgs: [{ path: 'testorg' }] + }) +})) + +vi.mock('@/packs/useFetchApi', () => ({ + default: (url) => ({ + json: () => { + console.log(url) + if (url === '/organization/testorg') { + return Promise.resolve({ + data: { + value: { + data: { + path: 'testorg', + name: 'testorg', + homepage: 'https://baiud.com', + logo: 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/072d3ec8-c5c1-4e36-b268-05fd2a6747ee', + org_type: '社区组织', + verified: false + } + } + }, + error: { value: null } + }) + } + if (url === '/organization/testorg/members') { + return Promise.resolve({ + data: { + value: { + data: { + data: [ + { + username: 'testuser', + nickname: 'testuser', + uuid: '75496af6-3004-4e96-ad7e-07ff999b40fc', + avatar: + 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/comment/10fe27da-4ebe-4713-aa7d-2daafdf9851c', + role: 'admin', + last_login_at: '2024-12-30 02:55:43' + } + ], + total: 1 + } + } + }, + error: { value: null } + }) + } + if (url === '/organization/testorg/members/testuser') { + return Promise.resolve({ + data: { + value: { + data: 'admin' + } + }, + error: { value: null } + }) + } + return Promise.resolve({ + data: { value: { data: null } }, + error: { value: null } + }) + } + }) +})) + +describe('OrganizationDetail', () => { + describe('mount', () => { + it('mounts correctly', async () => { + const wrapper = createWrapper() + expect(wrapper.exists()).toBe(true) + await wrapper.vm.$nextTick() + expect(wrapper.vm.organizationData).toEqual( + expect.objectContaining({ + name: 'testorg', + nickname: 'testorg', + verified: false, + avatar: + 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/072d3ec8-c5c1-4e36-b268-05fd2a6747ee' + }) + ) + expect(wrapper.vm.membersList).toEqual([ + { + username: 'testuser', + nickname: 'testuser', + role: 'admin', + last_login_at: '2024-12-30 02:55:43', + uuid: '75496af6-3004-4e96-ad7e-07ff999b40fc', + avatar: + 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/comment/10fe27da-4ebe-4713-aa7d-2daafdf9851c' + } + ]) + await wrapper.vm.currentUserRole() + expect(wrapper.vm.role).toBe('admin') + }) + }) +}) diff --git a/frontend/src/components/__tests__/organizations/OrganizationSettings.spec.js b/frontend/src/components/__tests__/organizations/OrganizationSettings.spec.js new file mode 100644 index 000000000..be4a79278 --- /dev/null +++ b/frontend/src/components/__tests__/organizations/OrganizationSettings.spec.js @@ -0,0 +1,137 @@ +import { describe, it, expect, vi } from 'vitest' +import { mount } from '@vue/test-utils' +import OrganizationSettings from '@/components/organizations/OrganizationSettings.vue' +import OrganizationEdit from '@/components/organizations/OrganizationEdit.vue' +import OrganizationMembers from '@/components/organizations/OrganizationMembers.vue' +import Menu from '@/components/organizations/Menu.vue' + +const createWrapper = (props) => { + return mount(OrganizationSettings, { + global: { + provide: { + verified: false + } + }, + props: { + name: 'testorg', + action: 'edit', + ...props + } + }) +} + +vi.mock('../../../stores/UserStore', () => ({ + default: () => ({ + username: 'testuser', + orgs: [{ path: 'testorg' }] + }) +})) + +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 === '/organization/testorg') { + return Promise.resolve({ + data: { + value: { + data: { + path: 'testorg', + name: 'testorg', + homepage: 'https://baiud.com', + logo: 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/072d3ec8-c5c1-4e36-b268-05fd2a6747ee', + org_type: '社区组织', + verified: false + } + } + }, + error: { value: null } + }) + } + if (url === '/organization/testorg/members/testuser') { + return Promise.resolve({ + data: { + value: { + data: 'admin' + } + }, + error: { value: null } + }) + } + return Promise.resolve({ + data: { value: null }, + error: { value: null } + }) + } + }) +})) + +describe('OrganizationSettings', () => { + describe('mount', async () => { + it('mounts correctly', async () => { + const wrapper = createWrapper() + expect(wrapper.exists()).toBe(true) + await wrapper.vm.$nextTick() + expect(wrapper.vm.organization).toEqual( + expect.objectContaining({ + name: 'testorg', + nickname: 'testorg', + homepage: 'https://baiud.com', + logo: 'https://opencsg-test.oss-cn-beijing.aliyuncs.com/org_logo/072d3ec8-c5c1-4e36-b268-05fd2a6747ee', + org_type: '社区组织', + verified: false + }) + ) + await wrapper.vm.currentUserRole() + expect(wrapper.vm.role).toBe('admin') + }) + it('renders Menu component', () => { + const wrapper = createWrapper() + const menu = wrapper.findComponent(Menu) + expect(menu.exists()).toBe(true) + }) + it('renders OrganizationEdit when action is edit', () => { + const wrapper = createWrapper() + expect(wrapper.findComponent(OrganizationEdit).exists()).toBe(true) + }) + + it('does not render OrganizationMembers when action is not members', () => { + const wrapper = createWrapper() + expect(wrapper.findComponent(OrganizationMembers).exists()).toBe(false) + }) + }) +}) diff --git a/frontend/src/components/organizations/OrganizationDetail.vue b/frontend/src/components/organizations/OrganizationDetail.vue index ce662fa8e..aa9f0e16f 100644 --- a/frontend/src/components/organizations/OrganizationDetail.vue +++ b/frontend/src/components/organizations/OrganizationDetail.vue @@ -109,7 +109,6 @@ import { ref, onMounted, watch } from 'vue' import InviteMember from './InviteMember.vue' import ProfileRepoList from '../shared/ProfileRepoList.vue' - import { useCookies } from 'vue3-cookies' import useFetchApi from '../../packs/useFetchApi' import { ElMessage } from 'element-plus' import useUserStore from '../../stores/UserStore' @@ -126,8 +125,6 @@ }) const membersList = ref([]) - const { cookies } = useCookies() - const userStore = useUserStore() const role = ref('')