Skip to content

Commit

Permalink
Added UI Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Progi1984 committed May 28, 2024
1 parent 4e1496d commit 3260fb6
Show file tree
Hide file tree
Showing 9 changed files with 2,924 additions and 0 deletions.
142 changes: 142 additions & 0 deletions .github/workflows/ui-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: UI Tests
on:
## Check each PR
push:
pull_request:
## Manual execution on branch
workflow_dispatch:
## Nightly
### Needs secrets
#### GC_PROJECT_ID
#### GC_SERVICE_KEY
#### NIGHTLY_TOKEN
schedule:
- cron: '0 0 * * *'
env:
CAMPAIGN: 'ps_emailalerts'
jobs:
ui_test:
name: UI Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- PS_VERSION: '1.7.7.8'
PHP_VERSION: '7.3'
- PS_VERSION: '1.7.8.11'
PHP_VERSION: '7.4'
- PS_VERSION: '8.0.5'
PHP_VERSION: '8.1'
- PS_VERSION: '8.1.6'
PHP_VERSION: '8.1'
- PS_VERSION: 'nightly'
PHP_VERSION: '8.2'
env:
PS_VERSION: ${{ matrix.PS_VERSION }}
PHP_VERSION: ${{ matrix.PHP_VERSION }}
steps:
- name: Checkout
uses: actions/[email protected]

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.PHP_VERSION }}

- name: Install dependencies
run: composer install --no-dev && composer dump-autoload -o --no-dev

- name: Start containers
working-directory: tests/UI/
run: |
docker compose -f "docker-compose.yml" up -d --build
bash -c 'while [[ "$(curl -L -s -o /dev/null -w %{http_code} http://localhost/en/)" != "200" ]]; do sleep 5; done'
- name: Install dependencies
working-directory: tests/UI/
run: npm ci

- name: Install Playwright Browsers
working-directory: tests/UI/
run: npx playwright install chromium --with-deps

- name: Run Playwright tests
working-directory: tests/UI/
run: npx playwright test

- name: Export Docker errors
working-directory: tests/UI/
if: always()
run: docker compose logs --no-color >& docker-compose.log

- name: Upload artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-${{ matrix.PS_VERSION }}
path: |
tests/UI/reports/
tests/UI/report.json
tests/UI/docker-compose.log
retention-days: 30

nightly:
name: Nightly Report
if: ${{ github.event_name == 'schedule' }}
needs:
- ui_test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
PS_VERSION:
- '1.7.7.8'
- '1.7.8.11'
- '8.0.5'
- '8.1.6'
- 'nightly'
permissions:
contents: 'read'
id-token: 'write'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Download report
uses: actions/download-artifact@v4
with:
name: playwright-report-${{ matrix.PS_VERSION }}
path: tests/UI/

# Nightly : Rename file
- name: "Nightly : Rename file"
working-directory: tests/UI/
run: |
mkdir -p nightly
REPORT_NAME="${{ env.CAMPAIGN }}_$(date +%Y-%m-%d)-${{ matrix.PS_VERSION }}"
mv report.json nightly/${REPORT_NAME}.json
# Nightly : Auth GCP
- name: "Nightly : Auth GCP"
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GC_SERVICE_KEY }}
project_id: ${{ secrets.GC_PROJECT_ID }}

# Nightly : Setup GCP
- name: "Nightly : Setup GCP"
uses: google-github-actions/setup-gcloud@v1

# Nightly : Upload to Google Cloud Storage (GCS)
- name: "Nightly : Upload to Google Cloud Storage (GCS)"
working-directory: tests/UI/
run: gsutil cp -r "nightly/**" gs://prestashop-core-nightly/reports

# Nightly : Push Report
- name: "Nightly : Push Report"
run: |
REPORT_NAME="${{ env.CAMPAIGN }}_$(date +%Y-%m-%d)-${{ matrix.PS_VERSION }}"
curl -v "https://api-nightly.prestashop-project.org/import/report/playwright?token=${{ secrets.NIGHTLY_TOKEN }}&filename=${REPORT_NAME}.json&campaign=${{ env.CAMPAIGN }}&platform=chromium"
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
/vendor
.php_cs.cache

## UI Tests
/tests/UI/.env
/tests/UI/node_modules/
/tests/UI/report.json
/tests/UI/reports/
/tests/UI/test-results/
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import {
test,
expect,
type Page,
type BrowserContext,
} from '@playwright/test';

import {
boDashboardPage,
boLoginPage,
boModuleManagerPage,
boProductsPage,
dataModules,
FakerProduct,
foClassicCategoryPage,
foClassicHomePage,
foClassicProductPage,
opsBOCatalogProduct,
utilsFile,
utilsTest,
} from '@prestashop-core/ui-testing';

const baseContext: string = 'modules_ps_emailalerts_installation_uninstallAndInstallModule';

test.describe('Mail alerts module - Uninstall and install module', async () => {
let browserContext: BrowserContext;
let page: Page;
let idProduct: number;
let nthProduct: number|null;

const productOutOfStockNotAllowed: FakerProduct = new FakerProduct({
name: 'Product Out of stock not allowed',
type: 'standard',
taxRule: 'No tax',
tax: 0,
quantity: 0,
behaviourOutOfStock: 'Deny orders',
});

test.beforeAll(async ({ browser }) => {
browserContext = await browser.newContext();
page = await browserContext.newPage();
});
test.afterAll(async () => {
await page.close();
});

test('PRE-Condition : Create product out of stock not allowed', async () => {
await opsBOCatalogProduct.createProduct(page, productOutOfStockNotAllowed, `${baseContext}_preTest`);
});

// BackOffice - Fetch the ID of the product
test('should login in BO', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'loginBO', baseContext);

await boLoginPage.goTo(page, global.BO.URL);
await boLoginPage.successLogin(page, global.BO.EMAIL, global.BO.PASSWD);

const pageTitle = await boDashboardPage.getPageTitle(page);
expect(pageTitle).toContain(boDashboardPage.pageTitle);
});

test('should go to \'Catalog > Products\' page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToProductsPage', baseContext);

await boDashboardPage.goToSubMenu(
page,
boDashboardPage.catalogParentLink,
boDashboardPage.productsLink,
);

const pageTitle = await boProductsPage.getPageTitle(page);
expect(pageTitle).toContain(boProductsPage.pageTitle);
});

test('should filter list by \'product_name\'', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'filterProductName', baseContext);

await boProductsPage.resetFilter(page);
await boProductsPage.filterProducts(page, 'product_name', productOutOfStockNotAllowed.name, 'input');

const numberOfProductsAfterFilter = await boProductsPage.getNumberOfProductsFromList(page);
expect(numberOfProductsAfterFilter).toEqual(1);

idProduct = await boProductsPage.getTextColumn(page, 'id_product', 1) as number;
});

// BackOffice - Uninstall Module
test('should go to \'Modules > Module Manager\' page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToModuleManagerPage', baseContext);

await boDashboardPage.goToSubMenu(
page,
boDashboardPage.modulesParentLink,
boDashboardPage.moduleManagerLink,
);
await boModuleManagerPage.closeSfToolBar(page);

const pageTitle = await boModuleManagerPage.getPageTitle(page);
expect(pageTitle).toContain(boModuleManagerPage.pageTitle);
});

test(`should search the module ${dataModules.psEmailAlerts.name}`, async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'searchModule', baseContext);

const isModuleVisible = await boModuleManagerPage.searchModule(page, dataModules.psEmailAlerts);
expect(isModuleVisible).toBeTruthy();
});

test('should display the uninstall modal and cancel it', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'uninstallModuleAndCancel', baseContext);

const textResult = await boModuleManagerPage.setActionInModule(page, dataModules.psEmailAlerts, 'uninstall', true);
expect(textResult).toEqual('');

const isModuleVisible = await boModuleManagerPage.isModuleVisible(page, dataModules.psEmailAlerts);
expect(isModuleVisible).toBeTruthy();

const isModalVisible = await boModuleManagerPage.isModalActionVisible(page, dataModules.psEmailAlerts, 'uninstall');
expect(isModalVisible).toBeFalsy();

const dirExists = await utilsFile.doesFileExist(`${utilsFile.getRootPath()}/modules/${dataModules.psEmailAlerts.tag}/`);
expect(dirExists).toBeTruthy();
});

test('should uninstall the module', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'uninstallModule', baseContext);

const successMessage = await boModuleManagerPage.setActionInModule(page, dataModules.psEmailAlerts, 'uninstall', false);
expect(successMessage).toEqual(boModuleManagerPage.uninstallModuleSuccessMessage(dataModules.psEmailAlerts.tag));

// Check the directory `modules/Modules.psEmailAlerts.tag`
const dirExists = await utilsFile.doesFileExist(`${utilsFile.getRootPath()}/modules/${dataModules.psEmailAlerts.tag}/`);
expect(dirExists).toBeTruthy();
});

// FrontOffice - Check that the module is not present
test('should go to Front Office', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToFoAfterUninstall', baseContext);

page = await boModuleManagerPage.viewMyShop(page);
await foClassicHomePage.changeLanguage(page, 'en');

const isHomePage = await foClassicHomePage.isHomePage(page);
expect(isHomePage).toBeTruthy();
});

test('should go to the All Products Page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToAllProductsPageAfterUninstall', baseContext);

await foClassicHomePage.goToAllProductsPage(page);

const isCategoryPageVisible = await foClassicCategoryPage.isCategoryPage(page);
expect(isCategoryPageVisible, 'Home category page was not opened').toBeTruthy();
});

test('should go the the second page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToSecondPage', baseContext);

await foClassicCategoryPage.goToNextPage(page);

nthProduct = await foClassicCategoryPage.getNThChildFromIDProduct(page, idProduct);
expect(nthProduct).not.toBeNull();
});

test('should go to the product page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToProductPage', baseContext);

await foClassicCategoryPage.goToProductPage(page, nthProduct!);

const pageTitle = await foClassicProductPage.getPageTitle(page);
expect(pageTitle.toUpperCase()).toContain(productOutOfStockNotAllowed.name.toUpperCase());

const hasFlagOutOfStock = await foClassicProductPage.hasProductFlag(page, 'out_of_stock');
expect(hasFlagOutOfStock).toBeTruthy();

const hasBlockMailAlert = await foClassicProductPage.hasBlockMailAlert(page);
expect(hasBlockMailAlert).toBeFalsy();
});

// BackOffice - Install the module
test('should go back to BO', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goBackToBo', baseContext);

page = await foClassicProductPage.closePage(browserContext, page, 0);
await boModuleManagerPage.reloadPage(page);

const pageTitle = await boModuleManagerPage.getPageTitle(page);
expect(pageTitle).toContain(boModuleManagerPage.pageTitle);
});

test('should install the module', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'installModule', baseContext);

const successMessage = await boModuleManagerPage.setActionInModule(page, dataModules.psEmailAlerts, 'install', false);
expect(successMessage).toEqual(boModuleManagerPage.installModuleSuccessMessage(dataModules.psEmailAlerts.tag));

// Check the directory `modules/Modules.psEmailAlerts.tag`
const dirExists = await utilsFile.doesFileExist(`${utilsFile.getRootPath()}/modules/${dataModules.psEmailAlerts.tag}/`);
expect(dirExists).toBeTruthy();
});

// FrontOffice - Check that the module is present
test('should return to Front Office', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToFo', baseContext);

page = await boModuleManagerPage.viewMyShop(page);
await foClassicHomePage.changeLanguage(page, 'en');

const isHomePage = await foClassicHomePage.isHomePage(page);
expect(isHomePage).toBeTruthy();
});

test('should return to the All Products Page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToAllProductsPage', baseContext);

await foClassicHomePage.goToAllProductsPage(page);

const isCategoryPageVisible = await foClassicCategoryPage.isCategoryPage(page);
expect(isCategoryPageVisible, 'Home category page was not opened').toBeTruthy();
});

test('should return to the product page', async () => {
await utilsTest.addContextItem(test.info(), 'testIdentifier', 'goToProductPageWithMailAlert', baseContext);

await foClassicCategoryPage.goToNextPage(page);
await foClassicCategoryPage.goToProductPage(page, nthProduct!);

const pageTitle = await foClassicProductPage.getPageTitle(page);
expect(pageTitle.toUpperCase()).toContain(productOutOfStockNotAllowed.name.toUpperCase());

const hasFlagOutOfStock = await foClassicProductPage.hasProductFlag(page, 'out_of_stock');
expect(hasFlagOutOfStock).toBeTruthy()

const hasBlockMailAlert = await foClassicProductPage.hasBlockMailAlert(page);
expect(hasBlockMailAlert).toBeTruthy();
});

test('POST-Condition : Delete product out of stock not allowed', async () => {
await opsBOCatalogProduct.deleteProduct(page, productOutOfStockNotAllowed, `${baseContext}_postTest_0`);
});
});
Loading

0 comments on commit 3260fb6

Please sign in to comment.