-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
2,926 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
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: Rights | ||
run: chmod -R 777 ./mails | ||
|
||
- 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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ |
242 changes: 242 additions & 0 deletions
242
tests/UI/campaigns/01_installation/01_uninstallAndInstallModule.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`); | ||
}); | ||
}); |
Oops, something went wrong.