Files
automatisch/packages/e2e-tests/tests/flow-folders/flow-folder.spec.js
2025-05-03 23:34:13 +02:00

403 lines
14 KiB
JavaScript

const { test, expect } = require('../../fixtures/index');
const { request } = require('@playwright/test');
const {
CreateFolderDialog,
} = require('../../fixtures/folder/create-folder-dialog');
const {
UpdateFolderDialog,
} = require('../../fixtures/folder/update-folder-dialog');
const { MoveFolderDialog } = require('../../fixtures/folder/move-flow-dialog');
const {
DeleteFolderDialog,
} = require('../../fixtures/folder/delete-folder-dialog');
const { getToken } = require('../../helpers/auth-api-helper');
const { addUser, acceptInvitation } = require('../../helpers/user-api-helper');
const { addFolder } = require('../../helpers/folder-api-helper');
const { createFlow, updateFlowName } = require('../../helpers/flow-api-helper');
import Crypto from 'crypto';
test.describe('Folders', () => {
test('owner folder lifecycle', async ({
page,
flowsPage,
flowEditorPage,
}) => {
const createFolderDialog = new CreateFolderDialog(page);
const updateFolderDialog = new UpdateFolderDialog(page);
const folderMoveToDialog = new MoveFolderDialog(page);
const deleteFolderDialog = new DeleteFolderDialog(page);
const flowName = Crypto.randomUUID();
await test.step('new flow should be in uncategorized folder', async () => {
await flowsPage.createFlowButton.click();
await flowEditorPage.flowName.click();
await flowEditorPage.flowNameInput.fill(flowName);
await flowEditorPage.flowStep.first().click();
await flowEditorPage.goBackButton.click();
await expect(page).toHaveURL('/flows');
await flowsPage.searchInput.fill(flowName);
await expect(
flowsPage.flowRow.filter({
hasText: flowName,
})
).toHaveCount(1);
await flowsPage.uncategorizedFlowsFolder.click();
await flowsPage.searchInput.fill(flowName);
await expect(
flowsPage.flowRow.filter({
hasText: flowName,
})
).toHaveCount(1);
});
await test.step('folder name should be at least 1 character long', async () => {
await flowsPage.addNewFolderButton.click();
await createFolderDialog.createButton.click();
await expect(createFolderDialog.errorAlert).toHaveCount(1);
await createFolderDialog.closeDialog.click();
});
await test.step('should be able to add a folder', async () => {
await flowsPage.addNewFolderButton.click();
await createFolderDialog.folderNameInput.fill('newFolder');
await createFolderDialog.createButton.click();
await expect(createFolderDialog.successAlert).toHaveCount(1);
await createFolderDialog.closeDialog.click();
await expect(flowsPage.userFolders.getByText('newFolder')).toHaveCount(1);
await flowsPage.userFolders.getByText('newFolder').click();
await expect(flowsPage.flowRow).toHaveCount(0);
});
await test.step('should be possible to move flow to the new folder', async () => {
await flowsPage.allFlowsFolder.click();
await flowsPage.flowRow
.filter({
hasText: flowName,
})
.getByRole('button')
.click();
await flowsPage.moveTo.click();
await folderMoveToDialog.folderNameAutocomplete.click();
await page.getByRole('option', { name: 'newFolder' }).last().click();
await folderMoveToDialog.moveButton.click();
await expect(folderMoveToDialog.successAlert).toHaveCount(1);
await folderMoveToDialog.closeDialog.click();
});
await test.step('flow should be visible in the new folder and in all flows folder', async () => {
await flowsPage.userFolders.getByText('newFolder').click();
await flowsPage.searchInput.fill(flowName);
await expect(
flowsPage.flowRow.filter({
hasText: flowName,
})
).toHaveCount(1);
await flowsPage.flowRow
.filter({
hasText: flowName,
})
.click();
await expect(page).toHaveURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
await expect(flowEditorPage.folderName).toContainText('newFolder');
await flowEditorPage.goBackButton.click();
await flowsPage.allFlowsFolder.click();
await flowsPage.searchInput.fill(flowName);
await expect(
flowsPage.flowRow.filter({
hasText: flowName,
})
).toHaveCount(1);
await flowsPage.uncategorizedFlowsFolder.click();
await flowsPage.searchInput.fill(flowName);
await expect(
flowsPage.flowRow.filter({
hasText: flowName,
})
).toHaveCount(0);
});
await test.step('should be able to update a folder', async () => {
await expect(
flowsPage.userFolders.getByText('updatedFolderName')
).toHaveCount(0);
await flowsPage.userFolders.getByText('newFolder').first().click();
await flowsPage.editFolder.click();
await updateFolderDialog.folderNameInput.fill('updatedFolderName');
await Promise.all([
page.waitForResponse(
(resp) => /(\/folders\/.*)/.test(resp.url()) && resp.status() === 200
),
updateFolderDialog.updateButton.click(),
expect(updateFolderDialog.successAlert).toHaveCount(1),
]);
await updateFolderDialog.closeDialog.click();
await expect(
flowsPage.userFolders.getByText('updatedFolderName')
).toHaveCount(1);
await flowsPage.flowRow
.filter({
hasText: flowName,
})
.click();
await expect(page).toHaveURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
await expect(flowEditorPage.folderName).toContainText(
'updatedFolderName'
);
await flowEditorPage.goBackButton.click();
});
await test.step('should be able to delete a folder with a flow', async () => {
await expect(
flowsPage.userFolders.getByText('updatedFolderName')
).toHaveCount(1);
await flowsPage.deleteFolder.click();
await deleteFolderDialog.cancelButton.click();
await flowsPage.deleteFolder.click();
await Promise.all([
page.waitForResponse(
(resp) => /(\/folders\/.*)/.test(resp.url()) && resp.status() === 204
),
deleteFolderDialog.deleteButton.click(),
expect(
flowsPage.userFolders.getByText('updatedFolderName')
).toHaveCount(0),
expect(flowsPage.deleteFolderSuccessAlert).toHaveCount(1),
]);
await flowsPage.flowRow
.filter({
hasText: flowName,
})
.click();
await expect(page).toHaveURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
await expect(flowEditorPage.folderName).toContainText('Uncategorized');
await flowEditorPage.goBackButton.click();
});
});
// removal of the empty folder is buggy
test.skip('should be able to delete empty folder', async ({
page,
flowsPage,
flowEditorPage,
}) => {
// add flow
await flowsPage.createFlowButton.click();
await flowEditorPage.flowName.click();
await flowEditorPage.flowNameInput.fill('deleteFlow');
await flowEditorPage.flowStep.first().click();
await flowEditorPage.goBackButton.click();
await expect(page).toHaveURL('/flows');
// add folder
await flowsPage.addNewFolderButton.click();
await createFolderDialog.folderNameInput.fill('deleteFolder');
await createFolderDialog.createButton.click();
await expect(createFolderDialog.successAlert).toContainText(
'The folder has been successfully created!'
);
await createFolderDialog.closeDialog.click();
await expect(flowsPage.userFolders.getByText('deleteFolder')).toHaveCount(
1
);
await flowsPage.userFolders.getByText('deleteFolder').click();
// move flow
await flowsPage.allFlowsFolder.click();
await flowsPage.flowRow
.filter({
hasText: 'deleteFlow',
})
.getByRole('button')
.click();
await flowsPage.moveTo.click();
await folderMoveToDialog.folderNameAutocomplete.click();
await page.getByRole('option', { name: 'deleteFolder' }).last().click();
await folderMoveToDialog.moveButton.click();
await expect(folderMoveToDialog.successAlert).toHaveCount(1);
await folderMoveToDialog.closeDialog.click();
// remove flow
await flowsPage.allFlowsFolder.click();
await flowsPage.flowRow
.filter({
hasText: 'deleteFlow',
})
.getByRole('button')
.click();
await flowsPage.delete.click();
// remove folder
await flowsPage.userFolders.getByText('deleteFolder').click();
await flowsPage.deleteFolder.click();
await deleteFolderDialog.deleteButton.click();
await expect(flowsPage.userFolders.getByText('deleteFolder')).toHaveCount(
0
);
await expect(flowsPage.deleteFolderSuccessAlert).toHaveCount(1);
});
// folder name is not correct (still uncategorized)
test.skip('should be possible to add flow in the new folder', async ({
flowsPage,
flowEditorPage,
}) => {
await expect(flowsPage.userFolders.getByText('newFolder')).toHaveCount(1);
await flowsPage.userFolders.getByText('newFolder').click();
await flowsPage.createFlowButton.click();
await expect(flowEditorPage.folderName).toContainText('newFolder');
});
test('should be able to add a folder with the same name', async ({
flowsPage,
page,
}) => {
const createFolderDialog = new CreateFolderDialog(page);
await flowsPage.addNewFolderButton.click();
await createFolderDialog.folderNameInput.fill('sameNameFolder');
await createFolderDialog.createButton.click();
await expect(createFolderDialog.successAlert).toHaveCount(1);
await createFolderDialog.closeDialog.click();
await expect(flowsPage.userFolders.getByText('sameNameFolder')).toHaveCount(
1
);
await flowsPage.addNewFolderButton.click();
await createFolderDialog.folderNameInput.fill('sameNameFolder');
await createFolderDialog.createButton.click();
await expect(createFolderDialog.successAlert).toHaveCount(1);
await createFolderDialog.closeDialog.click();
await expect(flowsPage.userFolders.getByText('sameNameFolder')).toHaveCount(
2
);
});
test('non-owner folder visibility', async ({
page,
flowsPage,
flowEditorPage,
adminCreateUserPage,
}) => {
const apiRequest = await request.newContext();
const tokenJsonResponse = await getToken(apiRequest);
let userTokenJsonResponse;
let flowId;
await test.step('add another user', async () => {
adminCreateUserPage.seed(
Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)
);
const testUser = adminCreateUserPage.generateUser();
const addUserResponse = await addUser(
apiRequest,
tokenJsonResponse.data.token,
{
fullName: testUser.fullName,
email: testUser.email,
}
);
const acceptToken =
addUserResponse.data.acceptInvitationUrl.split('=')[1];
await acceptInvitation(apiRequest, {
token: acceptToken,
password: 'alamakota',
});
userTokenJsonResponse = await getToken(
apiRequest,
testUser.email,
'alamakota'
);
});
await test.step('add folder as an another user', async () => {
await addFolder(
apiRequest,
userTokenJsonResponse.data.token,
'anotherUserFolder'
);
});
await test.step('add folder as a main user', async () => {
await addFolder(
apiRequest,
tokenJsonResponse.data.token,
'mainUserFolder'
);
});
await test.step('add flow as an another user', async () => {
const flow = await createFlow(
apiRequest,
userTokenJsonResponse.data.token
);
flowId = flow.data.id;
await updateFlowName(
apiRequest,
userTokenJsonResponse.data.token,
flowId
);
await page.reload();
});
await test.step('should not see folders of different user on the list', async () => {
await expect(
flowsPage.userFolders.getByText('anotherUserFolder')
).toHaveCount(0);
});
await test.step('should not see folders of different user in the flow details', async () => {
await flowsPage.flowRow
.filter({
hasText: flowId,
})
.click();
await expect(page).toHaveURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
await expect(flowEditorPage.folderName).toContainText('Uncategorized');
await flowEditorPage.goBackButton.click();
});
await test.step("another user's flow should be uncategorized and in all flows folder", async () => {
await flowsPage.allFlowsFolder.click();
await flowsPage.searchInput.fill(flowId);
await expect(
flowsPage.flowRow.filter({
hasText: flowId,
})
).toHaveCount(1);
await flowsPage.uncategorizedFlowsFolder.click();
await flowsPage.searchInput.fill(flowId);
await expect(
flowsPage.flowRow.filter({
hasText: flowId,
})
).toHaveCount(1);
await flowsPage.userFolders.getByText('mainUserFolder').click();
await flowsPage.searchInput.fill(flowId);
await expect(
flowsPage.flowRow.filter({
hasText: flowId,
})
).toHaveCount(0);
});
});
test.skip('non-owner should not reassing folder of different user', async ({
page,
}) => {
// TODO feature is wip https://github.com/automatisch/automatisch/pull/2420
});
});