import { createTestingPinia } from '@pinia/testing'; import userEvent from '@testing-library/user-event'; import { createComponentRenderer } from '@/__tests__/render'; import { createTestWorkflow } from '@/__tests__/mocks'; import { createProjectListItem } from '@/__tests__/data/projects'; import { getDropdownItems, mockedStore } from '@/__tests__/utils'; import type { MockedStore } from '@/__tests__/utils'; import { PROJECT_MOVE_RESOURCE_MODAL } from '@/constants'; import ProjectMoveResourceModal from '@/components/Projects/ProjectMoveResourceModal.vue'; import { useTelemetry } from '@/composables/useTelemetry'; import { useProjectsStore } from '@/stores/projects.store'; import { useWorkflowsStore } from '@/stores/workflows.store'; import { useCredentialsStore } from '@/stores/credentials.store'; const renderComponent = createComponentRenderer(ProjectMoveResourceModal, { pinia: createTestingPinia(), global: { stubs: { Modal: { template: '
', }, }, }, }); let telemetry: ReturnType; let projectsStore: MockedStore; let workflowsStore: MockedStore; let credentialsStore: MockedStore; describe('ProjectMoveResourceModal', () => { beforeEach(() => { vi.clearAllMocks(); telemetry = useTelemetry(); projectsStore = mockedStore(useProjectsStore); workflowsStore = mockedStore(useWorkflowsStore); credentialsStore = mockedStore(useCredentialsStore); }); it('should send telemetry when mounted', async () => { const telemetryTrackSpy = vi.spyOn(telemetry, 'track'); projectsStore.availableProjects = [createProjectListItem()]; workflowsStore.fetchWorkflow.mockResolvedValueOnce(createTestWorkflow()); const props = { modalName: PROJECT_MOVE_RESOURCE_MODAL, data: { resourceType: 'workflow', resourceTypeLabel: 'workflow', resource: { id: '1', homeProject: { id: '2', name: 'My Project', }, }, }, }; renderComponent({ props }); expect(telemetryTrackSpy).toHaveBeenCalledWith( 'User clicked to move a workflow', expect.objectContaining({ workflow_id: '1' }), ); }); it('should show no available projects message', async () => { projectsStore.availableProjects = []; workflowsStore.fetchWorkflow.mockResolvedValueOnce(createTestWorkflow()); const props = { modalName: PROJECT_MOVE_RESOURCE_MODAL, data: { resourceType: 'workflow', resourceTypeLabel: 'workflow', resource: { id: '1', homeProject: { id: '2', name: 'My Project', }, }, }, }; const { getByText } = renderComponent({ props }); expect(getByText(/Currently there are not any projects or users available/)).toBeVisible(); }); it('should not hide project select if filter has no result', async () => { const projects = Array.from({ length: 5 }, createProjectListItem); projectsStore.availableProjects = projects; const props = { modalName: PROJECT_MOVE_RESOURCE_MODAL, data: { resourceType: 'workflow', resourceTypeLabel: 'Workflow', resource: { id: '1', homeProject: { id: projects[0].id, name: projects[0].name, }, }, }, }; const { getByTestId, getByRole } = renderComponent({ props }); const projectSelect = getByTestId('project-move-resource-modal-select'); const projectSelectInput: HTMLInputElement = getByRole('combobox'); expect(projectSelectInput).toBeVisible(); expect(projectSelect).toBeVisible(); const projectSelectDropdownItems = await getDropdownItems(projectSelect); expect(projectSelectDropdownItems).toHaveLength(projects.length - 1); await userEvent.click(projectSelectInput); await userEvent.type(projectSelectInput, 'non-existing project'); expect(projectSelect).toBeVisible(); }); it('should not load workflow if the resource is a credential', async () => { const telemetryTrackSpy = vi.spyOn(telemetry, 'track'); projectsStore.availableProjects = [createProjectListItem()]; const props = { modalName: PROJECT_MOVE_RESOURCE_MODAL, data: { resourceType: 'credential', resourceTypeLabel: 'credential', resource: { id: '1', homeProject: { id: '2', name: 'My Project', }, }, }, }; const { getByText } = renderComponent({ props }); expect(telemetryTrackSpy).toHaveBeenCalledWith( 'User clicked to move a credential', expect.objectContaining({ credential_id: '1' }), ); expect(workflowsStore.fetchWorkflow).not.toHaveBeenCalled(); expect(getByText(/Moving will remove any existing sharing for this credential/)).toBeVisible(); }); it('should send credential IDs when workflow moved with used credentials and checkbox checked', async () => { const destinationProject = createProjectListItem(); const currentProjectId = '123'; const movedWorkflow = { ...createTestWorkflow(), usedCredentials: [ { id: '1', name: 'PG Credential', credentialType: 'postgres', currentUserHasAccess: true, }, { id: '2', name: 'Notion Credential', credentialType: 'notion', currentUserHasAccess: true, }, ], }; projectsStore.currentProjectId = currentProjectId; projectsStore.availableProjects = [destinationProject]; workflowsStore.fetchWorkflow.mockResolvedValueOnce(movedWorkflow); credentialsStore.fetchAllCredentials.mockResolvedValueOnce([ { id: '1', name: 'PG Credential', createdAt: '2021-01-01T00:00:00Z', updatedAt: '2021-01-01T00:00:00Z', type: 'postgres', scopes: ['credential:share'], isManaged: false, }, { id: '2', name: 'Notion Credential', createdAt: '2021-01-01T00:00:00Z', updatedAt: '2021-01-01T00:00:00Z', type: 'notion', scopes: ['credential:share'], isManaged: false, }, { id: '3', name: 'Another Credential', createdAt: '2021-01-01T00:00:00Z', updatedAt: '2021-01-01T00:00:00Z', type: 'another', scopes: ['credential:share'], isManaged: false, }, ]); const props = { modalName: PROJECT_MOVE_RESOURCE_MODAL, data: { resourceType: 'workflow', resourceTypeLabel: 'workflow', resource: movedWorkflow, }, }; const { getByTestId, getByText } = renderComponent({ props }); expect(getByTestId('project-move-resource-modal-button')).toBeDisabled(); expect(getByText(/Moving will remove any existing sharing for this workflow/)).toBeVisible(); const projectSelect = getByTestId('project-move-resource-modal-select'); expect(projectSelect).toBeVisible(); const projectSelectDropdownItems = await getDropdownItems(projectSelect); await userEvent.click(projectSelectDropdownItems[0]); expect(getByTestId('project-move-resource-modal-button')).toBeEnabled(); await userEvent.click(getByTestId('project-move-resource-modal-checkbox-all')); await userEvent.click(getByTestId('project-move-resource-modal-button')); expect(projectsStore.moveResourceToProject).toHaveBeenCalledWith( 'workflow', movedWorkflow.id, destinationProject.id, ['1', '2'], ); }); });