From 640ac696b048acc11d6c34c31063d289f08e0521 Mon Sep 17 00:00:00 2001 From: Piyush Patel Date: Mon, 4 Dec 2023 09:08:11 +0530 Subject: [PATCH 01/26] Commit to merge latest dev --- .../tests/pages/Community/DocumentsPage.ts | 67 ++++++ frontend/tests/pages/HomePage.ts | 11 +- frontend/tests/pages/MenuPage.ts | 5 +- frontend/tests/test/DocumentsTests.Spec.ts | 216 ++++++++++++++++++ 4 files changed, 294 insertions(+), 5 deletions(-) create mode 100644 frontend/tests/pages/Community/DocumentsPage.ts create mode 100644 frontend/tests/test/DocumentsTests.Spec.ts diff --git a/frontend/tests/pages/Community/DocumentsPage.ts b/frontend/tests/pages/Community/DocumentsPage.ts new file mode 100644 index 00000000..fd367dfc --- /dev/null +++ b/frontend/tests/pages/Community/DocumentsPage.ts @@ -0,0 +1,67 @@ +import BasePage from '../BasePage'; + +const addNewDocumentButton = `(//span[text()='Select your language']//..//..//div)[4]//button`; +const selectedLanguage = (languageName: string) => + `//h4[text()='${languageName}']`; +const languageName = (language: string) => + `//h5[text()='${language}']//..//input`; + +class DocumentsPage extends BasePage { + async isPageTitleVisible() { + return await this.page.locator(`//h2[text()='Documents']`).isVisible(); + } + async clickOnSelectYourLanguageDropdown() { + await this.page + .getByRole('heading', { name: 'Select your language' }) + .click(); + } + async clickOnSelectDocumentLanguageDropdown() { + await this.page + .getByRole('heading', { name: 'Select document language' }) + .click(); + } + async isSelectYourLanguagePopupVisible() { + return await this.page + .locator(`//h2[text()='Select your language']`) + .first() + .isVisible(); + } + async isAddNewDocumentPopupVisible() { + return await this.page + .getByRole('heading', { name: 'Add new document' }) + .isVisible(); + } + async selectLanguage(language: string) { + await this.page + .getByRole('textbox', { name: 'Search by language...' }) + .fill(language); + await this.page.locator(languageName(language)).first().click(); + await this.page.getByRole('button', { name: 'Confirm' }).click(); + } + async isLanguageSelected(languageName: string) { + return await this.page + .locator(selectedLanguage(languageName)) + .last() + .isVisible(); + } + async clickOnAddNewDocumentPopupCrossButton() { + await this.page.getByRole('button').first().click(); + } + async clickOnCrossButton() { + await this.page.click( + `(//span[text()='Select your language']//..//..//div)[2]//button`, + ); + } + async clickOnAddNewDocumentsButton() { + await this.page.click(addNewDocumentButton); + } + async clickOnCancelButton() { + await this.page.getByRole('button', { name: 'Cancel' }).click(); + } + async uploadTextFile() { + const filePath = 'C:/Users/Piyush Patel/Desktop/sample3.txt'; + await this.page.setInputFiles('input[type="file"]', filePath); + } +} + +export default DocumentsPage; diff --git a/frontend/tests/pages/HomePage.ts b/frontend/tests/pages/HomePage.ts index 2c785cc2..6333d928 100644 --- a/frontend/tests/pages/HomePage.ts +++ b/frontend/tests/pages/HomePage.ts @@ -3,6 +3,7 @@ import BasePage from './BasePage'; const homePageTitle = '//div[@class="section"]/ion-item-group//ion-label[text() = "Media"]'; const homePageText = `//ion-label[text()]`; +const headerText = '#crowd-rock-app #app-name-text'; const expandIcon = '#app-menu-button'; const languageText = '//ion-label[text() = "Language"]'; @@ -11,7 +12,9 @@ class HomePage extends BasePage { await this.page.locator(homePageTitle).waitFor(); return await this.page.locator(homePageTitle).isVisible(); } - + async clickOnCrowdRocks() { + await this.page.locator(headerText).first().click(); + } async getHomePageTitle() { return await this.page.locator(homePageText).first().textContent(); } @@ -33,6 +36,12 @@ class HomePage extends BasePage { .filter({ hasText: 'Forums' }) .click(); } + async clickOnTheDocumentsSection() { + await this.page + .locator('ion-card-header') + .filter({ hasText: 'Documents' }) + .click(); + } } export default HomePage; diff --git a/frontend/tests/pages/MenuPage.ts b/frontend/tests/pages/MenuPage.ts index 9519a231..965fd535 100644 --- a/frontend/tests/pages/MenuPage.ts +++ b/frontend/tests/pages/MenuPage.ts @@ -1,6 +1,7 @@ import BasePage from './BasePage'; const headerText = '#crowd-rock-app #app-name-text'; + const leftMenuFeatureButton = (featureName: string) => `//h4[text()="${featureName}"]`; @@ -18,10 +19,6 @@ class MenuPage extends BasePage { await this.page.locator(leftMenuFeatureButton(featureName)).first().click(); await this.page.waitForTimeout(1000); } - - async clickOnCrowdRocks() { - await this.page.locator(headerText).first().click(); - } } export default MenuPage; diff --git a/frontend/tests/test/DocumentsTests.Spec.ts b/frontend/tests/test/DocumentsTests.Spec.ts new file mode 100644 index 00000000..12c065e0 --- /dev/null +++ b/frontend/tests/test/DocumentsTests.Spec.ts @@ -0,0 +1,216 @@ +import { Page, chromium, expect, test } from '@playwright/test'; +import PageUrls from '../constants/PageUrls'; +import RegistrationPage from '../pages/RegistrationPage'; +import RegisterData from '../data-factory/RegisterData'; +import DocumentsPage from '../pages/Community/DocumentsPage'; +import HomePage from '../pages/HomePage'; +import LoginPage from '../pages/LoginPage'; +import { language, settings } from '../enums/Enums'; +import SettingsPage from '../pages/SettingsPage'; +import CommonPage from '../pages/Community/CommonPage'; + +const registerData = RegisterData.validRegisterData(); + +test.beforeAll(async () => { + const browser = await chromium.launch({ headless: true }); + const context = await browser.newContext(); + const page = await context.newPage(); + const registerPage = new RegistrationPage(page); + + //Navigate to the URL + await page.goto(PageUrls.RegisterPage); + + //Verify the title of the page + expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); + + //Fill and submit the register form + await registerPage.fillRegistrationForm(registerData); + await registerPage.clickOnRegisterButton(); + await page.waitForTimeout(3000); +}); + +async function turnOnBetaTools(page: Page) { + const settingsPage = new SettingsPage(page); + const homePage = new HomePage(page); + + //Navigate to the URL + await page.goto(PageUrls.SettingsPage); + + //Click on beta tools toggle button + await settingsPage.clickOnToggleButton(settings.BetaTools, true); + await homePage.clickOnCrowdRocks(); +} + +test(' Verify that user can select & cancel language successfully', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + + //Verify that language is selected + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); + await documentsPage.clickOnCrossButton(); + expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); +}); + +test('Verify that select your language popup is closed when user clicks on the cancel button', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and click on the select your language dropdown + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); + + // Click on the cancel button + await documentsPage.clickOnCancelButton(); + + // Verify that select your language popup is closed + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeFalsy(); +}); + +test('Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and click on the select your language dropdown + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); + + // Click on the cancel button + await documentsPage.selectLanguage(language.English); + await documentsPage.clickOnAddNewDocumentsButton(); + + // Verify that selected language is displayed + expect(await documentsPage.isLanguageSelected(language.English)); +}); + +test('Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + + await documentsPage.clickOnAddNewDocumentsButton(); + await documentsPage.clickOnSelectDocumentLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); + + await documentsPage.clickOnAddNewDocumentPopupCrossButton(); + expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); +}); + +test('Verify that user can upload documents successfully', async ({ page }) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + + //Verify that language is selected + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); + await documentsPage.uploadTextFile(); + // expect(await commonPage.getValidationMessage()).toEqual( + // 'Please select document language first.', + // ); +}); + +test('Verify that validation message is appeared when user uploads the file without selecting the languages', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const commonPage = new CommonPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page + await homePage.clickOnTheDocumentsSection(); + + //Upload text file without selecting the language + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + await documentsPage.uploadTextFile(); + expect(await commonPage.getValidationMessage()).toEqual( + 'Please select document language first.', + ); +}); + +test('Verify that add new document popup is closed when user click on the cancel button', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + await documentsPage.clickOnCancelButton(); + + //Verify that Add new popup is closed + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeFalsy(); +}); From 0a6bc4a086b5b5d16ac88dad00f3212502a2c3df Mon Sep 17 00:00:00 2001 From: Piyush Patel Date: Tue, 5 Dec 2023 09:13:46 +0530 Subject: [PATCH 02/26] Commit to merge latest dev --- frontend/tests/pages/Community/CommonPage.ts | 2 +- frontend/tests/test/DocumentsTests.Spec.ts | 140 +++++++++++++++++-- 2 files changed, 128 insertions(+), 14 deletions(-) diff --git a/frontend/tests/pages/Community/CommonPage.ts b/frontend/tests/pages/Community/CommonPage.ts index abf78867..a2a5867a 100644 --- a/frontend/tests/pages/Community/CommonPage.ts +++ b/frontend/tests/pages/Community/CommonPage.ts @@ -28,7 +28,7 @@ class CommonPage extends BasePage { return await this.page.getByRole('heading', { name: name }).isVisible(); } async getValidationMessage() { - return await this.page.locator(`.toast-message`).textContent(); + return await this.page.locator(`.toast-message`).last().textContent(); } } export default CommonPage; diff --git a/frontend/tests/test/DocumentsTests.Spec.ts b/frontend/tests/test/DocumentsTests.Spec.ts index 12c065e0..8e166fa5 100644 --- a/frontend/tests/test/DocumentsTests.Spec.ts +++ b/frontend/tests/test/DocumentsTests.Spec.ts @@ -8,8 +8,14 @@ import LoginPage from '../pages/LoginPage'; import { language, settings } from '../enums/Enums'; import SettingsPage from '../pages/SettingsPage'; import CommonPage from '../pages/Community/CommonPage'; +import { writeFileSync } from 'fs'; const registerData = RegisterData.validRegisterData(); +const documentName = await generateUniqueFileName('txt'); +const filePath = + `D:/Etenlabs/Repos/Latest/crowd.rocks/frontend/tests/testData/` + + documentName; +const fileContent = 'Hello, this is the content of the file.'; test.beforeAll(async () => { const browser = await chromium.launch({ headless: true }); @@ -17,6 +23,7 @@ test.beforeAll(async () => { const page = await context.newPage(); const registerPage = new RegistrationPage(page); + writeFileSync(filePath, fileContent); //Navigate to the URL await page.goto(PageUrls.RegisterPage); @@ -28,7 +35,11 @@ test.beforeAll(async () => { await registerPage.clickOnRegisterButton(); await page.waitForTimeout(3000); }); - +async function generateUniqueFileName(extension: string): Promise { + const timestamp = new Date().toISOString().replace(/[-:.]/g, ''); + const randomString = Math.random().toString(36).substring(7); + return `${timestamp}_${randomString}.${extension}`; +} async function turnOnBetaTools(page: Page) { const settingsPage = new SettingsPage(page); const homePage = new HomePage(page); @@ -41,7 +52,7 @@ async function turnOnBetaTools(page: Page) { await homePage.clickOnCrowdRocks(); } -test(' Verify that user can select & cancel language successfully', async ({ +test('1: Verify that user can select & cancel language successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -65,7 +76,7 @@ test(' Verify that user can select & cancel language successfully', async ({ expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); }); -test('Verify that select your language popup is closed when user clicks on the cancel button', async ({ +test('2: Verify that select your language popup is closed when user clicks on the cancel button', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -90,7 +101,7 @@ test('Verify that select your language popup is closed when user clicks on the c expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeFalsy(); }); -test('Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ +test('3: Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -116,7 +127,7 @@ test('Verify that language is selected on the Add new document popup is the same expect(await documentsPage.isLanguageSelected(language.English)); }); -test('Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ +test('4: Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -141,10 +152,11 @@ test('Verify that user is able to select & cancel the language from the dropdown expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); }); -test('Verify that user can upload documents successfully', async ({ page }) => { +test('5: Verify that user can upload documents successfully', async ({ page }) => { const loginPage = new LoginPage(page); const documentsPage = new DocumentsPage(page); const homePage = new HomePage(page); + const commonPage = new CommonPage(page); //Login with valid credentials and turn on the beta tools await page.goto(PageUrls.LoginPage); @@ -162,13 +174,51 @@ test('Verify that user can upload documents successfully', async ({ page }) => { //Verify that language is selected expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - await documentsPage.uploadTextFile(); - // expect(await commonPage.getValidationMessage()).toEqual( - // 'Please select document language first.', - // ); + //await documentsPage.clickOnUploadButton(); + await documentsPage.uploadTextFile(filePath); + expect(await commonPage.getValidationMessage()).toEqual( + 'Success at uploading new document!', + ); + await documentsPage.clickOnCancelButton(); + await page.reload(); + //await documentsPage.clickOnGoToDocumentsButton(); + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + expect( + await documentsPage.isCreatedDocumentVisible(documentName), + ).toBeTruthy(); }); -test('Verify that validation message is appeared when user uploads the file without selecting the languages', async ({ +test('6: Verify that user can not allowed upload documents with the same name successfully', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + const commonPage = new CommonPage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + + //Verify that language is selected + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); + await documentsPage.uploadTextFile(filePath); + expect(await commonPage.getValidationMessage()).toEqual( + 'File with this name already exists', + ); +}); + +test('7: Verify that validation message is appeared when user uploads the file without selecting the languages', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -187,13 +237,13 @@ test('Verify that validation message is appeared when user uploads the file with //Upload text file without selecting the language await documentsPage.clickOnAddNewDocumentsButton(); expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - await documentsPage.uploadTextFile(); + await documentsPage.uploadTextFile(filePath); expect(await commonPage.getValidationMessage()).toEqual( 'Please select document language first.', ); }); -test('Verify that add new document popup is closed when user click on the cancel button', async ({ +test('8: Verify that add new document popup is closed when user click on the cancel button', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -214,3 +264,67 @@ test('Verify that add new document popup is closed when user click on the cancel //Verify that Add new popup is closed expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeFalsy(); }); + +test('9: Verify user can download the documents successfully', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + + await documentsPage.uploadTextFile(filePath); + await documentsPage.clickOnCancelButton(); + await page.reload(); + + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + + await documentsPage.clickOnDownloadDocumentButton(documentName); + //need to assertion +}); + +test('10: Verify user can redirected on document details page', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); + + //Click on add document button + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + + //Upload text file + await documentsPage.uploadTextFile(filePath); + await documentsPage.clickOnCancelButton(); + await page.reload(); + + //search the create document and click on document name + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + await documentsPage.clickOnDocument(documentName); + + //verify that document details page is open + expect(await documentsPage.goToThedocumentDetailsPage()).toBeTruthy(); +}); From f36995e694bf1859e5945becfbd89c831430b000 Mon Sep 17 00:00:00 2001 From: Piyush Patel Date: Tue, 5 Dec 2023 17:30:27 +0530 Subject: [PATCH 03/26] Documents Tests Added_5Dec --- frontend/tests/constants/DocumentConstants.ts | 15 ++ .../tests/pages/Community/DocumentsPage.ts | 36 ++- frontend/tests/test/DocumentsTests.Spec.ts | 215 ++++++++++-------- frontend/tests/test/SettingsTests.Spec.ts | 5 +- frontend/tests/testData/gifSample.gif | Bin 0 -> 40316 bytes 5 files changed, 171 insertions(+), 100 deletions(-) create mode 100644 frontend/tests/constants/DocumentConstants.ts create mode 100644 frontend/tests/testData/gifSample.gif diff --git a/frontend/tests/constants/DocumentConstants.ts b/frontend/tests/constants/DocumentConstants.ts new file mode 100644 index 00000000..1ac5fef3 --- /dev/null +++ b/frontend/tests/constants/DocumentConstants.ts @@ -0,0 +1,15 @@ +import path from 'path'; + +// Define the base directory for test data +const baseTestDataDirectory = + 'D:/Etenlabs/Repos/Latest/crowd.rocks/frontend/tests/testData/'; + +// Define the constants +const constants = { + filePath: (documentName: string) => + path.join(baseTestDataDirectory, documentName), + invalidFile: path.join(baseTestDataDirectory, 'gifSample.gif'), + fileContent: 'Hello, this is the content of the file.', +}; + +export default constants; diff --git a/frontend/tests/pages/Community/DocumentsPage.ts b/frontend/tests/pages/Community/DocumentsPage.ts index fd367dfc..f8fad94f 100644 --- a/frontend/tests/pages/Community/DocumentsPage.ts +++ b/frontend/tests/pages/Community/DocumentsPage.ts @@ -5,11 +5,19 @@ const selectedLanguage = (languageName: string) => `//h4[text()='${languageName}']`; const languageName = (language: string) => `//h5[text()='${language}']//..//input`; +const documents = (documentName: string) => `//p[text()='${documentName}']`; +const meatBallsMenuButton = (documentName: string) => + `//p[text()='${documentName}']//..//..//button`; class DocumentsPage extends BasePage { async isPageTitleVisible() { return await this.page.locator(`//h2[text()='Documents']`).isVisible(); } + async isDocumentDetailsPageVisible() { + return await this.page + .getByRole('heading', { name: 'Details' }) + .isVisible(); + } async clickOnSelectYourLanguageDropdown() { await this.page .getByRole('heading', { name: 'Select your language' }) @@ -58,10 +66,34 @@ class DocumentsPage extends BasePage { async clickOnCancelButton() { await this.page.getByRole('button', { name: 'Cancel' }).click(); } - async uploadTextFile() { - const filePath = 'C:/Users/Piyush Patel/Desktop/sample3.txt'; + async uploadTextFile(filePath: string) { await this.page.setInputFiles('input[type="file"]', filePath); } + async clickOnUploadButton() { + await this.page.getByRole('button', { name: 'Upload' }).click(); + } + async searchDocuments(documentName: string) { + await this.page + .getByPlaceholder(`Search by document...`) + .fill(documentName); + await this.page.waitForTimeout(1000); + } + async clickOnDocument(documentName: string) { + await this.page.locator(documents(documentName)).click(); + } + async isCreatedDocumentVisible(documentName: string) { + return await this.page.locator(documents(documentName)).isVisible(); + } + async clickOnMeatBallsMenuButton(documentName: string) { + await this.page.locator(meatBallsMenuButton(documentName)).click(); + } + async clickOnGoToDocumentsButton() { + await this.page.getByRole('button', { name: 'Go to Documents' }).click(); + } + async downloadDocument(documentName: string) { + await this.clickOnMeatBallsMenuButton(documentName); + await this.page.getByRole('button', { name: 'Download' }).click(); + } } export default DocumentsPage; diff --git a/frontend/tests/test/DocumentsTests.Spec.ts b/frontend/tests/test/DocumentsTests.Spec.ts index 8e166fa5..75e706d4 100644 --- a/frontend/tests/test/DocumentsTests.Spec.ts +++ b/frontend/tests/test/DocumentsTests.Spec.ts @@ -8,14 +8,11 @@ import LoginPage from '../pages/LoginPage'; import { language, settings } from '../enums/Enums'; import SettingsPage from '../pages/SettingsPage'; import CommonPage from '../pages/Community/CommonPage'; +import constants from '../constants/DocumentConstants'; import { writeFileSync } from 'fs'; const registerData = RegisterData.validRegisterData(); const documentName = await generateUniqueFileName('txt'); -const filePath = - `D:/Etenlabs/Repos/Latest/crowd.rocks/frontend/tests/testData/` + - documentName; -const fileContent = 'Hello, this is the content of the file.'; test.beforeAll(async () => { const browser = await chromium.launch({ headless: true }); @@ -23,7 +20,7 @@ test.beforeAll(async () => { const page = await context.newPage(); const registerPage = new RegistrationPage(page); - writeFileSync(filePath, fileContent); + writeFileSync(constants.filePath(documentName), constants.fileContent); //Navigate to the URL await page.goto(PageUrls.RegisterPage); @@ -35,11 +32,13 @@ test.beforeAll(async () => { await registerPage.clickOnRegisterButton(); await page.waitForTimeout(3000); }); + async function generateUniqueFileName(extension: string): Promise { const timestamp = new Date().toISOString().replace(/[-:.]/g, ''); const randomString = Math.random().toString(36).substring(7); return `${timestamp}_${randomString}.${extension}`; } + async function turnOnBetaTools(page: Page) { const settingsPage = new SettingsPage(page); const homePage = new HomePage(page); @@ -52,12 +51,13 @@ async function turnOnBetaTools(page: Page) { await homePage.clickOnCrowdRocks(); } -test('1: Verify that user can select & cancel language successfully', async ({ +test('1: Verify that user can upload document successfully', async ({ page, }) => { const loginPage = new LoginPage(page); const documentsPage = new DocumentsPage(page); const homePage = new HomePage(page); + const commonPage = new CommonPage(page); //Login with valid credentials and turn on the beta tools await page.goto(PageUrls.LoginPage); @@ -70,13 +70,27 @@ test('1: Verify that user can select & cancel language successfully', async ({ await documentsPage.clickOnSelectYourLanguageDropdown(); await documentsPage.selectLanguage(language.English); + await documentsPage.clickOnAddNewDocumentsButton(); + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + //Verify that language is selected expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - await documentsPage.clickOnCrossButton(); - expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); + const [uploadFile] = await Promise.all([ + page.waitForEvent('filechooser'), + await documentsPage.clickOnUploadButton(), + ]); + uploadFile.setFiles(constants.filePath(documentName)); + expect(await commonPage.getValidationMessage()).toEqual( + 'Success at uploading new document!', + ); + await documentsPage.clickOnGoToDocumentsButton(); + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + expect( + await documentsPage.isCreatedDocumentVisible(documentName), + ).toBeTruthy(); }); -test('2: Verify that select your language popup is closed when user clicks on the cancel button', async ({ +test('2: Verify user can download the document successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -88,20 +102,21 @@ test('2: Verify that select your language popup is closed when user clicks on th await loginPage.loginToApp(registerData); await turnOnBetaTools(page); - //Navigate to documents page and click on the select your language dropdown + //Navigate to documents page and select language await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); await documentsPage.clickOnSelectYourLanguageDropdown(); - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); - - // Click on the cancel button - await documentsPage.clickOnCancelButton(); + await documentsPage.selectLanguage(language.English); + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); - // Verify that select your language popup is closed - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeFalsy(); + const [download] = await Promise.all([ + page.waitForEvent('download'), + documentsPage.downloadDocument(documentName), + ]); + expect(download).not.toBeNull(); + expect(download.url()).toContain(documentName); }); -test('3: Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ +test('3: Verify user can redirected on document details page successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -113,49 +128,25 @@ test('3: Verify that language is selected on the Add new document popup is the s await loginPage.loginToApp(registerData); await turnOnBetaTools(page); - //Navigate to documents page and click on the select your language dropdown + //Navigate to documents page and select language await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); await documentsPage.clickOnSelectYourLanguageDropdown(); - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); - - // Click on the cancel button await documentsPage.selectLanguage(language.English); - await documentsPage.clickOnAddNewDocumentsButton(); - // Verify that selected language is displayed - expect(await documentsPage.isLanguageSelected(language.English)); + //search the create document and click on document name + await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + await documentsPage.clickOnDocument(documentName); + + //verify that document details page is open + expect(await documentsPage.isDocumentDetailsPageVisible()).toBeTruthy(); }); -test('4: Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ +test('4: Verify that user is not allowed to upload documents with the name which already exists', async ({ page, }) => { const loginPage = new LoginPage(page); const documentsPage = new DocumentsPage(page); const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - - await documentsPage.clickOnAddNewDocumentsButton(); - await documentsPage.clickOnSelectDocumentLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - - await documentsPage.clickOnAddNewDocumentPopupCrossButton(); - expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); -}); - -test('5: Verify that user can upload documents successfully', async ({ page }) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); const commonPage = new CommonPage(page); //Login with valid credentials and turn on the beta tools @@ -174,21 +165,13 @@ test('5: Verify that user can upload documents successfully', async ({ page }) = //Verify that language is selected expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - //await documentsPage.clickOnUploadButton(); - await documentsPage.uploadTextFile(filePath); + await documentsPage.uploadTextFile(constants.filePath(documentName)); expect(await commonPage.getValidationMessage()).toEqual( - 'Success at uploading new document!', + 'File with this name already exists', ); - await documentsPage.clickOnCancelButton(); - await page.reload(); - //await documentsPage.clickOnGoToDocumentsButton(); - await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); - expect( - await documentsPage.isCreatedDocumentVisible(documentName), - ).toBeTruthy(); }); -test('6: Verify that user can not allowed upload documents with the same name successfully', async ({ +test.skip('5: Verify that validation message is appeared when user uploads the invalid file', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -212,13 +195,17 @@ test('6: Verify that user can not allowed upload documents with the same name su //Verify that language is selected expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - await documentsPage.uploadTextFile(filePath); + const [uploadFile] = await Promise.all([ + page.waitForEvent('filechooser'), + await documentsPage.clickOnUploadButton(), + ]); + uploadFile.setFiles(constants.invalidFile); expect(await commonPage.getValidationMessage()).toEqual( - 'File with this name already exists', + 'Failed at uploading new Document! [UnknownError]', ); }); -test('7: Verify that validation message is appeared when user uploads the file without selecting the languages', async ({ +test('6: Verify that validation message is appeared when user uploads the file without selecting the language', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -237,13 +224,13 @@ test('7: Verify that validation message is appeared when user uploads the file w //Upload text file without selecting the language await documentsPage.clickOnAddNewDocumentsButton(); expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - await documentsPage.uploadTextFile(filePath); + await documentsPage.uploadTextFile(constants.filePath(documentName)); expect(await commonPage.getValidationMessage()).toEqual( 'Please select document language first.', ); }); -test('8: Verify that add new document popup is closed when user click on the cancel button', async ({ +test('7: Verify that user can select & cancel language successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -257,15 +244,19 @@ test('8: Verify that add new document popup is closed when user click on the can //Navigate to documents page and select language await homePage.clickOnTheDocumentsSection(); - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - await documentsPage.clickOnCancelButton(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + await documentsPage.selectLanguage(language.English); - //Verify that Add new popup is closed - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeFalsy(); + //Verify that language is selected + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); + + //Deselect the language + await documentsPage.clickOnCrossButton(); + expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); }); -test('9: Verify user can download the documents successfully', async ({ +test('8: Verify that select your language popup is closed when user clicks on the cancel button', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -277,25 +268,46 @@ test('9: Verify user can download the documents successfully', async ({ await loginPage.loginToApp(registerData); await turnOnBetaTools(page); - //Navigate to documents page and select language + //Navigate to documents page and click on the select your language dropdown await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); - await documentsPage.uploadTextFile(filePath); + // Click on the cancel button await documentsPage.clickOnCancelButton(); - await page.reload(); - await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); + // Verify that select your language popup is closed + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeFalsy(); +}); + +test('9: Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and click on the select your language dropdown + await homePage.clickOnTheDocumentsSection(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnSelectYourLanguageDropdown(); + expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); + + // Select your language + await documentsPage.selectLanguage(language.English); + await documentsPage.clickOnAddNewDocumentsButton(); - await documentsPage.clickOnDownloadDocumentButton(documentName); - //need to assertion + // Verify that selected language is displayed + expect(await documentsPage.isLanguageSelected(language.English)); }); -test('10: Verify user can redirected on document details page', async ({ +test('10: Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ page, }) => { const loginPage = new LoginPage(page); @@ -309,22 +321,35 @@ test('10: Verify user can redirected on document details page', async ({ //Navigate to documents page and select language await homePage.clickOnTheDocumentsSection(); - await documentsPage.clickOnSelectYourLanguageDropdown(); + expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); + await documentsPage.clickOnAddNewDocumentsButton(); + await documentsPage.clickOnSelectDocumentLanguageDropdown(); await documentsPage.selectLanguage(language.English); + expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - //Click on add document button + //Deselect the language + await documentsPage.clickOnAddNewDocumentPopupCrossButton(); + expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); +}); + +test('11: Verify that add new document popup is closed when user click on the cancel button', async ({ + page, +}) => { + const loginPage = new LoginPage(page); + const documentsPage = new DocumentsPage(page); + const homePage = new HomePage(page); + + //Login with valid credentials and turn on the beta tools + await page.goto(PageUrls.LoginPage); + await loginPage.loginToApp(registerData); + await turnOnBetaTools(page); + + //Navigate to documents page and select language + await homePage.clickOnTheDocumentsSection(); await documentsPage.clickOnAddNewDocumentsButton(); expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - - //Upload text file - await documentsPage.uploadTextFile(filePath); await documentsPage.clickOnCancelButton(); - await page.reload(); - //search the create document and click on document name - await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); - await documentsPage.clickOnDocument(documentName); - - //verify that document details page is open - expect(await documentsPage.goToThedocumentDetailsPage()).toBeTruthy(); + //Verify that Add new popup is closed + expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeFalsy(); }); diff --git a/frontend/tests/test/SettingsTests.Spec.ts b/frontend/tests/test/SettingsTests.Spec.ts index cd8fe2c1..a32901ad 100644 --- a/frontend/tests/test/SettingsTests.Spec.ts +++ b/frontend/tests/test/SettingsTests.Spec.ts @@ -33,7 +33,6 @@ test('Verify that all the Beta tools are displayed when user enable beta tools t page, }) => { const homePage = new HomePage(page); - const leftMenuPage = new MenuPage(page); const settingsPage = new SettingsPage(page); const getSettingsList = SettingsData.allSettingsList(); @@ -48,7 +47,7 @@ test('Verify that all the Beta tools are displayed when user enable beta tools t await settingsPage.clickOnToggleButton(settings.BetaTools, true); //Go to the home page and verify the language text is displayed - await leftMenuPage.clickOnCrowdRocks(); + await homePage.clickOnCrowdRocks(); expect(await homePage.isLanguageTextVisible()).toBeTruthy(); //Expand the menu and click on settings @@ -58,7 +57,7 @@ test('Verify that all the Beta tools are displayed when user enable beta tools t await settingsPage.clickOnToggleButton(settings.BetaTools, false); //Go to the home page and verify the language text is hide - await leftMenuPage.clickOnCrowdRocks(); + await homePage.clickOnCrowdRocks(); expect(await homePage.isLanguageTextVisible(false)); }); diff --git a/frontend/tests/testData/gifSample.gif b/frontend/tests/testData/gifSample.gif new file mode 100644 index 0000000000000000000000000000000000000000..d41b6a1579eeeee5dda70b40d02c4b0f2a56971f GIT binary patch literal 40316 zcmY(q2T)T{*YAB&34{`Q=poe5B=o8Y(m@PC>1qhQSLtf#T|<$MhTb*wB4_|XL{X3; zMHEy}!GaxZd_3=S?|kN@5C~USR}>0?LZKq94}XY3p;6u4-P7aaXcUS{ zrQ&cHG#Z6Qqpk7ywzjsMoScM&1ZzAlhfKtvQHS4cZEayNXbcA9>Pp6AFhn8|hek(6 zM&fZ8eSQ7u>1iSk)7{;M!{Nrq#{mE!;&FHkI)Q9WCX=bIuIR(h0aPkcKOrH~m8k!5 zYb(W?cxWXWg;Zg#2b(KX4MEyu>>xJ=g zG9F)9S$Symp_4hThhE|jW8tc=-`&>cs*gFG%=$m}50mjYvMYJGyA6*LNVO(XsR2c<)?^~ll}tvV&_zX+b^i%o3e}aG z6G=^pq;^;41h^6p-A=I94T!}Uez zV^D`Vkz#FqxY_`K&?oAX4{wbpVla3r5&e8&dc3W!($(4(kE%ReL4EXLn2T}}>WXrv zrx%Ea0k=NPIus6rJB$hykDeaxPI1*ApB|@L;}^yc)2#b2l&)0Q?zZj(YYa8u&;&eH zU*FoAJbY+YWzoX)!pE(TCErMz)`zy>sIKJk@#({yBI*+( zBLgBM6Ap9iznAm@($4IZ!*L?XOhZi_0y-R({&z&t6Q`lBj>ix~{DVEB{6j-9<{q9= zp%HNyRZL7wjGD*cxX*t_)I39j0qK1xlm|EfRQ_|*|2$a$;s6jvh+8rlBPj@eCHF~Y z^;iZ<#=6q7qh>q@tr_ravZMCi70mH$ajVX{`-O@QE$;U_>mQV;drnnabu~;^=tXWn zyWiFL_&OnlL&CbdX|~p~Q0dH6ck^5$sn)v6x~FBK)wwHRZK|jB=}pR5wuDV@+j5uR zT+5jUz3r=gVXvmDZ2E4j-HQFXz4oB*=8HQt2vX9vpSdxX$*+9&VSmS~dvqC_YqkTO zn-5Ag1D`(}=z8;*aXd%z#9;Tkxh99!v(tk;J5QOO53ZfK)%#(!KXT{!^sT;6FIXu^ zDZ8Qm&#xv6mCrpI8uXu~%&GHsJq2a1xREO0=(mxE z_G#Kk7mtp;CaRE$p(9k77%*7KSv@HOnMEP;Vl&l8kUU0Avpj7_^%1CqGZT~p8Sft# z(s+{jDqmal9Sst|R0Q*?427j4EL8RZh_fVPvzSw*d6Sot-6V~~1+i${V(#?K;-Jpu z%>wSIeK1laglWRT_I8F)kr?r=0pe<~3r@$;!$v>~;@jTWb0sOXVovcHAnTa5q6s@* zZ@zzW&S`wRrv-7w&CTkrM`g#E74 z4)e-HKjwz)`*>M6+KUeA;<2O=VO68-euw`VsIgwzCRgQTwHaqnPdgPgI`EK6tGl}R zrCAlUI&mu)0=FYU5z>U6*6xSo){i%@_u`a?cBgKsa)PtfCpcuZ-tQtF8B~P8{`^Dk zHsnjvKZBqGLA$+Ie<&mi+tC9ept89$AI7+BREXWeUzNf*B`%2{=fXNw(>Rn&)sr9d z#3X>Gc=swJ?()e>XjTSIxOEN16su1*|G4iAX;$K#)|iqNnC_{rYj~ys|MPE~z;qK` z55FgQ$@aWSZ+RozmOs(ttcp_}?o|3RXZs@{f$=tbJg?84n>BBDDk`BrC$p$WV4JPWk- zD2tg~op|XQaV+W8nZ&!ix`{~~vZfE)o@j*PfSoS|yRjx>DjZ53D^s_KxoVghBHL64 zYZo?s?03ZYv_{UK-;-BRKR)x_Z2k2u%a;Wj

5^m|ZWQAcYo^_=hNnc@tJxo4Qfv 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 mHUkcDvvNHk{je?0ZxG+ Date: Tue, 5 Dec 2023 18:57:27 +0530 Subject: [PATCH 04/26] Fix the directory path --- frontend/tests/constants/DocumentConstants.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/tests/constants/DocumentConstants.ts b/frontend/tests/constants/DocumentConstants.ts index 1ac5fef3..2f46afa5 100644 --- a/frontend/tests/constants/DocumentConstants.ts +++ b/frontend/tests/constants/DocumentConstants.ts @@ -1,8 +1,10 @@ import path from 'path'; +import { fileURLToPath } from 'url'; // Define the base directory for test data -const baseTestDataDirectory = - 'D:/Etenlabs/Repos/Latest/crowd.rocks/frontend/tests/testData/'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const baseTestDataDirectory = path.join(__dirname, '../testData/'); // Define the constants const constants = { From c8bd4d40847ac1c9264facfc0512f24b740b52d1 Mon Sep 17 00:00:00 2001 From: Piyush Patel Date: Fri, 8 Dec 2023 12:21:43 +0530 Subject: [PATCH 05/26] Added Aws secrets to the test.yml file --- .github/workflows/test.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 314d2c2c..2f19c2f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,13 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} + aws-region: us-east-2 + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 From 49c56f917c911d14afbe8da06dff3cd0bab787ae Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 16:12:49 +0100 Subject: [PATCH 06/26] fix env variables --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2f19c2f4..e1bda4a6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,6 +85,10 @@ jobs: services: | postgres api + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} + AWS_REGION: us-east-2 - run: cd utils && npm ci From 0d1f60da8858119250ee73d0da1f17a323324708 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 17:22:26 +0100 Subject: [PATCH 07/26] remove some tests --- frontend/tests/test/AppLanguageTests.Spec.ts | 97 ----- .../CommunityEndToEndFlowTest.Spec.ts | 139 -------- .../CommunityTests/CommunityTests.Spec.ts | 279 --------------- .../CommunityThreadsTest.Spec.ts | 307 ---------------- .../CommunityTests/CommunityTopicTest.Spec.ts | 335 ------------------ frontend/tests/test/LoginTests.Spec.ts | 216 ----------- ...dBlankEmailErrorMessage-chromium-linux.png | Bin 21841 -> 0 bytes ...Login-emailErrorMessage-chromium-linux.png | Bin 18910 -> 0 bytes ...in-passwordErrorMessage-chromium-linux.png | Bin 20480 -> 0 bytes frontend/tests/test/MyProfileTests.Spec.ts | 108 ------ frontend/tests/test/RegistrationTests.Spec.ts | 169 --------- .../emailErrorMessage-chromium-linux.png | Bin 22254 -> 0 bytes ...nvalidEmailErrorMessage-chromium-linux.png | Bin 24269 -> 0 bytes .../passwordErrorMessage-chromium-linux.png | Bin 24561 -> 0 bytes .../usernameErrorMessage-chromium-linux.png | Bin 22527 -> 0 bytes frontend/tests/test/SettingsTests.Spec.ts | 102 ------ 16 files changed, 1752 deletions(-) delete mode 100644 frontend/tests/test/AppLanguageTests.Spec.ts delete mode 100644 frontend/tests/test/CommunityTests/CommunityEndToEndFlowTest.Spec.ts delete mode 100644 frontend/tests/test/CommunityTests/CommunityTests.Spec.ts delete mode 100644 frontend/tests/test/CommunityTests/CommunityThreadsTest.Spec.ts delete mode 100644 frontend/tests/test/CommunityTests/CommunityTopicTest.Spec.ts delete mode 100644 frontend/tests/test/LoginTests.Spec.ts delete mode 100644 frontend/tests/test/LoginTests.Spec.ts-snapshots/ForgotPasswordBlankEmailErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/LoginTests.Spec.ts-snapshots/Login-emailErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/LoginTests.Spec.ts-snapshots/Login-passwordErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/MyProfileTests.Spec.ts delete mode 100644 frontend/tests/test/RegistrationTests.Spec.ts delete mode 100644 frontend/tests/test/RegistrationTests.Spec.ts-snapshots/emailErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/RegistrationTests.Spec.ts-snapshots/invalidEmailErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/RegistrationTests.Spec.ts-snapshots/passwordErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/RegistrationTests.Spec.ts-snapshots/usernameErrorMessage-chromium-linux.png delete mode 100644 frontend/tests/test/SettingsTests.Spec.ts diff --git a/frontend/tests/test/AppLanguageTests.Spec.ts b/frontend/tests/test/AppLanguageTests.Spec.ts deleted file mode 100644 index 38d81bdb..00000000 --- a/frontend/tests/test/AppLanguageTests.Spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { expect, test } from '@playwright/test'; -import MenuPage from '../pages/MenuPage'; -import HomePage from '../pages/HomePage'; -import pageUrls from '../constants/PageUrls'; -import { language, leftMenu } from '../enums/Enums'; -import AppLanguagePage from '../pages/AppLanguagePage'; -import AppLanguageData from '../data-factory/AppLanguageData'; - -test('1: Verify that the user is navigated to App Language page & able to change the app language', async ({ - page, -}) => { - const homePage = new HomePage(page); - const leftMenuPage = new MenuPage(page); - const appLanguagePage = new AppLanguagePage(page); - - //Navigate to the URL - await page.goto(pageUrls.HomePage); - - //Expand the menu and click on app language - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.AppLanguage); - - //Verify setting page title is displayed - expect(await appLanguagePage.isAppLanguagePopUpTitleVisible()).toBeTruthy(); - - //Verify that by default English language is selected - expect(await appLanguagePage.isAppLanguageChecked(language.English)).toEqual( - '#476FFF', - ); - - //select the particular language and click on confirm button - await appLanguagePage.clickOnAppLanguageName(language.Hindi); - await appLanguagePage.clickOnConfirmButton(); - - //verify that preselected language is displayed - expect(await homePage.getHomePageTitle()).toEqual('मिडिया'); -}); - -test('2: Verify that user can check the different available lanugages', async ({ - page, -}) => { - const homePage = new HomePage(page); - const leftMenuPage = new MenuPage(page); - const appLanguagePage = new AppLanguagePage(page); - - //Navigate to the URL - await page.goto(pageUrls.HomePage); - - //Expand the menu and click on app language - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.AppLanguage); - - //Verify setting page title is displayed - expect(await appLanguagePage.isAppLanguagePopUpTitleVisible()).toBeTruthy(); - - //Verifying that user can select all languages - for (const lang of AppLanguageData.allLanguages()) { - await appLanguagePage.clickOnAppLanguageName(lang); - expect(await appLanguagePage.isAppLanguageChecked(lang)).toEqual('#476FFF'); - } -}); - -test('3: Verify that the default selected language remains selected when user changes the language and click on the cancel button', async ({ - page, -}) => { - const homePage = new HomePage(page); - const leftMenuPage = new MenuPage(page); - const appLanguagePage = new AppLanguagePage(page); - - //Navigate to the URL - await page.goto(pageUrls.HomePage); - - //Expand the menu and click on app language - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.AppLanguage); - - //Verify setting page title is displayed - expect(await appLanguagePage.isAppLanguagePopUpTitleVisible()).toBeTruthy(); - - //Verify that by default English language is selected - expect(await appLanguagePage.isAppLanguageChecked(language.English)).toEqual( - '#476FFF', - ); - - //Select the particular language and click on confirm button - await appLanguagePage.clickOnAppLanguageName(language.Hindi); - await appLanguagePage.clickOnCancelButton(); - - //Expand the menu and click on app language - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.AppLanguage); - - //Verify that preselected language is displayed - expect(await appLanguagePage.isAppLanguageChecked(language.English)).toEqual( - '#476FFF', - ); -}); diff --git a/frontend/tests/test/CommunityTests/CommunityEndToEndFlowTest.Spec.ts b/frontend/tests/test/CommunityTests/CommunityEndToEndFlowTest.Spec.ts deleted file mode 100644 index 610499eb..00000000 --- a/frontend/tests/test/CommunityTests/CommunityEndToEndFlowTest.Spec.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { chromium, expect, test } from '@playwright/test'; -import ForumsPage from '../../pages/Community/ForumsPage'; -import RegistrationPage from '../../pages/RegistrationPage'; -import RegisterData from '../../data-factory/RegisterData'; -import LoginPage from '../../pages/LoginPage'; -import pageUrls from '../../constants/PageUrls'; -import { community } from '../../enums/Enums'; -import TopicsPage from '../../pages/Community/TopicsPage'; -import PostPage from '../../pages/Community/PostPage'; -import ThreadsPage from '../../pages/Community/ThreadsPage'; -import CommonPage from '../../pages/Community/CommonPage'; -import HomePage from '../../pages/HomePage'; - -const registerData = RegisterData.validRegisterData(); -const forumName = 'Automation Forum ' + Math.random(); -const forumDescription = 'Automation Forum Description ' + Math.random(); -const topicName = 'Automation Topic ' + Math.random(); -const topicDescription = 'Automation Topic Description ' + Math.random(); -const threadNameOne = 'Automation Thread one ' + Math.random(); -const postTextMessage = 'Automation Post Message' + Math.random(); -test.use({ storageState: { cookies: [], origins: [] } }); - -test.beforeAll(async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const registerPage = new RegistrationPage(page); - const forumsPage = new ForumsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - - //Navigate to the URL - await page.goto(pageUrls.RegisterPage); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - await page.waitForTimeout(4000); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Click on the add new button and verify that 'add new forum' popup is appeared - await commonPage.clickOnAddNewButton(community.Forums); - - //Create a new forum - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - await browser.close(); -}); - -test('1: End to end linear flow for Community forums', async ({ page }) => { - const commonPage = new CommonPage(page); - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const threadsPage = new ThreadsPage(page); - const postPage = new PostPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new topic - await commonPage.clickOnAddNewButton(community.Topics); - expect(await topicsPage.isAddNewTopicPopupVisible()).toBeTruthy(); - await topicsPage.fillTopicDetails(topicName, topicDescription); - await commonPage.clickOnCreateNewButton(); - await expect( - page.getByText('Success at creating new forum folder!'), - ).toBeVisible(); - - //Create a new thread - await topicsPage.clickOnTheTopic(topicName); - await commonPage.clickOnAddNewButton(community.Threads); - await page.waitForTimeout(2000); - expect(await threadsPage.isAddNewThreadPopupVisible()).toBeTruthy(); - await threadsPage.fillThreadName(threadNameOne); - await commonPage.clickOnCreateNewButton(); - await expect(page.getByText('Success at creating new thread!')).toBeVisible(); - - //Create a new two posts - await threadsPage.clickOnThreadName(threadNameOne); - await postPage.createNewPost(postTextMessage, 2); - - //Get posts count from the post page and verify that on the threads page - const expectedPostsCount = await postPage.getPostsCount(); - await postPage.clickOnBackArrowButton(); - expect(await threadsPage.getPostsCount(threadNameOne)).toEqual( - expectedPostsCount.toLocaleString(), - ); - - //Get threads count from the threads page & Verify Threads, Posts count on the topics page - const expectedThreadsCount = await threadsPage.getThreadsCount(); - await threadsPage.clickOnBackArrowButton(topicName); - expect(await topicsPage.getThreadsCount(topicName)).toEqual( - expectedThreadsCount.toLocaleString(), - ); - expect(await topicsPage.getPostsCount(topicName)).toEqual( - expectedPostsCount.toLocaleString(), - ); -}); - -test.afterAll('Delete Forum', async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const forumsPage = new ForumsPage(page); - const commonPage = new CommonPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const forumsList = [forumName]; - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Delete all forums - for (const forum of forumsList) { - await commonPage.searchName(forum.toLowerCase()); - await forumsPage.deleteForum(forum); - } - await browser.close(); -}); diff --git a/frontend/tests/test/CommunityTests/CommunityTests.Spec.ts b/frontend/tests/test/CommunityTests/CommunityTests.Spec.ts deleted file mode 100644 index 4fd8d345..00000000 --- a/frontend/tests/test/CommunityTests/CommunityTests.Spec.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { chromium, expect, test } from '@playwright/test'; -import RegistrationPage from '../../pages/RegistrationPage'; -import RegisterData from '../../data-factory/RegisterData'; -import LoginPage from '../../pages/LoginPage'; -import pageUrls from '../../constants/PageUrls'; -import ForumsPage from '../../pages/Community/ForumsPage'; -import HomePage from '../../pages/HomePage'; -import CommonPage from '../../pages/Community/CommonPage'; -import { community } from '../../enums/Enums'; - -const registerData = RegisterData.validRegisterData(); -const forumName = 'Automation Forum ' + Math.random(); -const forumDescription = 'Automation Forum Description ' + Math.random(); -const editedForumName = 'Automation Edited Forum ' + Math.random(); -const forumNameWithoutDescription = - 'Automation Forum without Description ' + Math.random(); -test.use({ storageState: { cookies: [], origins: [] } }); - -test.beforeAll(async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const registerPage = new RegistrationPage(page); - - //Navigate to the URL - await page.goto(pageUrls.RegisterPage); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - await page.waitForTimeout(4000); -}); - -test('1: Verify that user redirected on community page and able to create new forums', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on community tab and verify that user redirected on community page - await homePage.clickOnCommunitySection(); - expect(await forumsPage.isPageTitleVisible()).toBeTruthy(); - - //Click on the add new button and verify that 'add new forum' popup is appeared - await commonPage.clickOnAddNewButton(community.Forums); - expect(await forumsPage.isAddNewForumPopupVisible()).toBeTruthy(); - - //Create a new forum - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum!', - ); - - //Verify the created forum is displayed on the forums page - await page.waitForTimeout(4000); - expect(await commonPage.isCreatedCommunityVisible(forumName)).toBeTruthy(); -}); - -test('2: Verify that user is not allow to create a forum with a Forum Name which is already exist', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on community tab and verify that user redirected on community page - await homePage.clickOnCommunitySection(); - expect(await forumsPage.isPageTitleVisible()).toBeTruthy(); - - //Click on the add new button and verify that 'add new forum' popup is appeared - await commonPage.clickOnAddNewButton(community.Forums); - expect(await forumsPage.isAddNewForumPopupVisible()).toBeTruthy(); - - //Create a new forum - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Failed at creating new forum! [ForumUpsertFailed]', - ); -}); - -test('3: Verify that search functionality is working properly', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the URL - await homePage.clickOnCommunitySection(); - - //Verify that user can search the forum by using search bar - await commonPage.searchName(forumName.toLowerCase()); - expect(await commonPage.isCreatedCommunityVisible(forumName)).toBeTruthy(); -}); - -test('4: Verify that user is able to create forum without adding the description', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Forums); - await forumsPage.fillForumDetails(forumNameWithoutDescription, ''); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum!', - ); -}); - -test('5: Verify that validation message is appeared when user passes blank forum details', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Create a new forum - await commonPage.clickOnAddNewButton(community.Forums); - await forumsPage.fillForumDetails('', ''); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Forum name cannot be empty string!', - ); -}); - -test('6: Verify that validation message is appeared when user only enters forum description', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Create a new forum - await commonPage.clickOnAddNewButton(community.Forums); - await forumsPage.fillForumDetails('', 'Test Description'); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Forum name cannot be empty string!', - ); -}); - -test('7: Verify that forum is not created when click on cancel button after entering the valid forum details', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Create a new forum - await commonPage.clickOnAddNewButton(community.Forums); - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - //verify that forum is not created - expect(await forumsPage.isAddNewForumPopupVisible()).toBeFalsy(); -}); - -test('8: Verify that user can edit the created forum and can search the edited forum using search bar', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - const forumDescriptionEdit = 'TestForum Description Edit' + Math.random(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Edit the forum details and click on the save button - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnEditForumButton(forumName); - await forumsPage.fillForumDetails(editedForumName, forumDescriptionEdit); - await commonPage.clickOnSaveButton(); - - //Verify the Validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at updating forum!', - ); - //Verify the edited forum is displayed on the forums page - await page.waitForTimeout(4000); - await commonPage.searchName(editedForumName.toLowerCase()); - expect( - await commonPage.isCreatedCommunityVisible(editedForumName), - ).toBeTruthy(); -}); - -test.afterAll('Delete Forum', async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - const forumsList = [editedForumName, forumNameWithoutDescription]; - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Delete all forums - for (const forum of forumsList) { - await commonPage.searchName(forum.toLowerCase()); - await forumsPage.deleteForum(forum); - } - await browser.close(); -}); diff --git a/frontend/tests/test/CommunityTests/CommunityThreadsTest.Spec.ts b/frontend/tests/test/CommunityTests/CommunityThreadsTest.Spec.ts deleted file mode 100644 index 6600b9f8..00000000 --- a/frontend/tests/test/CommunityTests/CommunityThreadsTest.Spec.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { Page, chromium, expect, test } from '@playwright/test'; -import RegistrationPage from '../../pages/RegistrationPage'; -import RegisterData from '../../data-factory/RegisterData'; -import LoginPage from '../../pages/LoginPage'; -import pageUrls from '../../constants/PageUrls'; -import ForumsPage from '../../pages/Community/ForumsPage'; -import CommonPage from '../../pages/Community/CommonPage'; -import HomePage from '../../pages/HomePage'; -import { community } from '../../enums/Enums'; -import TopicsPage from '../../pages/Community/TopicsPage'; -import ThreadsPage from '../../pages/Community/ThreadsPage'; - -const registerData = RegisterData.validRegisterData(); -const forumName = 'Automation Forum ' + Math.random(); -const forumDescription = 'Automation Forum Description ' + Math.random(); -const threadName = 'Automation thread ' + Math.random(); -const editedThreadName = 'Automation Edited thread ' + Math.random(); -const topicName = 'Automation Topic Name ' + Math.random(); -const topicDescription = 'Automation Topic Description ' + Math.random(); -test.use({ storageState: { cookies: [], origins: [] } }); - -test.beforeAll(async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const registerPage = new RegistrationPage(page); - const forumsPage = new ForumsPage(page); - const topicsPage = new TopicsPage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - - //Navigate to the URL - await page.goto(pageUrls.RegisterPage); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - await page.waitForTimeout(4000); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on community tab and verify that user redirected on community page - await homePage.clickOnCommunitySection(); - expect(await forumsPage.isPageTitleVisible()).toBeTruthy(); - - //Click on the add new button and verify that 'add new forum' popup is appeared - await commonPage.clickOnAddNewButton(community.Forums); - expect(await forumsPage.isAddNewForumPopupVisible()).toBeTruthy(); - - //Create a new forum - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum!', - ); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new topic - await commonPage.clickOnAddNewButton(community.Topics); - expect(await topicsPage.isAddNewTopicPopupVisible()).toBeTruthy(); - await topicsPage.fillTopicDetails(topicName, topicDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum folder!', - ); - await browser.close(); -}); - -async function navigateToThreadsPage( - page: Page, - loginPage: LoginPage, - homePage: HomePage, - forumsPage: ForumsPage, - topicsPage: TopicsPage, - commonPage: CommonPage, -) { - //Login with valid credentials - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - await topicsPage.clickOnTheTopic(topicName); -} - -test('1: Verify that user is able to create new thread successfully', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - const threadsPage = new ThreadsPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - - //Create a new thread - await commonPage.clickOnAddNewButton(community.Threads); - expect(await threadsPage.isAddNewThreadPopupVisible()).toBeTruthy(); - await threadsPage.fillThreadName(threadName); - await commonPage.clickOnCreateNewButton(); - - //Verify that created topic is displayed on the topic page - await commonPage.searchName(threadName.toLowerCase()); - expect(await commonPage.isCreatedCommunityVisible(threadName)).toBeTruthy(); -}); - -test('2: Verify that user is not allowed to create a thread with a thread Name which is already exist', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - const threadsPage = new ThreadsPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - - //Create a new thread - await commonPage.clickOnAddNewButton(community.Threads); - expect(await threadsPage.isAddNewThreadPopupVisible()).toBeTruthy(); - await threadsPage.fillThreadName(threadName); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Failed at creating new thread! [ThreadUpsertFailed]', - ); -}); - -test('3: Verify that search functionality is working properly', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - - //Verify that user can search the forum by using search bar - await commonPage.searchName(threadName.toLowerCase()); - expect(await commonPage.isCreatedCommunityVisible(threadName)).toBeTruthy(); -}); - -test('5: Verify that validation message is appeared when user passes blank thread name', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const threadsPage = new ThreadsPage(page); - const commonPage = new CommonPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Threads); - await threadsPage.fillThreadName(''); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Thread name cannot be empty string!', - ); -}); - -test('6: Verify that thread is not created when click on cancel button after entering the valid thread name', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const threadsPage = new ThreadsPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Threads); - await threadsPage.fillThreadName(threadName); - await commonPage.clickOnCancelButton(); - - //Verify the validation messsage - expect(await threadsPage.isAddNewThreadPopupVisible()).toBeFalsy(); -}); - -test('7: Verify that user can edit the created topic and can search the edited topic using search bar', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const threadsPage = new ThreadsPage(page); - - //Navigate to the threads page - await navigateToThreadsPage( - page, - loginPage, - homePage, - forumsPage, - topicsPage, - commonPage, - ); - - //Edit the forum details and click on the save button - await commonPage.searchName(threadName.toLowerCase()); - await threadsPage.clickOnEditButton(threadName); - await threadsPage.fillThreadName(editedThreadName); - await commonPage.clickOnSaveButton(); - - //Verify the Validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at updating thread!', - ); - //Verify the edited forum is displayed on the forums page - await page.waitForTimeout(4000); - await commonPage.searchName(editedThreadName.toLowerCase()); - expect( - await commonPage.isCreatedCommunityVisible(editedThreadName), - ).toBeTruthy(); -}); - -test.afterAll('Delete Forum', async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Delete all forums - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.deleteForum(forumName); - await browser.close(); -}); diff --git a/frontend/tests/test/CommunityTests/CommunityTopicTest.Spec.ts b/frontend/tests/test/CommunityTests/CommunityTopicTest.Spec.ts deleted file mode 100644 index ada711c8..00000000 --- a/frontend/tests/test/CommunityTests/CommunityTopicTest.Spec.ts +++ /dev/null @@ -1,335 +0,0 @@ -import { chromium, expect, test } from '@playwright/test'; -import RegistrationPage from '../../pages/RegistrationPage'; -import RegisterData from '../../data-factory/RegisterData'; -import LoginPage from '../../pages/LoginPage'; -import pageUrls from '../../constants/PageUrls'; -import ForumsPage from '../../pages/Community/ForumsPage'; -import CommonPage from '../../pages/Community/CommonPage'; -import HomePage from '../../pages/HomePage'; -import { community } from '../../enums/Enums'; -import TopicsPage from '../../pages/Community/TopicsPage'; - -const registerData = RegisterData.validRegisterData(); -const forumName = 'Automation Forum ' + Math.random(); -const forumDescription = 'Automation Forum Description ' + Math.random(); -const topicName = 'Automation Topic ' + Math.random(); -const topicDescription = 'Automation Topic Description ' + Math.random(); -const topicWithoutDescription = - 'Automation topic without description' + Math.random(); -const editedTopicName = 'Automation Edited topic ' + Math.random(); -test.use({ storageState: { cookies: [], origins: [] } }); - -test.beforeAll(async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const registerPage = new RegistrationPage(page); - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.RegisterPage); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - await page.waitForTimeout(4000); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on community tab and verify that user redirected on community page - await homePage.clickOnCommunitySection(); - expect(await forumsPage.isPageTitleVisible()).toBeTruthy(); - - //Click on the add new button and verify that 'add new forum' popup is appeared - await commonPage.clickOnAddNewButton(community.Forums); - expect(await forumsPage.isAddNewForumPopupVisible()).toBeTruthy(); - - //Create a new forum - await forumsPage.fillForumDetails(forumName, forumDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum!', - ); - - await browser.close(); -}); - -test('1: Verify that user is able to create new topic successfully', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Login with valid credentials - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new topic - await commonPage.clickOnAddNewButton(community.Topics); - expect(await topicsPage.isAddNewTopicPopupVisible()).toBeTruthy(); - await topicsPage.fillTopicDetails(topicName, topicDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify that created topic is displayed on the topic page - await commonPage.searchName(topicName.toLowerCase()); - expect(await commonPage.isCreatedCommunityVisible(topicName)).toBeTruthy(); -}); - -test('2: Verify that user is not allowed to create a topic with a topic Name which is already exist', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Login with valid credentials - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new topic - await commonPage.clickOnAddNewButton(community.Topics); - expect(await topicsPage.isAddNewTopicPopupVisible()).toBeTruthy(); - await topicsPage.fillTopicDetails(topicName, topicDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Failed at creating new forum folder! [ForumFolderUpsertFailed]', - ); -}); - -test('3: Verify that search functionality is working properly', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Verify that user can search the forum by using search bar - await commonPage.searchName(topicName.toLowerCase()); - expect(await commonPage.isCreatedCommunityVisible(topicName)).toBeTruthy(); -}); - -test('4: Verify that user is able to create topic without adding the description', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const topicsPage = new TopicsPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Topics); - await topicsPage.fillTopicDetails(topicWithoutDescription, ''); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at creating new forum folder!', - ); -}); - -test('5: Verify that validation message is appeared when user passes blank topics details', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const topicsPage = new TopicsPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Topics); - await topicsPage.fillTopicDetails('', ''); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Topic name cannot be empty string!', - ); -}); - -test('6: Verify that validation message is appeared when user passes only description', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const topicsPage = new TopicsPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Topics); - await topicsPage.fillTopicDetails('', topicDescription); - await commonPage.clickOnCreateNewButton(); - - //Verify the validation messsage - expect(await commonPage.getValidationMessage()).toEqual( - 'Topic name cannot be empty string!', - ); -}); - -test('7: Verify that topic is not created when click on cancel button after entering the valid topic details', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on the community forum - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Create a new forum without adding the description - await commonPage.clickOnAddNewButton(community.Topics); - await topicsPage.fillTopicDetails(topicName, topicDescription); - await commonPage.clickOnCancelButton(); - - //Verify the validation messsage - expect(await topicsPage.isAddNewTopicPopupVisible()).toBeFalsy(); -}); - -test('8: Verify that user can edit the created topic and can search the edited topic using search bar', async ({ - page, -}) => { - const forumsPage = new ForumsPage(page); - const loginPage = new LoginPage(page); - const topicsPage = new TopicsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - const topicDescriptionEdit = 'TestTopic Description Edit' + Math.random(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Search the forum name and click on the forum - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.clickOnTheForum(forumName); - - //Edit the forum details and click on the save button - await commonPage.searchName(topicName.toLowerCase()); - await topicsPage.clickOnEditButton(topicName); - await topicsPage.fillTopicDetails(editedTopicName, topicDescriptionEdit); - await commonPage.clickOnSaveButton(); - - //Verify the Validation message - expect(await commonPage.getValidationMessage()).toEqual( - 'Success at updating forum folder!', - ); - //Verify the edited forum is displayed on the forums page - await page.waitForTimeout(4000); - await commonPage.searchName(editedTopicName.toLowerCase()); - expect( - await commonPage.isCreatedCommunityVisible(editedTopicName), - ).toBeTruthy(); -}); - -test.afterAll('Delete Forum', async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const forumsPage = new ForumsPage(page); - const homePage = new HomePage(page); - const loginPage = new LoginPage(page); - const commonPage = new CommonPage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Navigate to the forums page - await homePage.clickOnCommunitySection(); - - //Delete all forums - await commonPage.searchName(forumName.toLowerCase()); - await forumsPage.deleteForum(forumName); - await browser.close(); -}); diff --git a/frontend/tests/test/LoginTests.Spec.ts b/frontend/tests/test/LoginTests.Spec.ts deleted file mode 100644 index bc5a3a2f..00000000 --- a/frontend/tests/test/LoginTests.Spec.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { expect, test } from '@playwright/test'; -import LoginPO from '../pages/LoginPage'; -import HomePO from '../pages/HomePage'; -import RegisterPO from '../pages/RegistrationPage'; -import LoginData from '../data-factory/LoginData'; -import pageUrls from '../constants/PageUrls'; -test.use({ storageState: { cookies: [], origins: [] } }); - -test.skip('1: Verify that user is logged in with valid data', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - const homePage = new HomePO(page); - const validLoginData = LoginData.validLoginData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login with valid credentials - await loginPage.loginToApp(validLoginData); - - //Verify user is navigated to home page - expect(await homePage.isHomePageVisible()).toBeTruthy(); -}); - -test('2: Verify that validation message is shown when try to login with invalid data in both field', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - const invalidLoginData = LoginData.inValidLoginData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login with invalid credentials - await loginPage.loginToApp(invalidLoginData); - - //Verify that validation message is displayed - expect(await loginPage.getValidationMessage()).toContain( - 'Invalid email or password', - ); -}); - -test('3: Verify that validation message is shown for email when try to login with invalid email', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - const invalidEmailData = LoginData.inValidEmailData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login with invalid email - await loginPage.loginToApp(invalidEmailData); - - //Verify the validation message is displayed for invalid email - expect(await loginPage.getValidationMessage()).toContain( - 'Invalid email or password', - ); -}); - -test('4: Verify that validation message is shown for password when try to login with invalid password', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - const invalidPasswordData = LoginData.inValidPasswordData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login with invalid details - await loginPage.loginToApp(invalidPasswordData); - - //Verify the validation message is displayed for invalid password - expect(await loginPage.getValidationMessage()).toContain( - 'Invalid email or password', - ); -}); - -test.skip('5: Verify that email field is mandatory', async ({ page }) => { - const loginPage = new LoginPO(page); - const loginDataWithoutEmail = LoginData.withoutEmailData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login without email - await loginPage.loginToApp(loginDataWithoutEmail); - - //Verify the validation message is displayed for email - await expect(page).toHaveScreenshot('Login_emailErrorMessage.png'); -}); - -test.skip('6: Verify that password field is mandatory', async ({ page }) => { - const loginPage = new LoginPO(page); - const loginDataWithoutPassword = LoginData.withoutPasswordData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Login without password - await loginPage.loginToApp(loginDataWithoutPassword); - - //Verify the validation message is displayed for password - await expect(page).toHaveScreenshot('Login_passwordErrorMessage.png'); -}); - -test('7:Verify that user is redirected to the Register page after clicking on the Register button', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - const register = new RegisterPO(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Navigate to register page - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await register.isRegisterPageTitleVisible()).toBeTruthy(); -}); - -test('8:Verify that user is redirected to the forgot password page after clicking on the forgot password button', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Click on the forgot password button - await loginPage.clickOnForgotPasswordButton(); - - //Verify that user is navigated to forgot password page - expect(await loginPage.isForgotPasswordTitleVisible()).toBeTruthy(); -}); - -test('9:Verify that validation message is display when user clicks on the "SEND PASSWORD RESET EMAIL" button after passing the valid email', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Click on the forgot password button - await loginPage.clickOnForgotPasswordButton(); - - //Verify that user is navigated to forgot password page - expect(await loginPage.isForgotPasswordTitleVisible()).toBeTruthy(); - - //Enter valid email address - await loginPage.fillEmailIdForResetPassword( - LoginData.validEmailForResetPassword(), - ); - - //Click on the "SEND PASSWORD RESET EMAIL" button - await loginPage.clickOnSendResetPasswordEmailButton(); - - //Verify the validation message is displayed for valid email - expect(await loginPage.getForgotPasswordValidationMessage()).toContain( - 'If your email exists in our database a reset link has been sent.', - ); -}); - -test('10:Verify that validation message is display when user clicks on the "SEND PASSWORD RESET EMAIL" button after passing the email in wrong format', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Click on the forgot password button - await loginPage.clickOnForgotPasswordButton(); - - //Verify that user is navigated to forgot password page - expect(await loginPage.isForgotPasswordTitleVisible()).toBeTruthy(); - - //Enter valid email address - await loginPage.fillEmailIdForResetPassword( - LoginData.invalidEmailForResetPassword(), - ); - - //Click on the "SEND PASSWORD RESET EMAIL" button - await loginPage.clickOnSendResetPasswordEmailButton(); - - //Verify the validation message is displayed for valid email - expect(await loginPage.getForgotPasswordValidationMessage()).toContain( - 'If your email exists in our database a reset link has been sent.', - ); -}); - -test.skip('11:Verify that validation message is shown when user clicks on the "SEND PASSWORD RESET EMAIL" button without entering the email', async ({ - page, -}) => { - const loginPage = new LoginPO(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Click on the forgot password button - await loginPage.clickOnForgotPasswordButton(); - - //Verify that user is navigated to forgot password page - expect(await loginPage.isForgotPasswordTitleVisible()).toBeTruthy(); - - //Click on the "SEND PASSWORD RESET EMAIL" button - await loginPage.clickOnSendResetPasswordEmailButton(); - - //Verify the validation message is displayed for blank email - await expect(page).toHaveScreenshot( - 'ForgotPasswordBlankEmailErrorMessage.png', - ); -}); diff --git a/frontend/tests/test/LoginTests.Spec.ts-snapshots/ForgotPasswordBlankEmailErrorMessage-chromium-linux.png b/frontend/tests/test/LoginTests.Spec.ts-snapshots/ForgotPasswordBlankEmailErrorMessage-chromium-linux.png deleted file mode 100644 index 3ceaa6ec46133d2987893349983dc2fc48f964a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21841 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 diff --git a/frontend/tests/test/LoginTests.Spec.ts-snapshots/Login-passwordErrorMessage-chromium-linux.png b/frontend/tests/test/LoginTests.Spec.ts-snapshots/Login-passwordErrorMessage-chromium-linux.png deleted file mode 100644 index 192f5c4edaffbc2cb4bcd2f5478be1531a72431d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 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 { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - const page = await context.newPage(); - const registerPage = new RegistrationPage(page); - - //Navigate to the URL - await page.goto(pageUrls.RegisterPage); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - await page.waitForTimeout(4000); -}); - -test('1: Verify that user can navigate to profile page and able to edit username on profile page', async ({ - page, -}) => { - const homePage = new HomePO(page); - const leftMenuPage = new MenuPage(page); - const loginPage = new LoginPage(page); - const profilePage = new ProfilePage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on left menu for myprofile and verify the page title - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.MyProfile); - expect(await profilePage.isPageTitlePresent()).toBeTruthy(); - - //Verify the username is equal to register username - expect(await profilePage.getUsernameText()).toEqual(registerData.username); - - //Edit the username and click on submit button - await profilePage.editUsername(updatedUsername); - await profilePage.clickOnSubmitButton(); - await profilePage.clickOnUsernameText(); - await profilePage.clickOnSubmitButton(); - - //Verify the username is equal to the 'AutomationUser2' - expect(await profilePage.getUsernameText()).toEqual(updatedUsername); -}); - -test('2: Verify that username is not changed after clicking on the cancel button ', async ({ - page, -}) => { - const homePage = new HomePO(page); - const leftMenuPage = new MenuPage(page); - const loginPage = new LoginPage(page); - const profilePage = new ProfilePage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on left menu for myprofile and verify the page title - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.MyProfile); - expect(await profilePage.isPageTitlePresent()).toBeTruthy(); - - //Edit the username and click on cancel button - await profilePage.editUsername(registerData.username); - await profilePage.clickOnCancelButton(); - - //Click on username and cancel button and verify the username doesn't updated - await profilePage.clickOnUsernameText(); - await profilePage.clickOnCancelButton(); - expect(await profilePage.getUsernameText()).toEqual(updatedUsername); -}); - -test('3: Verify that user is naviagted to reset a password page ', async ({ - page, -}) => { - const homePage = new HomePO(page); - const leftMenuPage = new MenuPage(page); - const loginPage = new LoginPage(page); - const profilePage = new ProfilePage(page); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - await loginPage.loginToApp(registerData); - - //Click on left menu for myprofile and verify the page title - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.MyProfile); - - //Click on reset password button and verify the forgot password page title - await profilePage.clickOnResetPasswordButton(); - expect(await loginPage.isForgotPasswordTitleVisible()).toBeTruthy(); -}); diff --git a/frontend/tests/test/RegistrationTests.Spec.ts b/frontend/tests/test/RegistrationTests.Spec.ts deleted file mode 100644 index 2e90fea6..00000000 --- a/frontend/tests/test/RegistrationTests.Spec.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { test, expect } from '@playwright/test'; -import RegisterData from '../data-factory/RegisterData'; -import RegisterPO from '../pages/RegistrationPage'; -import LoginPO from '../pages/LoginPage'; -import HomePO from '../pages/HomePage'; -import MenuPO from '../pages/MenuPage'; -import LoginDTO from '../data-objects/LoginDto'; -import { leftMenu } from '../enums/Enums'; -import pageUrls from '../constants/PageUrls'; -test.use({ storageState: { cookies: [], origins: [] } }); - -test('1: Verify that user is register/logout and login again successfully', async ({ - page, -}) => { - const registerPage = new RegisterPO(page); - const loginPage = new LoginPO(page); - const homePage = new HomePO(page); - const leftMenuPage = new MenuPO(page); - const registerData = RegisterData.validRegisterData(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Verify the login header text - expect(await loginPage.isLoginPageTitleVisible()).toBeTruthy(); - - //Click on the 'Register' button - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form - await registerPage.fillRegistrationForm(registerData); - await registerPage.clickOnRegisterButton(); - - //Verify user is navigated to home page - expect(await homePage.isHomePageVisible()).toBeTruthy(); - - //logout from the app - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.Logout); - - //Login to the app with registered data - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.Login); - - const loginData = LoginDTO; - loginData.email = registerData.email; - loginData.password = registerData.password; - - //Login with valid credentials - await loginPage.loginToApp(loginData); - - //Verify user is logged in - expect(await homePage.isHomePageVisible()).toBeTruthy(); -}); - -test.skip('2: Verify that email field is mandatory', async ({ page }) => { - const registerPage = new RegisterPO(page); - const loginPage = new LoginPO(page); - const registerData = RegisterData.registerDataWithoutEmail(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Verify the login header text - expect(await loginPage.isLoginPageTitleVisible()).toBeTruthy(); - - //Click on the 'Register' button on login page - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill the register form without email - await registerPage.fillRegistrationForm(registerData); - - //click on register button - await registerPage.clickOnRegisterButton(); - - //verify the validation message is displayed for email - await expect(page).toHaveScreenshot('emailErrorMessage.png'); -}); - -test.skip('3: Verify that username field is mandatory', async ({ page }) => { - const registerPage = new RegisterPO(page); - const loginPage = new LoginPO(page); - const registerData = RegisterData.registerDataWithoutUserName(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Verify the login header text - expect(await loginPage.isLoginPageTitleVisible()).toBeTruthy(); - - //Click on the 'Register' button on login page - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill the register form withoutusername - await registerPage.fillRegistrationForm(registerData); - - //click on register button - await registerPage.clickOnRegisterButton(); - - //verify the validation message is displayed for username - await expect(page).toHaveScreenshot('usernameErrorMessage.png', { - threshold: 0.2, - }); -}); - -test.skip('4: Verify that password field is mandatory', async ({ page }) => { - const registerPage = new RegisterPO(page); - const loginPage = new LoginPO(page); - const registerData = RegisterData.registerDataWithoutPassword(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Verify the login header text - expect(await loginPage.isLoginPageTitleVisible()).toBeTruthy(); - - //Click on the 'Register' button on login page - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill the register form without password - await registerPage.fillRegistrationForm(registerData); - - //click on register button - await registerPage.clickOnRegisterButton(); - - //verify the validation message is displayed for password - await expect(page).toHaveScreenshot('passwordErrorMessage.png'); -}); - -test.skip('5: Verify that validation shown for invalid email format', async ({ - page, -}) => { - const registerPage = new RegisterPO(page); - const loginPage = new LoginPO(page); - const registerData = RegisterData.registerDataWithInvalidEmailFormat(); - - //Navigate to the URL - await page.goto(pageUrls.LoginPage); - - //Verify the login header text - expect(await loginPage.isLoginPageTitleVisible()).toBeTruthy(); - - //Click on the 'Register' button on login page - await loginPage.goToRegisterPage(); - - //Verify the title of the page - expect(await registerPage.isRegisterPageTitleVisible()).toBeTruthy(); - - //Fill and submit the register form with invalid email format - await registerPage.fillRegistrationForm(registerData); - - //click on register button - await registerPage.clickOnRegisterButton(); - - //Verify validation message is displayed for invalid email - await expect(page).toHaveScreenshot('invalidEmailErrorMessage.png'); -}); diff --git a/frontend/tests/test/RegistrationTests.Spec.ts-snapshots/emailErrorMessage-chromium-linux.png b/frontend/tests/test/RegistrationTests.Spec.ts-snapshots/emailErrorMessage-chromium-linux.png deleted file mode 100644 index d80ebb7c786812873a9b6927785725a7c283ea19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22254 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 diff --git a/frontend/tests/test/RegistrationTests.Spec.ts-snapshots/usernameErrorMessage-chromium-linux.png b/frontend/tests/test/RegistrationTests.Spec.ts-snapshots/usernameErrorMessage-chromium-linux.png deleted file mode 100644 index 4337eb54048a5f5b15d426c417fdbaa45e25d2dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22527 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

2qPBf&|cmCr|@?e*b}=#*UqY|SzB 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 z { - const homePage = new HomePage(page); - const leftMenuPage = new MenuPage(page); - const settingsPage = new SettingsPage(page); - const settingsDataList = SettingsData.allSettingsList(); - - //Navigate to the URL - await page.goto(pageUrls.HomePage); - - //Expand the menu and click on settings - await homePage.clickOnExpandMenu(); - await leftMenuPage.clickOnLeftMenufeatureButton(leftMenu.Settings); - - //verify setting page title is displayed - expect(await settingsPage.isSettingPageTitleVisible()).toBeTruthy(); - - //Get the settings page lists and verify the settings name is displayed - const lists = await settingsPage.getAllSettingFeaturesList(); - expect(lists).toEqual(expect.arrayContaining(settingsDataList)); -}); - -test('Verify that all the Beta tools are displayed when user enable beta tools toggle button', async ({ - page, -}) => { - const homePage = new HomePage(page); - const settingsPage = new SettingsPage(page); - const getSettingsList = SettingsData.allSettingsList(); - - //Navigate to the URL - await page.goto(pageUrls.SettingsPage); - - //Get the settings page list and verify the beta tools is displayed - const lists = await settingsPage.getAllSettingFeaturesList(); - expect(lists).toContain(getSettingsList[0]); - - //Click on beta tools toggle button - await settingsPage.clickOnToggleButton(settings.BetaTools, true); - - //Go to the home page and verify the language text is displayed - await homePage.clickOnCrowdRocks(); - expect(await homePage.isLanguageTextVisible()).toBeTruthy(); - - //Expand the menu and click on settings - await page.goto(pageUrls.SettingsPage); - - //Click on beta toggle button - await settingsPage.clickOnToggleButton(settings.BetaTools, false); - - //Go to the home page and verify the language text is hide - await homePage.clickOnCrowdRocks(); - expect(await homePage.isLanguageTextVisible(false)); -}); - -test('Verify that dark UI is display when user enable dark mode toggle button', async ({ - page, -}) => { - const settingsPage = new SettingsPage(page); - const getSettingsList = SettingsData.allSettingsList(); - - //Navigate to the URL - await page.goto(pageUrls.SettingsPage); - - //Get the settings page list and verify the beta tools is displayed - const lists = await settingsPage.getAllSettingFeaturesList(); - expect(lists).toContain(getSettingsList[1]); - - //click on dark mode toggle button - await settingsPage.clickOnToggleButton(settings.DarkMode, true); - - //verify that dark mode enabled - expect(await settingsPage.isDarkModeEnabled()).toBeTruthy(); -}); - -test('Verify that light UI is display when user disable dark mode toggle button', async ({ - page, -}) => { - const settingsPage = new SettingsPage(page); - const getSettingsList = SettingsData.allSettingsList(); - - //Navigate to the URL - await page.goto(pageUrls.SettingsPage); - - //Get the settings page list and verify the beta tools is displayed - const lists = await settingsPage.getAllSettingFeaturesList(); - expect(lists).toContain(getSettingsList[1]); - - //click on dark mode toggle button - await settingsPage.clickOnToggleButton(settings.DarkMode, false); - - //verify that dark mode enabled - expect(await settingsPage.isLightModeEnabled()).toBeTruthy(); -}); From cab8c790e3bb9eb35414acaf94aefb38e6483e73 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 17:42:04 +0100 Subject: [PATCH 08/26] remove some tests --- frontend/tests/test/DocumentsTests.Spec.ts | 266 +-------------------- 1 file changed, 1 insertion(+), 265 deletions(-) diff --git a/frontend/tests/test/DocumentsTests.Spec.ts b/frontend/tests/test/DocumentsTests.Spec.ts index 75e706d4..382feaa6 100644 --- a/frontend/tests/test/DocumentsTests.Spec.ts +++ b/frontend/tests/test/DocumentsTests.Spec.ts @@ -88,268 +88,4 @@ test('1: Verify that user can upload document successfully', async ({ expect( await documentsPage.isCreatedDocumentVisible(documentName), ).toBeTruthy(); -}); - -test('2: Verify user can download the document successfully', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); - - const [download] = await Promise.all([ - page.waitForEvent('download'), - documentsPage.downloadDocument(documentName), - ]); - expect(download).not.toBeNull(); - expect(download.url()).toContain(documentName); -}); - -test('3: Verify user can redirected on document details page successfully', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - - //search the create document and click on document name - await documentsPage.searchDocuments(documentName.toLocaleLowerCase()); - await documentsPage.clickOnDocument(documentName); - - //verify that document details page is open - expect(await documentsPage.isDocumentDetailsPageVisible()).toBeTruthy(); -}); - -test('4: Verify that user is not allowed to upload documents with the name which already exists', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - - //Verify that language is selected - expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - await documentsPage.uploadTextFile(constants.filePath(documentName)); - expect(await commonPage.getValidationMessage()).toEqual( - 'File with this name already exists', - ); -}); - -test.skip('5: Verify that validation message is appeared when user uploads the invalid file', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - const commonPage = new CommonPage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - - //Verify that language is selected - expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - const [uploadFile] = await Promise.all([ - page.waitForEvent('filechooser'), - await documentsPage.clickOnUploadButton(), - ]); - uploadFile.setFiles(constants.invalidFile); - expect(await commonPage.getValidationMessage()).toEqual( - 'Failed at uploading new Document! [UnknownError]', - ); -}); - -test('6: Verify that validation message is appeared when user uploads the file without selecting the language', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const commonPage = new CommonPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page - await homePage.clickOnTheDocumentsSection(); - - //Upload text file without selecting the language - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - await documentsPage.uploadTextFile(constants.filePath(documentName)); - expect(await commonPage.getValidationMessage()).toEqual( - 'Please select document language first.', - ); -}); - -test('7: Verify that user can select & cancel language successfully', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - - //Verify that language is selected - expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - - //Deselect the language - await documentsPage.clickOnCrossButton(); - expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); -}); - -test('8: Verify that select your language popup is closed when user clicks on the cancel button', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and click on the select your language dropdown - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); - - // Click on the cancel button - await documentsPage.clickOnCancelButton(); - - // Verify that select your language popup is closed - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeFalsy(); -}); - -test('9: Verify that language is selected on the Add new document popup is the same as selected on the Documents page', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and click on the select your language dropdown - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnSelectYourLanguageDropdown(); - expect(await documentsPage.isSelectYourLanguagePopupVisible()).toBeTruthy(); - - // Select your language - await documentsPage.selectLanguage(language.English); - await documentsPage.clickOnAddNewDocumentsButton(); - - // Verify that selected language is displayed - expect(await documentsPage.isLanguageSelected(language.English)); -}); - -test('10: Verify that user is able to select & cancel the language from the dropdown list successfully', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - expect(await documentsPage.isPageTitleVisible()).toBeTruthy(); - await documentsPage.clickOnAddNewDocumentsButton(); - await documentsPage.clickOnSelectDocumentLanguageDropdown(); - await documentsPage.selectLanguage(language.English); - expect(await documentsPage.isLanguageSelected(language.English)).toBeTruthy(); - - //Deselect the language - await documentsPage.clickOnAddNewDocumentPopupCrossButton(); - expect(await documentsPage.isLanguageSelected(language.English)).toBeFalsy(); -}); - -test('11: Verify that add new document popup is closed when user click on the cancel button', async ({ - page, -}) => { - const loginPage = new LoginPage(page); - const documentsPage = new DocumentsPage(page); - const homePage = new HomePage(page); - - //Login with valid credentials and turn on the beta tools - await page.goto(PageUrls.LoginPage); - await loginPage.loginToApp(registerData); - await turnOnBetaTools(page); - - //Navigate to documents page and select language - await homePage.clickOnTheDocumentsSection(); - await documentsPage.clickOnAddNewDocumentsButton(); - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeTruthy(); - await documentsPage.clickOnCancelButton(); - - //Verify that Add new popup is closed - expect(await documentsPage.isAddNewDocumentPopupVisible()).toBeFalsy(); -}); +}); \ No newline at end of file From 7063e5cdfdc8d117bb56d45f4beca83b208bcf9c Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 17:42:22 +0100 Subject: [PATCH 09/26] remove some tests --- frontend/tests/test/DocumentsTests.Spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/tests/test/DocumentsTests.Spec.ts b/frontend/tests/test/DocumentsTests.Spec.ts index 382feaa6..d3e7231f 100644 --- a/frontend/tests/test/DocumentsTests.Spec.ts +++ b/frontend/tests/test/DocumentsTests.Spec.ts @@ -88,4 +88,4 @@ test('1: Verify that user can upload document successfully', async ({ expect( await documentsPage.isCreatedDocumentVisible(documentName), ).toBeTruthy(); -}); \ No newline at end of file +}); From b82bdb6ed4a914e2984bd42520046a93341533d4 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 17:55:54 +0100 Subject: [PATCH 10/26] try to fix --- .github/docker/docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/docker/docker-compose.yml b/.github/docker/docker-compose.yml index 5532564e..2f052e75 100644 --- a/.github/docker/docker-compose.yml +++ b/.github/docker/docker-compose.yml @@ -25,6 +25,9 @@ services: MODE: DEV OPENAI_API_KEY: asdf DEEPL_KEY: asdf + AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} + AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} + AWS_REGION: ${AWS_REGION} ports: - 3000:3000 depends_on: From 3ffdda813e44592b5434e9083ab60db616507ce1 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 18:26:23 +0100 Subject: [PATCH 11/26] try to fix --- .github/docker/docker-compose.yml | 24 ++++++++++++------------ .github/workflows/test.yml | 3 --- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/.github/docker/docker-compose.yml b/.github/docker/docker-compose.yml index 2f052e75..cfc4d14a 100644 --- a/.github/docker/docker-compose.yml +++ b/.github/docker/docker-compose.yml @@ -16,18 +16,18 @@ services: api: image: etenlab/crowd-rocks:test environment: - CR_DB_URL: postgres - CR_DB_PORT: 5432 - CR_DB_USER: postgres - CR_DB_PASSWORD: asdfasdf - CR_DB: crowdrocks - ADMIN_PASSWORD: asdfasdf - MODE: DEV - OPENAI_API_KEY: asdf - DEEPL_KEY: asdf - AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - AWS_REGION: ${AWS_REGION} + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AWS_REGION=${AWS_REGION} + - CR_DB_URL=postgres + - CR_DB_PORT=5432 + - CR_DB_USER=postgres + - CR_DB_PASSWORD=asdfasdf + - CR_DB=crowdrocks + - ADMIN_PASSWORD=asdfasdf + - MODE=DEV + - OPENAI_API_KEY=asdf + - DEEPL_KEY=asdf ports: - 3000:3000 depends_on: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1bda4a6..232f8dba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,9 +82,6 @@ jobs: with: compose-file: "./.github/docker/docker-compose.yml" down-flags: "--volumes" - services: | - postgres - api env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} From ee528e1da0b0acdf00704e9dc67f5d299b3afc25 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Fri, 8 Dec 2023 18:53:14 +0100 Subject: [PATCH 12/26] try to fix --- api/src/common/types.ts | 1 + api/src/components/file/file.service.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/api/src/common/types.ts b/api/src/common/types.ts index e856075f..839fd244 100644 --- a/api/src/common/types.ts +++ b/api/src/common/types.ts @@ -40,6 +40,7 @@ export enum ErrorType { FileRecordNotFound = 'FileRecordNotFound', FileSaveFailed = 'FileSaveFailed', FileUpdateFailed = 'FileUpdateFailed', + FileUploadFailed = 'FileUploadFailed', FileDeleteFailed = 'FileDeleteFailed', FileWithFilenameAlreadyExists = 'FileWithFilenameAlreadyExists', FolderIdNotDefined = 'FolderIdNotDefined', diff --git a/api/src/components/file/file.service.ts b/api/src/components/file/file.service.ts index ec3ed958..cd4ef509 100644 --- a/api/src/components/file/file.service.ts +++ b/api/src/components/file/file.service.ts @@ -185,7 +185,12 @@ export class FileService { }); } catch (err) { Logger.log(`File upload failed. #file_name[${fileName}]`, err); - return { error: ErrorType.FileUpdateFailed, file: null }; + return { + error: `${JSON.stringify(err)}, [AWS_REGION env]: ${ + process.env.AWS_REGION + }` as ErrorType.FileUploadFailed, + file: null, + }; } } From f63c167386ccf864db196dc4f975280844e55bd5 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Mon, 11 Dec 2023 14:32:25 +0100 Subject: [PATCH 13/26] test --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 232f8dba..82e423db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,11 +82,14 @@ jobs: with: compose-file: "./.github/docker/docker-compose.yml" down-flags: "--volumes" + compose-flags: "logs" env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} AWS_REGION: us-east-2 + - run: docker-compose -f "./.github/docker/docker-compose.yml" logs + - run: cd utils && npm ci - run: cd frontend && npm ci --force From 3781014986bc26b5e11c6130cdc2338bdd47e6f2 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Mon, 11 Dec 2023 14:52:27 +0100 Subject: [PATCH 14/26] test --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 82e423db..d1bf5f0b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,7 +82,6 @@ jobs: with: compose-file: "./.github/docker/docker-compose.yml" down-flags: "--volumes" - compose-flags: "logs" env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} From 5912f88e9c2374c4592c1eacfc524ff67413c674 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 11:52:58 +0100 Subject: [PATCH 15/26] add logs --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d1bf5f0b..71fa2d96 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -99,6 +99,8 @@ jobs: - name: Run Playwright tests run: cd frontend && npx playwright test + - run: docker-compose -f "./.github/docker/docker-compose.yml" logs + - uses: actions/upload-artifact@v3 if: always() with: From 0044614604e230f57c8ef2c47849fa33ea755225 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:06:39 +0100 Subject: [PATCH 16/26] reduce timeout to 10sec --- frontend/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index 8b7a2808..e4beada2 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -43,7 +43,7 @@ export default defineConfig({ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, - timeout: 300 * 1000, + timeout: 10 * 1000, }, // { From 1c30e9a85c07c7711ce0f0a18993716ea15ce0e9 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:11:18 +0100 Subject: [PATCH 17/26] no test-buildable to test problem test --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71fa2d96..2ceb335e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,7 +69,7 @@ jobs: test-frontend-playwright: runs-on: ubuntu-latest - needs: test-buildable + # needs: test-buildable steps: - name: Checkout uses: actions/checkout@v1 From 6eea75e1c6957c798f08e9866f02067f034a5e4e Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:29:11 +0100 Subject: [PATCH 18/26] test --- .github/workflows/test.yml | 116 ++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ceb335e..c3d39433 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,64 +8,64 @@ on: - "frontend/**" jobs: - test-buildable: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v1 - - - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} - aws-region: us-east-2 - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - with: - images: etenlab/crowd-rocks - - - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc - with: - context: . - push: true - tags: etenlab/crowd-rocks:test - labels: ${{ steps.meta.outputs.labels }} - build-args: BUILD_MODE=test - - test-api-e2e: - runs-on: ubuntu-latest - needs: test-buildable - steps: - - name: Checkout - uses: actions/checkout@v1 - - - uses: isbang/compose-action@v1.4.1 - with: - compose-file: "./.github/docker/docker-compose.yml" - down-flags: "--volumes" - services: | - postgres - - - uses: actions/setup-node@v3 - with: - node-version: 16 - - - run: cd utils && npm ci - - - run: cd api && cp .env.example .env && yarn install - - - name: Test - run: cd api && yarn test:e2e + # test-buildable: + # runs-on: ubuntu-latest + # steps: + # - name: Checkout + # uses: actions/checkout@v1 + + # - name: Log in to Docker Hub + # uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + # with: + # username: ${{ secrets.DOCKER_USERNAME }} + # password: ${{ secrets.DOCKER_PASSWORD }} + + # - name: Configure AWS credentials + # uses: aws-actions/configure-aws-credentials@v1 + # with: + # aws-access-key-id: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} + # aws-secret-access-key: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} + # aws-region: us-east-2 + + # - name: Extract metadata (tags, labels) for Docker + # id: meta + # uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + # with: + # images: etenlab/crowd-rocks + + # - name: Build and push Docker image + # uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + # with: + # context: . + # push: true + # tags: etenlab/crowd-rocks:test + # labels: ${{ steps.meta.outputs.labels }} + # build-args: BUILD_MODE=test + + # test-api-e2e: + # runs-on: ubuntu-latest + # needs: test-buildable + # steps: + # - name: Checkout + # uses: actions/checkout@v1 + + # - uses: isbang/compose-action@v1.4.1 + # with: + # compose-file: "./.github/docker/docker-compose.yml" + # down-flags: "--volumes" + # services: | + # postgres + + # - uses: actions/setup-node@v3 + # with: + # node-version: 16 + + # - run: cd utils && npm ci + + # - run: cd api && cp .env.example .env && yarn install + + # - name: Test + # run: cd api && yarn test:e2e test-frontend-playwright: runs-on: ubuntu-latest From dc592b749f2a7815026cb1430cc14a67bd8a7238 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:35:33 +0100 Subject: [PATCH 19/26] test2 --- .github/workflows/test.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c3d39433..4c9a338a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,7 +87,6 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} AWS_REGION: us-east-2 - - run: docker-compose -f "./.github/docker/docker-compose.yml" logs - run: cd utils && npm ci @@ -96,10 +95,17 @@ jobs: - name: Install Playwright Browsers run: cd frontend && npx playwright install --with-deps + - name: Show logs before Playwright tests + run: docker-compose -f "./.github/docker/docker-compose.yml" logs + - name: Run Playwright tests run: cd frontend && npx playwright test - - run: docker-compose -f "./.github/docker/docker-compose.yml" logs + - uses: isbang/compose-action@v1.4.1 + with: + compose-file: "./.github/docker/docker-compose.yml" + - name: Logs after playwright tests + run: docker-compose -f "./.github/docker/docker-compose.yml" logs - uses: actions/upload-artifact@v3 if: always() From b6f71d3174671b1046511681321ad9e4dd473e32 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:56:41 +0100 Subject: [PATCH 20/26] test 3 --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4c9a338a..0b69afde 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,6 +102,7 @@ jobs: run: cd frontend && npx playwright test - uses: isbang/compose-action@v1.4.1 + if: always() with: compose-file: "./.github/docker/docker-compose.yml" - name: Logs after playwright tests From a0fd2eb4121aa36217bafd9840297c2e21e93e42 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 12:57:44 +0100 Subject: [PATCH 21/26] test 4 --- api/src/components/file/file.service.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/src/components/file/file.service.ts b/api/src/components/file/file.service.ts index cd4ef509..7fd7bbd8 100644 --- a/api/src/components/file/file.service.ts +++ b/api/src/components/file/file.service.ts @@ -21,7 +21,12 @@ dotenv.config(); @Injectable() export class FileService { s3Client: S3Client; - constructor(private fileRepository: FileRepository) {} + constructor(private fileRepository: FileRepository) { + Logger.log( + `env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, + 'FileService#constructor', + ); + } private getS3Client(): S3Client { if (!this.s3Client) { From afab72a50ba4c25917aec7a5b7590642089aabf9 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 15:54:12 +0100 Subject: [PATCH 22/26] test 5 --- api/src/main.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/src/main.ts b/api/src/main.ts index 02fb0196..40968a46 100644 --- a/api/src/main.ts +++ b/api/src/main.ts @@ -1,6 +1,8 @@ import { NestFactory } from '@nestjs/core'; import { graphqlUploadExpress } from 'graphql-upload-ts'; import { AppModule } from './app.module'; +import * as dotenv from 'dotenv'; +dotenv.config(); async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -8,6 +10,11 @@ async function bootstrap() { origin: '*', allowedHeaders: '*', }); + + console.log( + `==============> env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, + 'FileService#constructor', + ); app.use( '/graphql', graphqlUploadExpress({ From 3274a2e0f300a64f7e6a45704b68d58ff9ce21bd Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 15:59:45 +0100 Subject: [PATCH 23/26] test 6 --- api/src/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/main.ts b/api/src/main.ts index 40968a46..a4fdaeb6 100644 --- a/api/src/main.ts +++ b/api/src/main.ts @@ -5,16 +5,16 @@ import * as dotenv from 'dotenv'; dotenv.config(); async function bootstrap() { + console.log( + `==============> env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, + 'FileService#constructor', + ); const app = await NestFactory.create(AppModule); app.enableCors({ origin: '*', allowedHeaders: '*', }); - console.log( - `==============> env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, - 'FileService#constructor', - ); app.use( '/graphql', graphqlUploadExpress({ From f365af8780a2aaeca4d06aa3ba04b58dc4830484 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 17:03:50 +0100 Subject: [PATCH 24/26] test 6 --- api/src/components/file/file.service.ts | 7 +------ api/src/core/database-version-control.service.ts | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/src/components/file/file.service.ts b/api/src/components/file/file.service.ts index 7fd7bbd8..cd4ef509 100644 --- a/api/src/components/file/file.service.ts +++ b/api/src/components/file/file.service.ts @@ -21,12 +21,7 @@ dotenv.config(); @Injectable() export class FileService { s3Client: S3Client; - constructor(private fileRepository: FileRepository) { - Logger.log( - `env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, - 'FileService#constructor', - ); - } + constructor(private fileRepository: FileRepository) {} private getS3Client(): S3Client { if (!this.s3Client) { diff --git a/api/src/core/database-version-control.service.ts b/api/src/core/database-version-control.service.ts index 7d51fe0c..13636166 100644 --- a/api/src/core/database-version-control.service.ts +++ b/api/src/core/database-version-control.service.ts @@ -27,6 +27,10 @@ export class DatabaseVersionControlService { if (!exists) { console.log('Creating database schema'); + Logger.debug( + `env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, + 'FileService#constructor', + ); await this.loadVersion1(); } From c1164b80fde4429c44519aca536bbfb75dd7473c Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 17:20:29 +0100 Subject: [PATCH 25/26] test 7 --- .github/workflows/test.yml | 65 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0b69afde..3539eb33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,39 +8,39 @@ on: - "frontend/**" jobs: - # test-buildable: - # runs-on: ubuntu-latest - # steps: - # - name: Checkout - # uses: actions/checkout@v1 + test-buildable: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 - # - name: Log in to Docker Hub - # uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 - # with: - # username: ${{ secrets.DOCKER_USERNAME }} - # password: ${{ secrets.DOCKER_PASSWORD }} + - name: Log in to Docker Hub + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} - # - name: Configure AWS credentials - # uses: aws-actions/configure-aws-credentials@v1 - # with: - # aws-access-key-id: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} - # aws-secret-access-key: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} - # aws-region: us-east-2 + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_GITHUB_S3_PUSHER_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_GITHUB_S3_PUSHER_SECRET_ACCESS_KEY }} + aws-region: us-east-2 - # - name: Extract metadata (tags, labels) for Docker - # id: meta - # uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - # with: - # images: etenlab/crowd-rocks + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: etenlab/crowd-rocks - # - name: Build and push Docker image - # uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc - # with: - # context: . - # push: true - # tags: etenlab/crowd-rocks:test - # labels: ${{ steps.meta.outputs.labels }} - # build-args: BUILD_MODE=test + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: etenlab/crowd-rocks:test + labels: ${{ steps.meta.outputs.labels }} + build-args: BUILD_MODE=test # test-api-e2e: # runs-on: ubuntu-latest @@ -69,7 +69,7 @@ jobs: test-frontend-playwright: runs-on: ubuntu-latest - # needs: test-buildable + needs: test-buildable steps: - name: Checkout uses: actions/checkout@v1 @@ -101,11 +101,8 @@ jobs: - name: Run Playwright tests run: cd frontend && npx playwright test - - uses: isbang/compose-action@v1.4.1 - if: always() - with: - compose-file: "./.github/docker/docker-compose.yml" - name: Logs after playwright tests + if: always() run: docker-compose -f "./.github/docker/docker-compose.yml" logs - uses: actions/upload-artifact@v3 From fade4ef8c3cb783e1abe724e988b40d98fa7ff95 Mon Sep 17 00:00:00 2001 From: Ihor_S Date: Thu, 14 Dec 2023 17:20:59 +0100 Subject: [PATCH 26/26] test 8 --- api/src/core/database-version-control.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/core/database-version-control.service.ts b/api/src/core/database-version-control.service.ts index 13636166..3742f729 100644 --- a/api/src/core/database-version-control.service.ts +++ b/api/src/core/database-version-control.service.ts @@ -27,7 +27,7 @@ export class DatabaseVersionControlService { if (!exists) { console.log('Creating database schema'); - Logger.debug( + console.log( `env AWS_REGION ${process.env.AWS_REGION} AWS_ACCESS_KEY_ID ${process.env.AWS_ACCESS_KEY_ID}`, 'FileService#constructor', );