Files
vikunja/frontend/tests/e2e/project/project.spec.ts

154 lines
6.2 KiB
TypeScript

import {test, expect} from '../../support/fixtures'
import {TaskFactory} from '../../factories/task'
import {ProjectFactory} from '../../factories/project'
import {createProjects} from './prepareProjects'
test.describe('Projects', () => {
test.use({
// Use authenticated page for all tests
})
let projects: any[]
test.beforeEach(async ({authenticatedPage}) => {
projects = await createProjects()
})
test('Should create a new project', async ({authenticatedPage: page}) => {
await page.goto('/projects')
await page.waitForLoadState('networkidle')
await page.locator('.action-buttons').getByRole('link', {name: /project/i}).click()
await expect(page).toHaveURL(/\/projects\/new/)
await expect(page.locator('.card-header-title')).toContainText('New project')
await page.locator('input[name=projectTitle]').fill('New Project')
await page.locator('.button').filter({hasText: 'Create'}).click()
await expect(page.locator('.global-notification', {timeout: 1000})).toContainText('Success')
await expect(page).toHaveURL(/\/projects\//)
await expect(page.locator('.project-title')).toContainText('New Project')
})
test('Should redirect to a specific project view after visited', async ({authenticatedPage: page}) => {
const projectId = projects[0].id
const kanbanViewId = projects[0].views[3].id
const loadBucketsPromise = page.waitForResponse(response =>
response.url().includes(`/projects/${projectId}/`) &&
response.url().includes('/views/') &&
response.url().includes('/tasks'),
)
await page.goto(`/projects/${projectId}/${kanbanViewId}`)
await expect(page).toHaveURL(new RegExp(`/projects/${projectId}/${kanbanViewId}`))
await loadBucketsPromise
await page.goto(`/projects/${projectId}`)
await expect(page).toHaveURL(new RegExp(`/projects/${projectId}/${kanbanViewId}`))
})
// FIXME: seeding fails with error 500
test('Should rename the project in all places', async ({authenticatedPage: page}) => {
const projectId = projects[0].id
const listViewId = projects[0].views[0].id
await TaskFactory.create(5, {
id: '{increment}',
project_id: projectId,
})
const newProjectName = 'New project name'
// Navigate to project and wait for redirect to view
await page.goto(`/projects/${projectId}/${listViewId}`)
await page.waitForLoadState('networkidle')
await expect(page.locator('.project-title')).toContainText('First Project')
// Click the project title dropdown and select Edit
await page.locator('.project-title-dropdown .project-title-button').click()
await page.getByRole('link', {name: /^edit$/i}).click()
await page.waitForLoadState('networkidle')
// Fill in the new name
await page.locator('input#title').fill(newProjectName)
await page.locator('footer.card-footer .button').filter({hasText: /^Save$/}).click()
await expect(page.locator('.global-notification')).toContainText('Success')
await expect(page.locator('.project-title')).toContainText(newProjectName)
await expect(page.locator('.project-title')).not.toContainText(projects[0].title)
await expect(page.locator('.menu-container .menu-list').getByRole('listitem').filter({hasText: newProjectName})).toBeVisible()
await page.goto('/')
await expect(page.locator('.project-grid')).toContainText(newProjectName)
await expect(page.locator('.project-grid')).not.toContainText(projects[0].title)
})
test('Should remove a project when deleting it', async ({authenticatedPage: page}) => {
const projectId = projects[0].id
const listViewId = projects[0].views[0].id
await page.goto(`/projects/${projectId}/${listViewId}`)
await page.waitForLoadState('networkidle')
await page.locator('.project-title-dropdown .project-title-button').click()
await page.getByRole('link', {name: /^delete$/i}).click()
await page.waitForLoadState('networkidle')
await expect(page).toHaveURL(/\/settings\/delete/)
await page.getByRole('button', {name: /do it/i}).click()
await expect(page.locator('.global-notification')).toContainText('Success')
await expect(page).toHaveURL('/')
await expect(page.getByRole('link', {name: projects[0].title})).not.toBeVisible()
})
test('Should archive a project', async ({authenticatedPage: page}) => {
const projectId = projects[0].id
const listViewId = projects[0].views[0].id
await page.goto(`/projects/${projectId}/${listViewId}`)
await page.waitForLoadState('networkidle')
await page.locator('.project-title-dropdown .project-title-button').click()
await page.getByRole('link', {name: /^archive$/i}).click()
await expect(page.locator('.modal-content')).toContainText('Archive this project')
await page.getByRole('button', {name: /do it/i}).click()
await expect(page.locator('.global-notification')).toContainText('Success')
await expect(page.locator('main.app-content')).toContainText('This project is archived. It is not possible to create new or edit tasks for it.')
})
test('Should show all projects on the projects page', async ({authenticatedPage: page}) => {
const projects = await ProjectFactory.create(10)
await page.goto('/projects')
await page.waitForLoadState('networkidle')
for (const p of projects) {
await expect(page.locator('.project-grid')).toContainText(p.title)
}
})
test('Should not show archived projects if the filter is not checked', async ({authenticatedPage: page}) => {
await ProjectFactory.create(1, {
id: 2,
}, false)
await ProjectFactory.create(1, {
id: 3,
is_archived: true,
}, false)
// Initial
await page.goto('/projects')
await page.waitForLoadState('networkidle')
await expect(page.locator('.project-grid')).not.toContainText('Archived')
// Show archived - click the checkbox label text
await page.getByText('Show Archived').click()
await expect(page.locator('input[type="checkbox"]').first()).toBeChecked()
await expect(page.locator('.project-grid')).toContainText('Archived')
// Don't show archived
await page.getByText('Show Archived').click()
await expect(page.locator('input[type="checkbox"]').first()).not.toBeChecked()
// Second time visiting after unchecking
await page.goto('/projects')
await page.waitForLoadState('networkidle')
await expect(page.locator('input[type="checkbox"]').first()).not.toBeChecked()
await expect(page.locator('.project-grid')).not.toContainText('Archived')
})
})