diff --git a/qms-tests/create-local.sh b/qms-tests/create-local.sh index 52006c07bb..664e455238 100755 --- a/qms-tests/create-local.sh +++ b/qms-tests/create-local.sh @@ -11,6 +11,9 @@ # Create second user record in accounts ./tool-local.sh create-account user2 -f Kainin -l Dirak -p 1234 ./tool-local.sh confirm-email user2 +# Create third user record in accounts +./tool-local.sh create-account user3 -f Cain -l Velasquez -p 1234 +./tool-local.sh confirm-email user3 ./tool-local.sh create-account user_qara -f Qara -l Admin -p 1234 ./tool-local.sh confirm-email user_qara \ No newline at end of file diff --git a/qms-tests/prepare.sh b/qms-tests/prepare.sh index ac9d064b81..a7af9f1865 100755 --- a/qms-tests/prepare.sh +++ b/qms-tests/prepare.sh @@ -27,11 +27,15 @@ fi # Create user record in accounts ./tool.sh create-account user1 -f John -l Appleseed -p 1234 ./tool.sh create-account user2 -f Kainin -l Dirak -p 1234 +./tool.sh create-account user3 -f Cain -l Velasquez -p 1234 + ./tool.sh assign-workspace user1 sanity-ws-qms ./tool.sh assign-workspace user2 sanity-ws-qms +./tool.sh assign-workspace user3 sanity-ws-qms # Make user the workspace maintainer ./tool.sh confirm-email user1 ./tool.sh confirm-email user2 +./tool.sh confirm-email user3 ./tool.sh create-account user_qara -f Qara -l Admin -p 1234 ./tool.sh assign-workspace user_qara sanity-ws-qms diff --git a/qms-tests/restore-local.sh b/qms-tests/restore-local.sh index 432daedbb9..1f97f037b5 100755 --- a/qms-tests/restore-local.sh +++ b/qms-tests/restore-local.sh @@ -14,6 +14,8 @@ export SERVER_SECRET=secret # Re-assign user to workspace. ./tool-local.sh assign-workspace user1 sanity-ws-qms ./tool-local.sh assign-workspace user2 sanity-ws-qms +./tool-local.sh assign-workspace user3 sanity-ws-qms + ./tool-local.sh assign-workspace user_qara sanity-ws-qms ./tool-local.sh set-user-role user1 sanity-ws-qms OWNER ./tool-local.sh set-user-role user2 sanity-ws-qms OWNER diff --git a/qms-tests/restore-workspace.sh b/qms-tests/restore-workspace.sh index 6bc008a0d8..509da438f1 100755 --- a/qms-tests/restore-workspace.sh +++ b/qms-tests/restore-workspace.sh @@ -8,7 +8,10 @@ # Re-assign user to workspace. ./tool.sh assign-workspace user1 sanity-ws-qms ./tool.sh assign-workspace user2 sanity-ws-qms +./tool.sh assign-workspace user3 sanity-ws-qms + +./tool.sh set-user-role user2 sanity-ws-qms OWNER ./tool.sh assign-workspace user_qara sanity-ws-qms ./tool.sh configure sanity-ws-qms --enable=* -./tool.sh configure sanity-ws-qms --list +./tool.sh configure sanity-ws-qms --list \ No newline at end of file diff --git a/qms-tests/sanity/.env b/qms-tests/sanity/.env index 6666334b84..c35d538294 100644 --- a/qms-tests/sanity/.env +++ b/qms-tests/sanity/.env @@ -2,8 +2,10 @@ PLATFORM_URI='http://localhost:8083' PLATFORM_TRANSACTOR='ws://localhost:3334' PLATFORM_USER='user1' PLATFORM_USER_SECOND='user2' +REGULAR_USER='user3' PLATFORM_TOKEN='eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjb25maXJtZWQiOnRydWUsImVtYWlsIjoidXNlcjEiLCJ3b3Jrc3BhY2UiOiJzYW5pdHktd3MtcW1zIiwicHJvZHVjdElkIjoiIn0.vQK1jI8gHkjnNJf5XZ71L4dCqyHNmKW4_iBGrhXrqW8' SETTING=storage.json SETTING_SECOND=storageSecond.json +SETTING_THIRD=storageThird.json SETTING_QARA_MANAGER=storageQaraManager.json PLATFORM_PASSWORD='1234' \ No newline at end of file diff --git a/qms-tests/sanity/storageThird-dev.json b/qms-tests/sanity/storageThird-dev.json new file mode 100644 index 0000000000..53c2cd2c93 --- /dev/null +++ b/qms-tests/sanity/storageThird-dev.json @@ -0,0 +1,34 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:8080", + "localStorage": [ + { + "name": "login:metadata:LoginEmail", + "value": "user3" + }, + { + "name": "login:metadata:LoginTokens", + "value": "{\"sanity-ws-qms\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjb25maXJtZWQiOnRydWUsImVtYWlsIjoidXNlcjMiLCJ3b3Jrc3BhY2UiOiJzYW5pdHktd3MtcW1zIiwicHJvZHVjdElkIjoiIn0.ylvF9znBgI9iQpHSR6GKvhI5yHDE9m8jB4eUPWuwuKk\"}" + }, + { + "name": "login:metadata:LoginEndpoint", + "value": "ws://localhost:3334" + }, + { + "name": "#platform.notification.logging", + "value": "false" + }, + { + "name": "#platform.lazy.loading", + "value": "false" + }, + { + "name": "flagOpenInDesktopApp", + "value": "true" + } + ] + } + ] + } \ No newline at end of file diff --git a/qms-tests/sanity/storageThird.json b/qms-tests/sanity/storageThird.json new file mode 100644 index 0000000000..ef4af3ee2c --- /dev/null +++ b/qms-tests/sanity/storageThird.json @@ -0,0 +1,34 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:8083", + "localStorage": [ + { + "name": "login:metadata:LoginEmail", + "value": "user3" + }, + { + "name": "login:metadata:LoginTokens", + "value": "{\"sanity-ws-qms\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjb25maXJtZWQiOnRydWUsImVtYWlsIjoidXNlcjMiLCJ3b3Jrc3BhY2UiOiJzYW5pdHktd3MtcW1zIiwicHJvZHVjdElkIjoiIn0.ylvF9znBgI9iQpHSR6GKvhI5yHDE9m8jB4eUPWuwuKk\"}" + }, + { + "name": "login:metadata:LoginEndpoint", + "value": "ws://localhost:3334" + }, + { + "name": "#platform.notification.logging", + "value": "false" + }, + { + "name": "#platform.lazy.loading", + "value": "false" + }, + { + "name": "flagOpenInDesktopApp", + "value": "true" + } + ] + } + ] + } \ No newline at end of file diff --git a/qms-tests/sanity/tests/documents/REQ-05-1.spec.ts b/qms-tests/sanity/tests/documents/REQ-05-1.spec.ts new file mode 100644 index 0000000000..1ab98743ab --- /dev/null +++ b/qms-tests/sanity/tests/documents/REQ-05-1.spec.ts @@ -0,0 +1,208 @@ +import { test } from '@playwright/test' +import { + attachScreenshot, + DocumentURI, + generateId, + getSecondPage, + HomepageURI, + PlatformSetting, + PlatformURI +} from '../utils' +import { allure } from 'allure-playwright' +import { DocumentContentPage } from '../model/documents/document-content-page' +import { LeftSideMenuPage } from '../model/left-side-menu-page' + +import { faker } from '@faker-js/faker' +import { createTemplateStep, prepareDocumentStep } from './common-documents-steps' +import { DocumentRights, DocumentStatus, NewDocument, NewTemplate } from '../model/types' +import { DocumentsPage } from '../model/documents/documents-page' + +test.use({ + storageState: PlatformSetting +}) + +test.describe('ISO 13485, 4.2.4 Control of documents', () => { + test.beforeEach(async ({ page }) => { + await (await page.goto(`${PlatformURI}/${HomepageURI}`))?.finished() + }) + + test.afterEach(async ({ browser }) => { + const contexts = browser.contexts() + for (const context of contexts) { + await context.close() + } + }) + + test('TESTS-382. Create new a new Effective Template with category External', async ({ page }) => { + await allure.description('Requirement\nUsers need to create a new template') + await allure.tms('TESTS-382', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-382') + + const leftSideMenuPage = new LeftSideMenuPage(page) + const category = faker.word.words(2) + const description = faker.lorem.sentence(1) + const code = faker.word.words(2) + const title = faker.word.words(2) + + const newTemplate: NewTemplate = { + location: { + space: 'Quality documents', + parent: 'Quality documents' + }, + title, + description, + code, + category, + reason: 'Test reason', + reviewers: ['Appleseed John'], + approvers: ['Appleseed John'] + } + + await leftSideMenuPage.clickButtonOnTheLeft('Documents') + await test.step('2. Create a new category', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.selectControlDocumentSubcategory('Categories') + await documentContentPage.clickOnAddCategoryButton() + await documentContentPage.fillCategoryForm(category, description, code) + await documentContentPage.expectCategoryCreated(category, code) + }) + await test.step('3. Create a new template', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.clickNewDocumentArrow() + await documentContentPage.clickNewTemplate() + await createTemplateStep(page, title, description, category, 'Quality documents') + }) + await test.step('4. Check document information', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.checkDocumentTitle(newTemplate.title) + await documentContentPage.checkDocument({ + type: 'N/A', + category: newTemplate.category ?? '', + version: 'v0.1', + status: DocumentStatus.DRAFT, + owner: 'Appleseed John', + author: 'Appleseed John' + }) + }) + await test.step('5. Check if templates exists in template category', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.selectControlDocumentSubcategory('Templates') + await documentContentPage.chooseFilter(code) + await documentContentPage.checkIfFilterIsApplied(title) + }) + await attachScreenshot('TESTS-382_Template_created.png', page) + }) + + test('TESTS-338. Negative: as a space Member only, I cannot be assigned as an approver to any document of this space', async ({ + page + }) => { + await allure.description( + 'Requirement\nUser is a space member and cannot be assigned as an approver to any document of this space' + ) + await allure.tms('TESTS-338', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-338') + const completeDocument: NewDocument = { + template: 'HR (HR)', + title: `Complete document-${generateId()}`, + description: `Complete document description-${generateId()}` + } + const leftSideMenuPage = new LeftSideMenuPage(page) + + await leftSideMenuPage.clickButtonOnTheLeft('Documents') + await test.step('2. Add a member to space', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.addMemberToQualityDocument() + }) + await test.step('3. Check if the member exists in approve list', async () => { + await prepareDocumentStep(page, completeDocument) + + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.clickSendForApproval() + await documentContentPage.clickAddMember() + await documentContentPage.checkIfMemberDropdownHasMember('Cain Velasquez', false) + }) + await attachScreenshot('TESTS-338_Member_not_in_the_list.png', page) + }) + + test('TESTS-383. Authorized User can search a doc per category ', async ({ browser, page }) => { + await allure.description('Requirement\nUsers need to create a new category') + await allure.tms('TESTS-383', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-383') + const userSecondPage = await getSecondPage(browser) + + const title = faker.word.words(2) + const description = faker.lorem.sentence(1) + const code = faker.word.words(2) + const leftSideMenuPage = new LeftSideMenuPage(page) + + await leftSideMenuPage.clickButtonOnTheLeft('Documents') + const category = faker.word.words(2) + const newTemplate: NewTemplate = { + location: { + space: 'Quality documents', + parent: 'Quality documents' + }, + title, + description, + code, + category, + reason: 'Test reason', + reviewers: ['Appleseed John'], + approvers: ['Appleseed John'] + } + const reviewer = 'Dirak Kainin' + await leftSideMenuPage.clickButtonOnTheLeft('Documents') + + await test.step('2. Create a new category', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.selectControlDocumentSubcategory('Categories') + await documentContentPage.clickOnAddCategoryButton() + await documentContentPage.fillCategoryForm(category, description, code) + await documentContentPage.expectCategoryCreated(category, code) + }) + await test.step('3. Create a new template', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.clickNewDocumentArrow() + await documentContentPage.clickNewTemplate() + await createTemplateStep(page, title, description, category, 'Quality documents') + }) + await test.step('4. Send for Approval', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.buttonSendForApproval.click() + await documentContentPage.fillSelectApproversForm([reviewer]) + await documentContentPage.checkDocumentStatus(DocumentStatus.IN_APPROVAL) + await documentContentPage.checkCurrentRights(DocumentRights.VIEWING) + await documentContentPage.confirmApproval() + }) + + await test.step('5. Approve document', async () => { + const documentsPageSecond = new DocumentsPage(userSecondPage) + await (await userSecondPage.goto(`${PlatformURI}/${DocumentURI}`))?.finished() + await documentsPageSecond.openDocument(title) + + const documentContentPageSecond = new DocumentContentPage(userSecondPage) + await documentContentPageSecond.confirmApproval() + + await documentContentPageSecond.checkDocumentStatus(DocumentStatus.EFFECTIVE) + await documentContentPageSecond.checkCurrentRights(DocumentRights.VIEWING) + + await test.step('6. Check document information', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.checkDocumentTitle(newTemplate.title) + await documentContentPage.checkDocument({ + type: 'N/A', + category: newTemplate.category ?? '', + version: 'v0.1', + status: DocumentStatus.EFFECTIVE, + owner: 'Appleseed John', + author: 'Appleseed John' + }) + }) + await test.step('7. Check if templates exists in template category', async () => { + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.selectControlDocumentSubcategory('Templates') + await documentContentPage.chooseFilter(code) + await documentContentPage.checkIfFilterIsApplied(title) + await documentContentPage.checkIfCategoryExists(category) + }) + await attachScreenshot('TESTS-383_Template_created.png', page) + }) + }) +}) diff --git a/qms-tests/sanity/tests/documents/REQ-05.spec.ts b/qms-tests/sanity/tests/documents/REQ-05.spec.ts index 11f9021ba1..13e063dfa5 100644 --- a/qms-tests/sanity/tests/documents/REQ-05.spec.ts +++ b/qms-tests/sanity/tests/documents/REQ-05.spec.ts @@ -5,7 +5,6 @@ import { DocumentContentPage } from '../model/documents/document-content-page' import { LeftSideMenuPage } from '../model/left-side-menu-page' import { faker } from '@faker-js/faker' -import { createTemplateStep } from './common-documents-steps' test.use({ storageState: PlatformSetting @@ -38,7 +37,7 @@ test.describe('ISO 13485, 4.2.4 Control of documents', () => { await documentContentPage.selectControlDocumentSubcategory('Categories') await documentContentPage.clickOnAddCategoryButton() await documentContentPage.fillCategoryForm(title, description, code) - await documentContentPage.checkIfCategoryIsCreated(title, code) + await documentContentPage.expectCategoryCreated(title, code) }) await attachScreenshot('TESTS-298_category_created.png', page) @@ -61,66 +60,4 @@ test.describe('ISO 13485, 4.2.4 Control of documents', () => { await attachScreenshot('TESTS-381_document_space_created.png', page) }) - - test('TESTS-382. Create new a new Effective Template with category External', async ({ page }) => { - await allure.description('Requirement\nUsers need to create a new template') - await allure.tms('TESTS-382', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-382') - const leftSideMenuPage = new LeftSideMenuPage(page) - const category = faker.word.words(2) - const description = faker.lorem.sentence(1) - const code = faker.word.words(2) - const title = faker.word.words(2) - - await leftSideMenuPage.clickButtonOnTheLeft('Documents') - await test.step('2. Create a new category', async () => { - const documentContentPage = new DocumentContentPage(page) - await documentContentPage.selectControlDocumentSubcategory('Categories') - await documentContentPage.clickOnAddCategoryButton() - await documentContentPage.fillCategoryForm(category, description, code) - await documentContentPage.checkIfCategoryIsCreated(category, code) - }) - await test.step('3. Create a new template', async () => { - const documentContentPage = new DocumentContentPage(page) - - await documentContentPage.clickNewDocumentArrow() - await documentContentPage.clickNewTemplate() - await createTemplateStep(page, title, description, category) - }) - - await attachScreenshot('TESTS-382_Template_created.png', page) - }) - - test('TESTS-383. authorized User can search a doc per category "External"', async ({ page }) => { - await allure.description('Requirement\nUsers need to create a new category and space') - await allure.tms('TESTS-383', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-383') - - const title = faker.word.words(2) - const description = faker.lorem.sentence(1) - const code = faker.word.words(2) - const leftSideMenuPage = new LeftSideMenuPage(page) - const category = faker.word.words(2) - - await leftSideMenuPage.clickButtonOnTheLeft('Documents') - await test.step('2. Create a new category', async () => { - const documentContentPage = new DocumentContentPage(page) - await documentContentPage.selectControlDocumentSubcategory('Categories') - await documentContentPage.clickOnAddCategoryButton() - await documentContentPage.fillCategoryForm(category, description, code) - await documentContentPage.checkIfCategoryIsCreated(category, code) - }) - await test.step('3. Create a new template', async () => { - const documentContentPage = new DocumentContentPage(page) - - await documentContentPage.clickNewDocumentArrow() - await documentContentPage.clickNewTemplate() - await createTemplateStep(page, title, description, category) - }) - await test.step('4. Check if templates exists in template category', async () => { - const documentContentPage = new DocumentContentPage(page) - await documentContentPage.selectControlDocumentSubcategory('Templates') - await documentContentPage.chooseFilter(code) - await documentContentPage.checkIfFilterIsApplied(title) - }) - await attachScreenshot('TESTS-383_Template_created.png', page) - }) }) diff --git a/qms-tests/sanity/tests/documents/REQ-10.spec.ts b/qms-tests/sanity/tests/documents/REQ-10.spec.ts new file mode 100644 index 0000000000..1ef459f4f3 --- /dev/null +++ b/qms-tests/sanity/tests/documents/REQ-10.spec.ts @@ -0,0 +1,78 @@ +import { test } from '@playwright/test' +import { attachScreenshot, generateId, HomepageURI, PlatformSettingSecond, PlatformURI } from '../utils' +import { allure } from 'allure-playwright' + +import { SettingsPage } from './../model/setting-page' +import { DocumentDetails, DocumentStatus, NewDocument } from '../model/types' +import { DocumentContentPage } from '../model/documents/document-content-page' +import { faker } from '@faker-js/faker' +import { prepareDocumentStep } from './common-documents-steps' + +test.use({ + storageState: PlatformSettingSecond +}) + +test.describe('ISO 13485, 4.2.4 Control of documents ensure that documents of external origin are identified and their distribution controlled', () => { + test.beforeEach(async ({ page }) => { + await (await page.goto(`${PlatformURI}/${HomepageURI}`))?.finished() + }) + + test('TESTS-341. As a workspace owner, I can create roles and setup permissions', async ({ page }) => { + await allure.description( + 'Requirement\nUser is the owner of the workspace and can create roles and setup permissions' + ) + await allure.tms('TESTS-341', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-341') + await test.step('2. Check user role', async () => { + const settingsPage = new SettingsPage(page) + await settingsPage.openProfileMenu() + await settingsPage.clickSettings() + await settingsPage.clickDefaultDocuments() + await settingsPage.chooseRole('Manager') + await settingsPage.checkIfPermissionsExist() + await attachScreenshot('TESTS-341_Manager_roles.png', page) + await settingsPage.clickDefaultDocuments() + await settingsPage.chooseRole('QARA') + await settingsPage.checkIfPermissionsExist() + await attachScreenshot('TESTS-341_QARA_roles.png', page) + await settingsPage.clickDefaultDocuments() + await settingsPage.chooseRole('Qualified User') + await settingsPage.checkPermissionsExistQualifyUser() + await attachScreenshot('TESTS-341_User_roles.png', page) + }) + }) + + test('TESTS-347. As a space manager, I can Create New document from the New Doc blue button', async ({ page }) => { + await allure.description( + 'Requirement\nUser is a space manager and can create a new document from the New Doc blue button' + ) + await allure.tms('TESTS-347', 'https://tracex.hc.engineering/workbench/platform/tracker/TESTS-347') + await test.step('2. create new document as manager role', async () => { + const completeDocument: NewDocument = { + template: 'HR (HR)', + title: `Complete document-${generateId()}`, + description: `Complete document description-${generateId()}` + } + const folderName = faker.word.words(1) + const documentContentPage = new DocumentContentPage(page) + await documentContentPage.clickAddFolderButton() + await documentContentPage.fillDocumentSpaceFormManager(folderName) + await prepareDocumentStep(page, completeDocument) + + const documentDetails: DocumentDetails = { + type: 'HR', + category: 'Human Resources', + version: 'v0.1', + status: DocumentStatus.DRAFT, + owner: 'Dirak Kainin', + author: 'Dirak Kainin' + } + await documentContentPage.checkDocument({ + ...documentDetails, + status: DocumentStatus.DRAFT, + version: 'v0.1' + }) + await documentContentPage.clickLeaveFolder(folderName) + await attachScreenshot('TESTS-347_manager_document_created.png', page) + }) + }) +}) diff --git a/qms-tests/sanity/tests/documents/common-documents-steps.ts b/qms-tests/sanity/tests/documents/common-documents-steps.ts index 9d234b29b5..edbfbbf27d 100644 --- a/qms-tests/sanity/tests/documents/common-documents-steps.ts +++ b/qms-tests/sanity/tests/documents/common-documents-steps.ts @@ -22,12 +22,13 @@ export async function createTemplateStep ( page: Page, title: string, description: string, - category: string + category: string, + spaceName: string ): Promise { await test.step('2. Create a new template', async () => { const documentsPage = new DocumentsPage(page) - await documentsPage.createTemplate(title, description, category) + await documentsPage.createTemplate(title, description, category, spaceName) }) } diff --git a/qms-tests/sanity/tests/documents/documents.spec.ts b/qms-tests/sanity/tests/documents/documents.spec.ts index 4a9334c4fc..149c17df52 100644 --- a/qms-tests/sanity/tests/documents/documents.spec.ts +++ b/qms-tests/sanity/tests/documents/documents.spec.ts @@ -583,172 +583,6 @@ test.describe('QMS. Documents tests', () => { }) }) - test('TESTS-141. Send for approval document after resolve comments', async ({ page, browser }) => { - await allure.description( - 'Requirement\nUsers need to make a resolve all comments and done documents for the Effective status' - ) - await allure.tms('TESTS-141', 'https://front.hc.engineering/workbench/platform/tracker/TESTS-141') - const userSecondPage = await getSecondPage(browser) - const completeDocument: NewDocument = { - template: 'HR (HR)', - title: `Complete document-${generateId()}`, - description: `Complete document description-${generateId()}` - } - const reviewer = 'Dirak Kainin' - const documentDetails: DocumentDetails = { - type: 'HR', - category: 'Human Resources', - version: 'v0.1', - status: DocumentStatus.DRAFT, - owner: 'Appleseed John', - author: 'Appleseed John' - } - const newContentFirst = `Complete document. New content-${generateId()}!!!!` - const updateContentFirst = `Complete document Updated. Updated content-${generateId()}!!!!` - const newContentSecond = `Complete document. New content Description-${generateId()}!!!!` - const messageToContent: string = `Complete document. Message to the content-${generateId()}` - const messageToContentSecond: string = `Complete document. Message to the content-second-${generateId()}` - - await prepareDocumentStep(page, completeDocument) - - const documentContentPage = new DocumentContentPage(page) - await test.step('2. Add section and content', async () => { - await documentContentPage.checkDocumentTitle(completeDocument.title) - await documentContentPage.checkDocumentStatus(DocumentStatus.DRAFT) - await documentContentPage.checkDocument(documentDetails) - await documentContentPage.checkCurrentRights(DocumentRights.EDITING) - - await documentContentPage.addContent(newContentFirst) - await documentContentPage.checkContent(newContentFirst) - - await documentContentPage.addContent(newContentSecond, true, true) - - await attachScreenshot('TESTS-141_add_section_and_content.png', page) - }) - - await test.step('3. Send for Review', async () => { - await documentContentPage.buttonSendForReview.click() - await documentContentPage.fillSelectReviewersForm([reviewer]) - await documentContentPage.checkDocumentStatus(DocumentStatus.IN_REVIEW) - await documentContentPage.checkDocument({ - ...documentDetails, - status: DocumentStatus.IN_REVIEW - }) - await attachScreenshot('TESTS-141_send_for_review.png', page) - }) - - await test.step('4. As author add comment', async () => { - await documentContentPage.addMessageToTheText(newContentFirst, messageToContent) - - await documentContentPage.buttonComments.click() - - const documentCommentsPage = new DocumentCommentsPage(page) - await documentCommentsPage.checkCommentExist(messageToContent) - await documentCommentsPage.checkCommentCanBeResolved(messageToContent) - await attachScreenshot('TESTS-141_author_add_comments.png', page) - }) - - await test.step('5. As reviewer add comment and Complete Review', async () => { - await (await userSecondPage.goto(`${PlatformURI}/${DocumentURI}`))?.finished() - - const documentsPageSecond = new DocumentsPage(userSecondPage) - await documentsPageSecond.openDocument(completeDocument.title) - - const documentContentPageSecond = new DocumentContentPage(userSecondPage) - await documentContentPageSecond.addMessageToTheText(newContentSecond, messageToContentSecond) - - await documentContentPageSecond.buttonComments.click() - - const documentCommentsPageSecond = new DocumentCommentsPage(userSecondPage) - await documentCommentsPageSecond.checkCommentExist(messageToContentSecond) - await documentCommentsPageSecond.checkCommentCanBeResolved(messageToContentSecond) - - // // TODO uncomment after fix https://front.hc.engineering/workbench/platform/tracker/EZQMS-552 - // await documentCommentsPageSecond.checkCommentCanNotBeResolved(newContentFirst.sectionTitle, 1) - // await documentCommentsPageSecond.checkCommentCanNotBeResolved(newContentFirst.sectionTitle, 2) - - await documentContentPageSecond.completeReview() - - await documentContentPageSecond.checkDocumentStatus(DocumentStatus.REVIEWED) - await documentContentPageSecond.checkCurrentRights(DocumentRights.VIEWING) - await attachScreenshot('TESTS-141_reviewer_add_comments.png', page) - }) - - await test.step('6. Update Document and fix reviews', async () => { - await documentContentPage.createNewDraft() - await documentContentPage.replaceContent(updateContentFirst) - - const documentCommentsPage = new DocumentCommentsPage(page) - await documentCommentsPage.checkCommentExist(messageToContent) - await documentCommentsPage.checkCommentExist(messageToContentSecond) - await documentCommentsPage.resolveAllComments() - - await documentCommentsPage.checkCommentDoesNotExist(messageToContent) - await documentCommentsPage.checkCommentDoesNotExist(messageToContentSecond) - await attachScreenshot('TESTS-141_fix_reviews.png', page) - - await documentContentPage.buttonDocumentInformation.click() - await documentContentPage.checkDocumentStatus(DocumentStatus.DRAFT) - await documentContentPage.checkDocument({ - ...documentDetails, - status: DocumentStatus.DRAFT, - version: 'v0.1' - }) - await attachScreenshot('TESTS-141_check_document.png', page) - }) - - await test.step('7. Send for Approval', async () => { - await documentContentPage.buttonSendForApproval.click() - await documentContentPage.fillSelectApproversForm([reviewer]) - await documentContentPage.checkDocumentStatus(DocumentStatus.IN_APPROVAL) - await documentContentPage.checkDocument({ - ...documentDetails, - status: DocumentStatus.IN_APPROVAL, - version: 'v0.1' - }) - await documentContentPage.checkCurrentRights(DocumentRights.VIEWING) - }) - - await test.step('8. Approve document', async () => { - const documentsPageSecond = new DocumentsPage(userSecondPage) - await documentsPageSecond.openDocument(completeDocument.title) - - const documentContentPageSecond = new DocumentContentPage(userSecondPage) - await documentContentPageSecond.confirmApproval() - - await documentContentPageSecond.buttonDocumentInformation.click() - await documentContentPageSecond.checkDocumentStatus(DocumentStatus.EFFECTIVE) - await documentContentPageSecond.checkDocument({ - ...documentDetails, - status: DocumentStatus.EFFECTIVE, - version: 'v0.1' - }) - await documentContentPageSecond.checkCurrentRights(DocumentRights.VIEWING) - - await attachScreenshot('TESTS-141_approve_document.png', page) - }) - - await test.step('9. Check document', async () => { - await documentContentPage.checkDocumentStatus(DocumentStatus.EFFECTIVE) - await documentContentPage.checkDocument({ - ...documentDetails, - status: DocumentStatus.EFFECTIVE, - version: 'v0.1' - }) - await documentContentPage.checkCurrentRights(DocumentRights.VIEWING) - - await attachScreenshot('TESTS-141_check_document.png', page) - }) - - await test.step('10. Check History tab', async () => { - await documentContentPage.buttonHistoryTab.first().click() - - const documentHistoryPage = new DocumentHistoryPage(page) - await documentHistoryPage.checkHistoryEventExist('New document creation') - await attachScreenshot('TESTS-141_check_history_tab.png', page) - }) - }) - test('TESTS-162. Approve document with delayed release', async ({ page }) => { await allure.description('Requirement\nUsers need to create document with delayed release') await allure.tms('TESTS-162', 'https://front.hc.engineering/workbench/platform/tracker/TESTS-162') @@ -990,7 +824,7 @@ test.describe('QMS. Documents tests', () => { await allure.description( 'Requirement\nUsers need to make a resolve all comments and done documents for the Effective status' ) - await allure.tms('TESTS-206', 'https://front.hc.engineering/workbench/platform/tracker/TESTS-141') + await allure.tms('TESTS-206', 'https://front.hc.engineering/workbench/platform/tracker/TESTS-206') const userSecondPage = await getSecondPage(browser) const completeDocument: NewDocument = { template: 'HR (HR)', diff --git a/qms-tests/sanity/tests/model/documents/document-content-page.ts b/qms-tests/sanity/tests/model/documents/document-content-page.ts index 80b7f1e923..0daf965e28 100644 --- a/qms-tests/sanity/tests/model/documents/document-content-page.ts +++ b/qms-tests/sanity/tests/model/documents/document-content-page.ts @@ -45,7 +45,8 @@ export class DocumentContentPage extends DocumentCommonPage { readonly addSpaceButton: Locator readonly inputSpaceName: Locator readonly roleSelector: Locator - readonly selectRoleMember: Locator + readonly selectRoleMemberAJ: Locator + readonly selectRoleMemberDK: Locator readonly createButton: Locator readonly createNewDocument: Locator readonly selectCustom: Locator @@ -71,6 +72,15 @@ export class DocumentContentPage extends DocumentCommonPage { readonly newTemplate: Locator readonly filter: Locator readonly filterCategory: Locator + readonly qualityButtonDots: Locator + readonly editDocumentSpace: Locator + readonly qualityButtonMembers: Locator + readonly userMemberCainVelasquez: Locator + readonly qualityDocument: Locator + readonly saveButton: Locator + readonly addMember: Locator + readonly addMemberDropdown: Locator + readonly changeSpaceButton: Locator constructor (page: Page) { super(page) @@ -126,7 +136,8 @@ export class DocumentContentPage extends DocumentCommonPage { this.addSpaceButton = page.locator('#tree-orgspaces') this.inputSpaceName = page.getByPlaceholder('New documents space') this.roleSelector = page.getByRole('button', { name: 'Members' }) - this.selectRoleMember = page.getByRole('button', { name: 'AJ Appleseed John' }) + this.selectRoleMemberAJ = page.getByRole('button', { name: 'AJ Appleseed John' }) + this.selectRoleMemberDK = page.getByRole('button', { name: 'DK Dirak Kainin' }) this.createButton = page.getByRole('button', { name: 'Create' }) this.createNewDocument = page.getByRole('button', { name: 'Create new document' }) this.selectCustom = page.getByText('Custom') @@ -152,6 +163,15 @@ export class DocumentContentPage extends DocumentCommonPage { this.newTemplate = page.getByRole('button', { name: 'New template', exact: true }) this.filter = page.getByRole('button', { name: 'Filter' }) this.filterCategory = page.locator('span').filter({ hasText: /^Category$/ }) + this.qualityButtonDots = page.getByRole('button', { name: 'Quality documents' }).getByRole('button') + this.editDocumentSpace = page.getByRole('button', { name: 'Edit documents space' }) + this.qualityButtonMembers = page.getByRole('button', { name: 'AJ DK AQ 3 members' }).first() + this.userMemberCainVelasquez = page.getByRole('button', { name: 'VC Velasquez Cain' }) + this.qualityDocument = page.getByRole('button', { name: 'Quality documents' }) + this.saveButton = page.getByRole('button', { name: 'Save' }) + this.addMember = page.getByText('Add member') + this.addMemberDropdown = page.locator('.selectPopup') + this.changeSpaceButton = page.locator('[id="space\\.selector"]') } async checkDocumentTitle (title: string): Promise { @@ -198,6 +218,28 @@ export class DocumentContentPage extends DocumentCommonPage { } } + async addMemberToQualityDocument (): Promise { + await this.qualityDocument.hover() + await this.qualityButtonDots.click() + await this.editDocumentSpace.click() + await this.qualityButtonMembers.click() + await this.userMemberCainVelasquez.click() + await this.page.keyboard.press('Escape') + await this.saveButton.click() + } + + async clickAddMember (): Promise { + await this.addMember.click() + } + + async checkIfMemberDropdownHasMember (member: string, contains: boolean): Promise { + if (contains) { + await expect(this.addMemberDropdown).toContainText(member) + } else { + await expect(this.addMemberDropdown).not.toContainText(member) + } + } + async fillCategoryForm (categoryTitle: string, description: string, categoryCode: string): Promise { await this.categoryTitle.fill(categoryTitle) await this.description.fill(description) @@ -205,7 +247,7 @@ export class DocumentContentPage extends DocumentCommonPage { await this.createButton.click() } - async checkIfCategoryIsCreated (categoryTitle: string, categoryCode: string): Promise { + async expectCategoryCreated (categoryTitle: string, categoryCode: string): Promise { await expect(this.page.getByText(categoryTitle)).toBeVisible() await expect(this.page.getByRole('link', { name: categoryCode })).toBeVisible() } @@ -256,6 +298,11 @@ export class DocumentContentPage extends DocumentCommonPage { await expect(this.contentLocator).toHaveText(content) } + async changeSpaceInCreateDocumentForm (space: string): Promise { + await this.changeSpaceButton.click() + await this.page.getByRole('button', { name: space, exact: true }).nth(1).click() + } + async executeMoreActions (action: string): Promise { await this.buttonMoreActions.click() await this.selectFromDropdown(this.page, action) @@ -281,18 +328,31 @@ export class DocumentContentPage extends DocumentCommonPage { await expect(this.page.getByText(code, { exact: true })).toBeVisible() } + async checkIfCategoryExists (category: string): Promise { + await expect(this.page.getByText(category)).toBeVisible() + } + async fillDocumentSpaceForm (spaceName: string): Promise { await this.inputSpaceName.fill(spaceName) await this.roleSelector.nth(2).click() - await this.selectRoleMember.nth(2).click() + await this.selectRoleMemberAJ.nth(2).click() await this.page.keyboard.press('Escape') - await this.selectRoleMember.nth(1).click() + await this.selectRoleMemberAJ.nth(1).click() await this.page.getByRole('button', { name: 'DK Dirak Kainin' }).click() await this.page.keyboard.press('Escape') await this.page.waitForTimeout(1000) await this.createButton.click() } + async fillDocumentSpaceFormManager (spaceName: string): Promise { + await this.inputSpaceName.fill(spaceName) + await this.roleSelector.nth(1).click() + await this.selectRoleMemberDK.nth(2).click() + await this.page.keyboard.press('Escape') + await this.page.waitForTimeout(1000) + await this.createButton.click() + } + async checkSpaceFormIsCreated (spaceName: string): Promise { await expect(this.page.getByRole('button', { name: spaceName })).toBeVisible() } diff --git a/qms-tests/sanity/tests/model/documents/documents-page.ts b/qms-tests/sanity/tests/model/documents/documents-page.ts index a15c74f79e..d8662495be 100644 --- a/qms-tests/sanity/tests/model/documents/documents-page.ts +++ b/qms-tests/sanity/tests/model/documents/documents-page.ts @@ -1,6 +1,7 @@ import { type Locator, type Page } from '@playwright/test' import { CalendarPage } from '../calendar-page' import { NewDocument } from '../types' + export class DocumentsPage extends CalendarPage { readonly page: Page readonly buttonCreateDocument: Locator @@ -15,6 +16,7 @@ export class DocumentsPage extends CalendarPage { readonly nextStep: Locator readonly addMember: Locator readonly newMember: Locator + readonly changeSpaceButton: Locator constructor (page: Page) { super(page) @@ -35,6 +37,7 @@ export class DocumentsPage extends CalendarPage { this.nextStep = page.getByRole('button', { name: 'Next step' }) this.addMember = page.getByText('Add member') this.newMember = page.getByRole('button', { name: 'AJ Appleseed John' }) + this.changeSpaceButton = page.locator('[id="space\\.selector"]') } async createDocument (data: NewDocument, startSecondStep: boolean = false): Promise { @@ -47,6 +50,7 @@ export class DocumentsPage extends CalendarPage { // template if (!startSecondStep) { + await this.changeSpaceInCreateDocumentForm('Quality documents') await this.buttonPopupNextStep.click() } await this.page.locator('div.templates div.tmpHeader', { hasText: data.template }).click() @@ -66,7 +70,15 @@ export class DocumentsPage extends CalendarPage { await this.inputNewDocumentCreateDaft.click() } - async createTemplate (title: string, description: string, category: string): Promise { + async changeSpaceInCreateDocumentForm (space: string): Promise { + await this.changeSpaceButton.click() + await this.page + .locator(`div.list-container.flex-col.flex-grow.svelte-15na0wa >> text=${space}`) + .click({ force: true }) + } + + async createTemplate (title: string, description: string, category: string, spaceName: string): Promise { + await this.changeSpaceInCreateDocumentForm(spaceName) await this.buttonPopupNextStep.click() await this.inputNewDocumentTitle.fill(title) await this.inputNewDocumentDescription.fill(description) diff --git a/qms-tests/sanity/tests/model/setting-page.ts b/qms-tests/sanity/tests/model/setting-page.ts new file mode 100644 index 0000000000..acfe67e155 --- /dev/null +++ b/qms-tests/sanity/tests/model/setting-page.ts @@ -0,0 +1,92 @@ +import { expect, Page, Locator } from '@playwright/test' + +export class SettingsPage { + readonly page: Page + readonly profileButton: Locator + readonly settings: Locator + readonly defaultDocuments: Locator + readonly managerRole: Locator + readonly qaraRole: Locator + readonly qualifiedUserRole: Locator + readonly createDocumentPermission: Locator + readonly addPermissionButton: Locator + readonly reviewDocumentPermission: Locator + readonly approveDocumentPermission: Locator + readonly coAuthorDocumentPermission: Locator + readonly createDocumentCategoryPermission: Locator + readonly updateDocumentCategoryPermission: Locator + readonly deleteDocumentCategoryPermission: Locator + readonly updateSpacePermission: Locator + readonly addRoleUpdatePermissionOwner: Locator + + constructor (page: Page) { + this.page = page + this.profileButton = page.locator('#profile-button') + this.settings = page.getByRole('button', { name: 'Settings' }) + this.defaultDocuments = page.getByRole('button', { name: 'Default Documents Controlled' }) + this.managerRole = page.getByRole('button', { name: 'Manager', exact: true }) + this.qaraRole = page.getByRole('button', { name: 'QARA', exact: true }) + this.qualifiedUserRole = page.getByRole('button', { name: 'Qualified User', exact: true }) + this.createDocumentPermission = page.getByText('Create document', { exact: true }) + this.addPermissionButton = page.locator('.hulyTableAttr-header > .font-medium-14') + this.reviewDocumentPermission = page.getByText('Review document', { exact: true }) + this.approveDocumentPermission = page.getByText('Approve document', { exact: true }) + this.coAuthorDocumentPermission = page.getByText('Co-author document', { exact: true }) + this.createDocumentCategoryPermission = page.getByText('Create document category', { exact: true }) + this.updateDocumentCategoryPermission = page.getByText('Update document category', { exact: true }) + this.deleteDocumentCategoryPermission = page.getByText('Delete document category', { exact: true }) + this.updateSpacePermission = page.getByText('Update space', { exact: true }) + this.addRoleUpdatePermissionOwner = page.getByRole('button', { name: 'Update document owner' }) + } + + async openProfileMenu (): Promise { + await this.profileButton.click() + } + + async clickSettings (): Promise { + await this.settings.click() + } + + async clickDefaultDocuments (): Promise { + await this.defaultDocuments.click() + } + + async clickAddPermissionButton (): Promise { + await this.addPermissionButton.click() + } + + async clickAddRoleUpdatePermissionOwner (): Promise { + await this.addRoleUpdatePermissionOwner.click() + } + + async checkIfPermissionsExist (): Promise { + await expect(this.reviewDocumentPermission).toBeVisible() + await expect(this.approveDocumentPermission).toBeVisible() + await expect(this.coAuthorDocumentPermission).toBeVisible() + await expect(this.createDocumentCategoryPermission).toBeVisible() + await expect(this.updateDocumentCategoryPermission).toBeVisible() + await expect(this.deleteDocumentCategoryPermission).toBeVisible() + await expect(this.updateSpacePermission).toBeVisible() + } + + async checkPermissionsExistQualifyUser (): Promise { + await expect(this.reviewDocumentPermission).toBeVisible() + await expect(this.approveDocumentPermission).toBeVisible() + } + + async chooseRole (role: string): Promise { + switch (role) { + case 'Manager': + await this.managerRole.click() + break + case 'QARA': + await this.qaraRole.click() + break + case 'Qualified User': + await this.qualifiedUserRole.click() + break + default: + throw new Error('Role not found') + } + } +} diff --git a/qms-tests/sanity/tests/playwright.config.ts b/qms-tests/sanity/tests/playwright.config.ts index 0974cecd9d..2272d8d36a 100644 --- a/qms-tests/sanity/tests/playwright.config.ts +++ b/qms-tests/sanity/tests/playwright.config.ts @@ -28,6 +28,8 @@ const config: PlaywrightTestConfig = { } } ], + fullyParallel: false, + workers: 1, retries: 1, timeout: 60000, maxFailures, diff --git a/qms-tests/sanity/tests/utils.ts b/qms-tests/sanity/tests/utils.ts index 3bcf628cf2..72517dcb5e 100644 --- a/qms-tests/sanity/tests/utils.ts +++ b/qms-tests/sanity/tests/utils.ts @@ -7,6 +7,7 @@ export const PlatformUser = process.env.PLATFORM_USER as string export const PlatformToken = process.env.PLATFORM_TOKEN as string export const PlatformSetting = process.env.SETTING as string export const PlatformSettingSecond = process.env.SETTING_SECOND as string +export const PlatformSettingThird = process.env.SETTING_THIRD as string export const PlatformSettingQaraManager = process.env.SETTING_QARA_MANAGER as string export const PlatformPassword = process.env.PLATFORM_PASSWORD as string export const DefaultWorkspace = 'sanity-ws-qms'