first commit

This commit is contained in:
2024-11-05 12:22:50 +01:00
commit e5682a3912
19641 changed files with 2948548 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
# E2E tests
This folder contains tests about ps_banner module.
## Supported versions
These tests can be run on `1.7.7.x` and `1.7.6.x` PrestaShop versions.
## Stack
In these tests, we used the actual stack :
- [prestashop_test_lib](https://www.npmjs.com/package/prestashop_test_lib) which uses [playwright](https://playwright.dev/) as a node library to automate browsers.
- [mocha](https://mochajs.org/) as a test framework.
- [chai](https://www.chaijs.com/) as an assertion library.
- [js-image-generator](https://www.npmjs.com/package/js-image-generator) as a node library to generate fake images for tests.
## Running tests
Before running tests, you should run `npm install`, to install all dependencies.
### Running all tests
```shell
PS_VERSION='1.7.7' URL_FO='http://localhost.com/' npm run e2e-tests
```
### Running all tests with fast fail mode
The fast fail mode give us the possibility to abort the run after first test failure. It uses the --bail option from [mocha](https://mochajs.org/#command-line-usage).
This mode is mostly used in CI (like here in Github Actions), to stop the tests as quickly as possible.
```shell
PS_VERSION='1.7.7' URL_FO='http://localhost/prestashop/' npm run e2e-tests-fast-fail
```
### Env variables
Some variables can be used to run tests:
| Parameter | Description |
|---------------------|----------------------------------------------------- |
| PS_VERSION | PrestaShop minor version (not patch version) (default to **`1.7.7`**)|
| URL_FO | URL of your PrestaShop website Front Office (default to **`http://localhost/prestashop/`**) |
| URL_BO | URL of your PrestaShop website Back Office (default to **`URL_FO + admin-dev/`**) |
| BROWSER | Specific browser to launch for tests (default to **`chromium`**) |
| HEADLESS | Boolean to run tests in [headless mode](https://en.wikipedia.org/wiki/Headless_software) or not (default to **`true`**) |
For more variables, please take a look on global vars on [prestashop_test_lib](https://github.com/PrestaShopCorp/prestashop_test_lib/blob/master/kernel/utils/globals.js).
Enjoy :wink: :v:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
{
"name": "ps_banner_e2e_tests",
"version": "1.0.0",
"description": "Tests E2E for ps_banner modules",
"scripts": {
"e2e-tests": "./node_modules/mocha/bin/mocha --recursive --file ./node_modules/prestashop_test_lib/kernel/utils/setup.js scenarios/*",
"e2e-tests-fast-fail": "./node_modules/mocha/bin/mocha --bail --recursive --file ./node_modules/prestashop_test_lib/kernel/utils/setup.js scenarios/*",
"lint": "eslint --ignore-path .gitignore .",
"lint-fix": "eslint --ignore-path .gitignore --fix ."
},
"_moduleAliases": {
"@versions": "versions",
"@scenarios": "scenarios",
"@utils": "utils"
},
"keywords": [
"e2e",
"tests",
"playwright"
],
"author": "",
"license": "ISC",
"dependencies": {
"chai": "^4.2.0",
"eslint-config-prestashop": "0.0.2",
"js-image-generator": "^1.0.3",
"mocha": "^8.2.1",
"mochawesome": "^6.2.1",
"module-alias": "^2.2.2",
"prestashop_test_lib": "0.0.14"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^5.4.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.22.1"
}
}

View File

@@ -0,0 +1,163 @@
require('module-alias/register');
const {expect} = require('chai');
const browserHelper = require('prestashop_test_lib/kernel/utils/helpers.js');
const configClassMap = require('@utils/configClassMap.js');
const imageHelper = require('@utils/imageHelper.js');
const fileHelper = require('@utils/fileHelper');
// Get resolver
const VersionSelectResolver = require('prestashop_test_lib/kernel/resolvers/versionSelectResolver.js');
const versionSelectResolver = new VersionSelectResolver(global.PS_VERSION, configClassMap);
// Import pages
const loginPage = versionSelectResolver.require('BO/login/index.js');
const dashboardPage = versionSelectResolver.require('BO/dashboard/index.js');
const moduleManagerPage = versionSelectResolver.require('BO/modules/moduleManager/index.js');
const psBannerModulePage = versionSelectResolver.require('BO/modules/ps_banner/index.js');
const homePage = versionSelectResolver.require('FO/home/index.js');
// Browser vars
let browserContext;
let page;
const moduleToInstall = {
name: 'Banner',
tag: 'ps_banner',
};
const moduleConfiguration = {
en: {
langId: 1,
imagePath: './image_en.png',
link: global.FO.URL,
description: 'This is a description for module ps_banner',
},
fr: {
langId: 2,
imagePath: './image_fr.png',
link: global.FO.URL,
description: 'Ceci est une description du module ps_banner',
},
};
describe('Go to ps_banner configuration page', async () => {
// before and after functions
before(async function () {
browserContext = await browserHelper.createBrowserContext(this.browser);
page = await browserHelper.newTab(browserContext);
// Create images for test
await Promise.all([
imageHelper.generateImage(moduleConfiguration.en.imagePath),
imageHelper.generateImage(moduleConfiguration.fr.imagePath),
]);
});
after(async () => {
await browserHelper.closeBrowserContext(browserContext);
// Delete images after test
await Promise.all([
fileHelper.deleteFile(moduleConfiguration.en.imagePath),
fileHelper.deleteFile(moduleConfiguration.fr.imagePath),
]);
});
it('should go to login page', async () => {
await loginPage.goTo(page, global.BO.URL);
const pageTitle = await loginPage.getPageTitle(page);
await expect(pageTitle).to.contains(loginPage.pageTitle);
});
it('should check PS version', async () => {
const psVersion = await loginPage.getPrestashopVersion(page);
await expect(psVersion).to.contains(global.PS_VERSION);
});
it('should login into BO with default user', async () => {
await loginPage.login(page, global.BO.EMAIL, global.BO.PASSWD);
await dashboardPage.closeOnboardingModal(page);
const pageTitle = await dashboardPage.getPageTitle(page);
await expect(pageTitle).to.contains(dashboardPage.pageTitle);
});
it('should go to module manager page', async () => {
await dashboardPage.goToSubMenu(
page,
dashboardPage.modulesParentLink,
dashboardPage.moduleManagerLink,
);
const pageTitle = await moduleManagerPage.getPageTitle(page);
await expect(pageTitle).to.contain(moduleManagerPage.pageTitle);
});
it('should check that the module was installed', async () => {
const isModuleVisible = await moduleManagerPage.searchModule(
page,
moduleToInstall.tag,
moduleToInstall.name,
);
await expect(isModuleVisible).to.be.true;
});
it('should check that the module is enabled', async () => {
const isModuleEnabled = await moduleManagerPage.isModuleEnabled(page, moduleToInstall.name);
await expect(isModuleEnabled).to.be.true;
});
it('should go to configuration page', async () => {
await moduleManagerPage.goToConfigurationPage(page, moduleToInstall.name);
// Check configuration page
const pageTitle = await psBannerModulePage.getPageTitle(page);
await expect(pageTitle).to.contain(psBannerModulePage.pageTitle);
// Check module name
const pageSubtitle = await psBannerModulePage.getPageSubtitle(page);
await expect(pageSubtitle).to.contain(moduleToInstall.name);
});
it('should set module configuration', async () => {
const textResult = await psBannerModulePage.setConfiguration(page, moduleConfiguration);
await expect(textResult).to.contain(psBannerModulePage.updatedSettingSuccessfulMessage);
});
it('should view my shop and check that banner exist', async () => {
page = await psBannerModulePage.viewMyShop(page);
const bannerExists = await homePage.isBannerVisible(page);
await expect(bannerExists).to.be.true;
});
it('should check banner link and description in english', async () => {
await homePage.changeLanguage(page, 'en');
// Check banner link
const bannerLink = await homePage.getBannerLink(page);
await expect(bannerLink).to.equal(moduleConfiguration.en.link);
// Check banner description
const bannerDescription = await homePage.getBannerDescription(page);
await expect(bannerDescription).to.equal(moduleConfiguration.en.description);
});
it('should check banner link and description in french', async () => {
await homePage.changeLanguage(page, 'fr');
// Check banner link
const bannerLink = await homePage.getBannerLink(page);
await expect(bannerLink).to.equal(moduleConfiguration.fr.link);
// Check banner description
const bannerDescription = await homePage.getBannerDescription(page);
await expect(bannerDescription).to.equal(moduleConfiguration.fr.description);
});
});

View File

@@ -0,0 +1,110 @@
require('module-alias/register');
const {expect} = require('chai');
const browserHelper = require('prestashop_test_lib/kernel/utils/helpers.js');
const configClassMap = require('@utils/configClassMap.js');
// Get resolver
const VersionSelectResolver = require('prestashop_test_lib/kernel/resolvers/versionSelectResolver.js');
const versionSelectResolver = new VersionSelectResolver(global.PS_VERSION, configClassMap);
// Import pages
const loginPage = versionSelectResolver.require('BO/login/index.js');
const dashboardPage = versionSelectResolver.require('BO/dashboard/index.js');
const moduleManagerPage = versionSelectResolver.require('BO/modules/moduleManager/index.js');
const homePage = versionSelectResolver.require('FO/home/index.js');
// Browser vars
let browserContext;
let page;
const moduleToInstall = {
name: 'Banner',
tag: 'ps_banner',
};
describe('Disable and enable module', async () => {
// before and after functions
before(async function () {
browserContext = await browserHelper.createBrowserContext(this.browser);
page = await browserHelper.newTab(browserContext);
});
after(async () => {
await browserHelper.closeBrowserContext(browserContext);
});
it('should go to login page', async () => {
await loginPage.goTo(page, global.BO.URL);
const pageTitle = await loginPage.getPageTitle(page);
await expect(pageTitle).to.contains(loginPage.pageTitle);
});
it('should login into BO with default user', async () => {
await loginPage.login(page, global.BO.EMAIL, global.BO.PASSWD);
await dashboardPage.closeOnboardingModal(page);
const pageTitle = await dashboardPage.getPageTitle(page);
await expect(pageTitle).to.contains(dashboardPage.pageTitle);
});
it('should go to module manager page', async () => {
await dashboardPage.goToSubMenu(
page,
dashboardPage.modulesParentLink,
dashboardPage.moduleManagerLink,
);
const pageTitle = await moduleManagerPage.getPageTitle(page);
await expect(pageTitle).to.contain(moduleManagerPage.pageTitle);
});
it('should check that the module was installed', async () => {
const isModuleVisible = await moduleManagerPage.searchModule(
page,
moduleToInstall.tag,
moduleToInstall.name,
);
await expect(isModuleVisible).to.be.true;
});
it('should check that the module is enabled', async () => {
const isModuleEnabled = await moduleManagerPage.isModuleEnabled(page, moduleToInstall.name);
await expect(isModuleEnabled).to.be.true;
});
it('should disable module', async () => {
const textResult = await moduleManagerPage.disableModule(page, moduleToInstall.tag, moduleToInstall.name);
await expect(textResult).to.contain(moduleManagerPage.successfulDisableMessage(moduleToInstall.tag));
});
it('should view my shop and check that banner don\'t exist', async () => {
page = await moduleManagerPage.viewMyShop(page);
const bannerExists = await homePage.isBannerVisible(page);
await expect(bannerExists).to.be.false;
});
it('should go back to BO', async () => {
page = await homePage.closePage(browserContext, page, 0);
const pageTitle = await moduleManagerPage.getPageTitle(page);
await expect(pageTitle).to.contain(moduleManagerPage.pageTitle);
});
it('should enable module', async () => {
const textResult = await moduleManagerPage.enableModule(page, moduleToInstall.name);
await expect(textResult).to.contain(moduleManagerPage.successfulEnableMessage(moduleToInstall.tag));
});
it('should view my shop and check that banner exist', async () => {
page = await moduleManagerPage.viewMyShop(page);
const bannerExists = await homePage.isBannerVisible(page);
await expect(bannerExists).to.be.true;
});
});

View File

@@ -0,0 +1,18 @@
module.exports = [
{
file: 'BO/modules/ps_banner/index.js',
versions: {
'1.7.6': '@versions/177/BO/modules/ps_banner/index.js',
'1.7.7': '@versions/177/BO/modules/ps_banner/index.js',
'1.7.8': '@versions/177/BO/modules/ps_banner/index.js',
},
},
{
file: 'FO/home/index.js',
versions: {
'1.7.6': '@versions/177/FO/home/index.js',
'1.7.7': '@versions/177/FO/home/index.js',
'1.7.8': '@versions/177/FO/home/index.js',
},
},
];

View File

@@ -0,0 +1,14 @@
const fs = require('fs');
module.exports = {
/**
* Delete File if exist
* @param pathToFile
* @return {Promise<void>}
*/
async deleteFile(pathToFile) {
if (fs.existsSync(pathToFile)) {
fs.unlinkSync(pathToFile);
}
},
};

View File

@@ -0,0 +1,18 @@
const fs = require('fs');
const imgGen = require('js-image-generator');
module.exports = {
/**
* Generate image
* @param imageName
* @param width
* @param height
* @param quality
* @return {Promise<void>}
*/
async generateImage(imageName, width = 200, height = 200, quality = 1) {
await imgGen.generateImage(width, height, quality, (err, image) => {
fs.writeFileSync(imageName, image.data);
});
},
};

View File

@@ -0,0 +1,121 @@
// Get resolver
const VersionSelectResolver = require('prestashop_test_lib/kernel/resolvers/versionSelectResolver');
const versionSelectResolver = new VersionSelectResolver(global.PS_VERSION);
// Import BOBasePage
const ModuleConfigurationPage = versionSelectResolver.require('BO/modules/moduleConfiguration/index.js');
class PS_BANNER extends ModuleConfigurationPage.constructor {
constructor() {
super();
this.updatedSettingSuccessfulMessage = 'The settings have been updated.';
// Selectors
this.titleBlock = 'h2.page-title';
this.subtitleBlock = 'h4.page-subtitle';
// Alert success selector
this.alertSuccessBlock = '.alert-success.module_confirmation';
// Form selectors
this.moduleForm = '#module_form';
this.bannerImageSelectButton = langId => `#BANNER_IMG_${langId}-selectbutton`;
this.bannerLinkInput = langId => `#BANNER_LINK_${langId}`;
this.bannerDescriptionInput = langId => `#BANNER_DESC_${langId}`;
this.saveButton = '#module_form_submit_btn';
// Change languages selector
this.dropdownLangButton = `${this.moduleForm} button.dropdown-toggle`;
this.dropdownLangItemLink = langId => `#dropdown-lang-item-link-${langId}`;
}
// Functions
/**
* Change form language
* @param page
* @param langId
* @return {Promise<void>}
*/
async changeLanguage(page, langId) {
await Promise.all([
page.click(this.dropdownLangButton),
this.waitForVisibleSelector(page, this.dropdownLangItemLink(langId)),
]);
await page.click(this.dropdownLangItemLink(langId));
}
/**
* Upload image for a specific language
* @param page
* @param imagePath
* @param langId
* @return {Promise<void>}
*/
async uploadImagePath(page, imagePath, langId) {
// Set value when fileChooser is open
page.once('filechooser', async (fileChooser) => {
await fileChooser.setFiles(imagePath);
});
await page.click(this.bannerImageSelectButton(langId));
}
/**
* Set link for a specific language
* @param page
* @param link
* @param langId
* @return {Promise<void>}
*/
async setBannerLink(page, link, langId) {
await this.setValue(page, this.bannerLinkInput(langId), link);
}
/**
* Set description for a specific language
* @param page
* @param description
* @param langId
* @return {Promise<void>}
*/
async setBannerDescription(page, description, langId) {
await this.setValue(page, this.bannerDescriptionInput(langId), description);
}
/**
* Fill all inputs in form in a specific language
* @param page
* @param configuration
* @return {Promise<void>}
*/
async fillSpecificLanguageForm(page, configuration) {
await this.changeLanguage(page, configuration.langId);
await this.uploadImagePath(page, configuration.imagePath, configuration.langId);
await this.setBannerLink(page, configuration.link, configuration.langId);
await this.setBannerDescription(page, configuration.description, configuration.langId);
}
/**
* Configure module in 2 languages en and fr
* @param page
* @param configuration
* @return {Promise<string>}
*/
async setConfiguration(page, configuration) {
// Fill form in lang=en
await this.fillSpecificLanguageForm(page, configuration.en);
// Fill form in lang=fr
await this.fillSpecificLanguageForm(page, configuration.fr);
// Save for and get successful message
await this.clickAndWaitForNavigation(page, this.saveButton);
return this.getTextContent(page, this.alertSuccessBlock);
}
}
module.exports = new PS_BANNER();

View File

@@ -0,0 +1,31 @@
// Get resolver
const CommonPage = require('prestashop_test_lib/versions/commonPage.js');
module.exports = class FoBasePage extends CommonPage {
constructor() {
super();
// Selectors
this.languageSelectorDiv = '#_desktop_language_selector';
this.languageSelectorExpandIcon = `${this.languageSelectorDiv} i.expand-more`;
this.languageSelectorMenuItemLink = language => `${this.languageSelectorDiv}`
+ ` ul li a[data-iso-code='${language}']`;
}
// Functions
/**
* Change language in FO
* @param page
* @param lang
* @return {Promise<void>}
*/
async changeLanguage(page, lang = 'en') {
await Promise.all([
page.click(this.languageSelectorExpandIcon),
this.waitForVisibleSelector(page, this.languageSelectorMenuItemLink(lang)),
]);
await this.clickAndWaitForNavigation(page, this.languageSelectorMenuItemLink(lang));
}
};

View File

@@ -0,0 +1,50 @@
const CommonPage = require('@versions/177/FO/foBasePage.js');
class Home extends CommonPage {
constructor() {
super();
// Selectors
this.bannerLink = 'a.banner';
this.bannerImage = `${this.bannerLink} img`;
}
// Functions
/**
* Check is banner is displayed
* @param page
* @return {Promise<boolean>}
*/
isBannerVisible(page) {
return this.elementVisible(page, this.bannerLink, 2000);
}
/**
* Get banner link
* @param page
* @return {Promise<string>}
*/
getBannerLink(page) {
return this.getAttributeContent(page, this.bannerLink, 'href');
}
/**
* Get banner description
* @param page
* @return {Promise<string>}
*/
getBannerDescription(page) {
return this.getAttributeContent(page, this.bannerLink, 'title');
}
/**
* Check if banner image is visible
* @param page
* @return {Promise<boolean>}
*/
bannerHasImage(page) {
return this.elementVisible(page, this.bannerImage, 2000);
}
}
module.exports = new Home();