diff --git a/tests/qa/.env.example b/tests/qa/.env.example new file mode 100644 index 00000000..7fb421ca --- /dev/null +++ b/tests/qa/.env.example @@ -0,0 +1,24 @@ +# MUtkin test singlesite, PHP 8.1 +# playwright-utils config +WP_BASE_URL='https://' +WP_USERNAME= +WP_PASSWORD= +WP_BASIC_AUTH_USER= +WP_BASIC_AUTH_PASS= +STORAGE_STATE_PATH='./storage-states' +STORAGE_STATE_PATH_ADMIN='./storage-states/admin.json' + +# WooCommerce API config +WC_API_KEY= +WC_API_SECRET= + +# Mollie +MOLLIE_LIVE_API_KEY= +MOLLIE_TEST_API_KEY= + +# Testrail +TESTRAIL_URL= +TESTRAIL_USERNAME= +TESTRAIL_PASSWORD= +TESTRAIL_PLAN_ID= +TESTRAIL_RUN_ID= \ No newline at end of file diff --git a/tests/qa/.gitignore b/tests/qa/.gitignore new file mode 100644 index 00000000..8fc08843 --- /dev/null +++ b/tests/qa/.gitignore @@ -0,0 +1,13 @@ +.idea +.vscode +node_modules +playwright-utils +playwright-report +playwright/.cache +storage-states +test-results +package-lock.json +playwright-wordpress-credentials.json + +.env* +!.env.example \ No newline at end of file diff --git a/tests/qa/.npmrc b/tests/qa/.npmrc new file mode 100644 index 00000000..426867c0 --- /dev/null +++ b/tests/qa/.npmrc @@ -0,0 +1 @@ +@inpsyde:registry=https://npm.pkg.github.com \ No newline at end of file diff --git a/tests/qa/README.md b/tests/qa/README.md new file mode 100644 index 00000000..8a9f3613 --- /dev/null +++ b/tests/qa/README.md @@ -0,0 +1,216 @@ +# Mollie Tests Repo + +Mollie Playwright tests. Depends on [`@inpsyde/playwright-utils`](https://github.com/inpsyde/playwright-utils) package. + +__\* - Currently the `@inpsyde/playwright-utils` needs to be installed locally (see section _Installation for local development_ below) and switched to branch `work/misha`.__ + +## Repo structure + +- `resources` - files with test-data, images, project related installation packages, types, etc. + +- `tests` - test specifications. For payment plugins contains following folders: + + - `01-plugin-foundation` - general tests for plugin installation, uninstallation, activation, deactivation, display of plugin in __WooCommerce -> Settings -> Payments__. + + - `02-merchant-setup` - tests for connection of current plugin instance to the payment system provider API via merchant (seller) credentials. + + - `03-plugin-settings` - tests for various plugin settings, may include assertions of settings effect on frontend. + + - `04-frontend-ui` - tests for plugin UI on frontend: display of payment buttons, display of payment methods depending on customer's country, etc. + + - `05-transaction` - tests of payment process. Typically include: adding products to cart as precondition, payment (transaction) process, assertions on order received page, dashboard order edit page, payment via payment system provider API. + + - `06-refund` - tests for refund transactions. Typically include: finished transaction as precondition, refund via payment system provider API on dashboard order edit page, assertion of refund statuses. + + - `07-vaulting` - tests for transactions with enabled vaulting (saved payment methods for registered customers). Ability to remember payment methods and use them for transactions. + + - `08-subscriptions` - tests for transactions for subscription products. Requires WooCommerce Subscriptions plugin. Usually available to registered customers and also includes vaulting and renewal of subscription (with automatic payment). WooCommerce Subscriptions plugin (can be [downloaded here](https://woocommerce.com/my-account/downloads/), login credentials in 1Password). + + - `09-compatibility` - tests for compatibility with other themes, plugins, etc. + + \* - folders are numerated on purpose, to force correct sequence of tests - from basic to advanced. Although each test should be independent and work separately, it is better to start testing from `plugin-foundation` and move to more complex tests. + + \*\* - folders and numeration can be different, based on project requirements. + +- `utils` - project related utility files, built on top of `@inpsyde/playwright-utils`. + + - `admin` - functionality for operating dashboard pages. + + - `frontend` - functionality for operating frontend pages, hosted checkout pages (payment system provider's pages). + + - `test.ts` - declarations of project related test fixtures. + + - other project related functionality, like helpers, APIs, urls. + +- `.env`, `playwright.config.ts`, `package.json` - see below. + +## Installation of `@inpsyde/playwright-utils` + +### Installation as a node package + +1. Remove `"workspaces": [ "playwright-utils" ]` from `package.json`. + +2. In the root of the monorepo run following command: + +```bash +npm run setup:tests +``` + +### Installation for local development + +1. Add `"workspaces": [ "playwright-utils" ]` to `package.json`. + +2. Delete `@inpsyde/playwright-utils` from `/node_modules`. + +3. In the root of the monorepo run following command: + + ```bash + git clone https://github.com/inpsyde/playwright-utils.git + ``` + + [`@inpsyde/playwright-utils`](https://github.com/inpsyde/playwright-utils) repository should be cloned as `playwright-utils` right inside the root directory of monorepo. + +4. Restart VSCode editor. This will create `playwright-utils` instance in the source control tab of VSCode editor. + +5. Run following command: + + ```bash + npm run setup:utils + ``` + +6. `@inpsyde/playwright-utils` should reappear in node_modules. Following message (coming from `tsc-watch`) should be displayed in the terminal: + + ```bash + 10:00:00 - Found 0 errors. Watching for file changes. + ``` + +7. If you plan to make changes in `playwright-utils` keep current terminal window opened and create another instance of terminal. + +## Project configuration + +Project from the monorepo requires a working WordPress website with WooCommmerce, `.env` file and configured Playwright. + +1. [SSE setup](https://inpsyde.atlassian.net/wiki/spaces/AT/pages/3175907370/Self+Service+WordPress+Environment) - will be deprecated in Q1 of 2025. + +2. Tested user with Administrator role should be created + +2. In the Dashboard navigate to __Settings -> Permalinks__ and select `Post name` in __Permalink structure__ for correct format of REST path. + +3. Install __Storefront__ theme. + +4. Install __WooCommerce__ plugin. + +5. In __WooCommerce -> Settings -> Advanced -> REST API__ create _Consumer Key_ and _Secret_ with Read/Write permissions and store them in `.env`. + +6. To avoid conflicts make sure any other payment plugins are deleted. + +7. Configure `.env` file following [these steps](https://github.com/inpsyde/playwright-utils?tab=readme-ov-file#env-variables). See also `.env.example`. + +8. Configure `playwright.config.ts` of the project following [these steps](https://github.com/inpsyde/playwright-utils?tab=readme-ov-file#playwright-configuration). + +9. Reporting. Add `testrail-reporter` in the reporter section of `playwright.config.ts`: + + ```ts + reporter: [ + // other reporters ... + [ '@inpsyde/playwright-utils/build/integration/testrail/testrail-reporter.js' ], + ], + ``` + + Configure connection to TestRail API in `.env` (see `.env.example`): + + ```bash + # Testrail + TESTRAIL_URL=https://website.testrail.io + TESTRAIL_USERNAME=user@company.com + TESTRAIL_PASSWORD=************* + TESTRAIL_PLAN_ID= + TESTRAIL_RUN_ID= + ``` + +## Run tests + +To execute all tests sequentially, in the terminal navigate to the `./tests/qa` directory and run following command: + +```bash +npx playwright test --project=all +``` + +### Additional options to run tests from command line + +- Add scripts to `package.json` of the project (eligible for Windows, not tested on other OS): + + ```json + "scripts": { + "all": "npx playwright test --project=all --workers=1", + "sequential": "npx playwright test --project=sequential --workers=1", + "parallel-surcharge": "npx playwright test --project=surcharge --workers=3" + }, + ``` + + Run script with the following command: + + ```bash + npm run parallel-transactions + ``` + + \* - there's a number of tests which can be executed in parallel to speed up test execution (see `projects` section in `playwright.config.ts`). + +- Run several tests by test ID + + - MacOS, Linux: + + ```bash + npx playwright test --grep "C123|C124|C125" + ``` + + - Windows (Powershell): + + ```bash + npx playwright test --grep --% "C123^|C124^|C125" + ``` + + It may be required additionally to specify the project (if tests relate to more then one project): + + ```bash + npx playwright test --project "project-name" --grep --% "C123^|C124^|C125" + ``` + + +## Autotest Execution workflow + +1. Create test plan with run in TestRail, named after the tested plugin version, for example "Test Plan for Release 1.2.3". + + \* - for autotest run there's no need to manually add tests cases to the run - the executed test will be added automatically before automated execution. + +2. Link release ticket (via `tests: JIR-234`). + +3. Set Test Execution ticket status `In progress`. + +4. Add/update test plan with run IDs in `.env` file of the project (`TESTRAIL_PLAN_ID, TESTRAIL_RUN_ID`). + +5. Download tested plugin `.zip` package (usually attached to release ticket) and add it to `/project//resources/files`. You may need to remove version number from the file name. + +6. Optional: delete previous version of tested plugin from the website if you don't execute __plugin foundation__ tests. + +7. Start autotest execution from command line for the defined scope of tests (e.g. all, Critical, etc.). You should see `Test plan ID: 001, Test run ID: 002` in the terminal. + +8. When finished test results should be exported to the specified test run ticket in Testrail. + +9. Analyze failed tests (if any). Restart execution for failed tests, possibly in debug mode (see section _Additional options to run tests from command line_): + + ```bash + npx playwright test --grep --% "C123^|C124^|C125" --debug + ``` + +10. Report bugs (if any) and attach them to the test-runs of failed tests. + +11. If needed fix failing tests in a new branch, create a PR and assign it for review. + +## Coding standards + +Before commiting changes run following command: + +```bash +npm run lint:js:fix +``` diff --git a/tests/qa/global-setup.ts b/tests/qa/global-setup.ts new file mode 100644 index 00000000..6b53b756 --- /dev/null +++ b/tests/qa/global-setup.ts @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { FullConfig } from '@playwright/test'; +import { restLogin, guestStorageState } from '@inpsyde/playwright-utils/build'; + +async function globalSetup( config: FullConfig ) { + const projectUse = config.projects[ 0 ].use; + + await restLogin( { + baseURL: projectUse.baseURL, + storageStatePath: String( projectUse.storageState ), + httpCredentials: projectUse.httpCredentials, + user: { + // @ts-ignore + username: process.env.WP_USERNAME, + // @ts-ignore + password: process.env.WP_PASSWORD, + }, + } ); + + await guestStorageState( { + baseURL: projectUse.baseURL, + httpCredentials: projectUse.httpCredentials, + storageStatePath: `${ process.env.STORAGE_STATE_PATH }/guest.json`, + } ); +} + +export default globalSetup; diff --git a/tests/qa/package.json b/tests/qa/package.json new file mode 100644 index 00000000..8da031fa --- /dev/null +++ b/tests/qa/package.json @@ -0,0 +1,62 @@ +{ + "name": "mollie-playwright-tests", + "version": "1.0.0", + "description": "Playwright e2e tests for Mollie", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/inpsyde/playwright-tests.git" + }, + "author": { + "name": "Inpsyde GmbH", + "email": "hello@inpsyde.com", + "url": "https://inpsyde.com/" + }, + "license": "GPL-3.0-or-later", + "bugs": { + "url": "https://github.com/inpsyde/playwright-tests/issues" + }, + "homepage": "https://github.com/inpsyde/playwright-tests#readme", + "dependencies": { + "@inpsyde/playwright-utils": "^2.0.0-beta.2", + "dotenv": "^16.3.1", + "dotenv-cli": "^7.3.0", + "playwright": "^1.40.1", + "yarn": "^1.22.21" + }, + "devDependencies": { + "@percy/cli": "^1.28.0", + "@percy/playwright": "^1.0.4", + "@playwright/test": "^1.38.1", + "@types/node": "^20.8.4", + "@wordpress/scripts": "^25.0.0" + }, + "scripts": { + "setup:tests": "npm install && npx playwright install", + "setup:utils": "npm run setup:tests && cd ./playwright-utils && yarn devLocal", + "lint:md": "wp-scripts lint-md-docs ./**/*.md README.md", + "lint:js": "wp-scripts lint-js ./**/*.{ts,tsx,mjs} projects/**/.*/*.{ts,tsx,mjs}", + "lint:js:fix": "wp-scripts lint-js --fix ./**/*.{ts,tsx,mjs} ./**/**/*.{ts,tsx,mjs} ./**/.*/*.{ts,tsx,mjs} ./**/**/.*/*.{ts,tsx,mjs}", + "all": "npx playwright test --project=all --workers=1", + "sequential": "npx playwright test --project=sequential --workers=1", + "parallel-transaction-eur-classic": "npx playwright test --project=transaction-eur-classic --workers=5", + "parallel-transaction-eur-block": "npx playwright test --project=transaction-eur-block --workers=3", + "transaction-non-eur": "npx playwright test --project=transaction-non-eur workers=1", + "parallel-surcharge": "npx playwright test --project=surcharge --workers=3", + "parallel-transactions": "npm run parallel-transaction-eur-block & npm run parallel-transaction-eur-classic", + "all-with-parallel": "npm run sequential & npm run parallel-surcharge & npm run parallel-transactions" + }, + "eslintConfig": { + "extends": [ + "plugin:@wordpress/eslint-plugin/recommended" + ], + "rules": { + "@wordpress/dependency-group": "error", + "@wordpress/no-unsafe-wp-apis": "off", + "no-console": "off" + } + }, + "workspaces": [ + "playwright-utils" + ] +} diff --git a/tests/qa/playwright.config.ts b/tests/qa/playwright.config.ts new file mode 100644 index 00000000..88fdd78b --- /dev/null +++ b/tests/qa/playwright.config.ts @@ -0,0 +1,137 @@ +/** + * External dependencies + */ +import { defineConfig, devices } from '@playwright/test'; +require( 'dotenv' ).config(); + +export default defineConfig( { + testDir: 'tests', + expect: { + timeout: 10 * 1000, + }, + timeout: 1 * 60 * 1000, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !! process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : 1, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: process.env.CI + ? [ + [ 'list' ], + // [ 'html', { outputFolder: 'playwright-report' } ], + [ + '@inpsyde/playwright-utils/build/integration/testrail/testrail-reporter.js', + ], + ] + : [ + [ 'list' ], + // [ 'html', { outputFolder: 'playwright-report' } ], + [ + '@inpsyde/playwright-utils/build/integration/testrail/testrail-reporter.js', + ], + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + + globalSetup: require.resolve( './global-setup' ), + + use: { + baseURL: process.env.WP_BASE_URL, + + storageState: process.env.STORAGE_STATE_PATH_ADMIN, + + httpCredentials: { + // @ts-ignore + username: process.env.WP_BASIC_AUTH_USER, + // @ts-ignore + password: process.env.WP_BASIC_AUTH_PASS, + }, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + // Capture screenshot after each test failure. + screenshot: 'only-on-failure', //'off', // + + // Record video only when retrying a test for the first time. + video: 'retain-on-failure', //'on', // + + ...devices[ 'Desktop Chrome' ], + + viewport: { width: 1280, height: 850 }, + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'setup-woocommerce', + testMatch: /woocommerce\.setup\.ts/, + fullyParallel: false, + }, + { + name: 'setup-mollie', + testMatch: /mollie-default\.setup\.ts/, + dependencies: [ 'setup-woocommerce' ], + fullyParallel: false, + }, + { + name: 'setup-pages-classic', + testMatch: /pages-classic\.setup\.ts/, + dependencies: [ 'setup-woocommerce' ], + fullyParallel: false, + }, + { + name: 'setup-pages-block', + testMatch: /pages-block\.setup\.ts/, + dependencies: [ 'setup-woocommerce' ], + fullyParallel: false, + }, + { + name: 'all', + dependencies: [ 'setup-woocommerce' ], + fullyParallel: false, + }, + { + name: 'sequential', + dependencies: [ 'setup-woocommerce' ], + fullyParallel: false, + testIgnore: [ + 'surcharge.spec.ts', + 'eur-checkout-classic.spec.ts', + 'eur-checkout.spec.ts', + 'eur-pay-for-order.spec.ts', + ], + }, + { + name: 'transaction-non-eur', + dependencies: [ 'setup-mollie' ], + testMatch: [ + 'non-eur-checkout-classic.spec.ts', + 'non-eur-checkout.spec.ts', + 'non-eur-pay-for-order.spec.ts', + ], + fullyParallel: false, + }, + { + name: 'surcharge', + dependencies: [ 'setup-mollie', 'setup-pages-classic' ], + testMatch: [ 'surcharge.spec.ts' ], + fullyParallel: true, + }, + { + name: 'transaction-eur-classic', + dependencies: [ 'setup-mollie', 'setup-pages-classic' ], + testMatch: [ 'eur-checkout-classic.spec.ts' ], + fullyParallel: true, + }, + { + name: 'transaction-eur-block', + dependencies: [ 'setup-mollie', 'setup-pages-block' ], + testMatch: [ 'eur-checkout.spec.ts', 'eur-pay-for-order.spec.ts' ], + fullyParallel: true, + }, + ], +} ); diff --git a/tests/qa/resources/cards.ts b/tests/qa/resources/cards.ts new file mode 100644 index 00000000..bef1064b --- /dev/null +++ b/tests/qa/resources/cards.ts @@ -0,0 +1,14 @@ +export const cardTypes = [ 'Visa' ]; + +const visa: WooCommerce.CreditCard = { + card_holder: 'Carl Holdersson', + card_number: '4543474002249996', + expiration_date: '12/2030', + card_cvv: '123', +}; + +export const cards: { + [ key: string ]: WooCommerce.CreditCard; +} = { + visa, +}; diff --git a/tests/qa/resources/disable-nonce-plugin.ts b/tests/qa/resources/disable-nonce-plugin.ts new file mode 100644 index 00000000..97f4bde3 --- /dev/null +++ b/tests/qa/resources/disable-nonce-plugin.ts @@ -0,0 +1,7 @@ +export default { + name: 'Disable nonce check', + slug: 'disable-nonce-check', + zipFile: 'disable-nonce.zip', + zipFilePath: './resources/files/disable-nonce.zip', + version: '', +}; diff --git a/tests/qa/resources/files/disable-nonce.zip b/tests/qa/resources/files/disable-nonce.zip new file mode 100644 index 00000000..52297a2d Binary files /dev/null and b/tests/qa/resources/files/disable-nonce.zip differ diff --git a/tests/qa/resources/files/disable-wc-setup-wizard.zip b/tests/qa/resources/files/disable-wc-setup-wizard.zip new file mode 100644 index 00000000..9d316ff2 Binary files /dev/null and b/tests/qa/resources/files/disable-wc-setup-wizard.zip differ diff --git a/tests/qa/resources/files/mollie-payments-for-woocommerce.zip b/tests/qa/resources/files/mollie-payments-for-woocommerce.zip new file mode 100644 index 00000000..d07bb3d6 Binary files /dev/null and b/tests/qa/resources/files/mollie-payments-for-woocommerce.zip differ diff --git a/tests/qa/resources/files/mollie-test-logo.png b/tests/qa/resources/files/mollie-test-logo.png new file mode 100644 index 00000000..c493571d Binary files /dev/null and b/tests/qa/resources/files/mollie-test-logo.png differ diff --git a/tests/qa/resources/files/woocommerce-subscriptions.zip b/tests/qa/resources/files/woocommerce-subscriptions.zip new file mode 100644 index 00000000..a7392424 Binary files /dev/null and b/tests/qa/resources/files/woocommerce-subscriptions.zip differ diff --git a/tests/qa/resources/gateways.ts b/tests/qa/resources/gateways.ts new file mode 100644 index 00000000..024794d5 --- /dev/null +++ b/tests/qa/resources/gateways.ts @@ -0,0 +1,477 @@ +/** + * Internal dependencies + */ +import { MollieGateway, MollieSettings } from './types'; + +export const defaultGatewaySettings: MollieSettings.Gateway = { + enableGateway: true, + useApiTitle: false, + displayLogo: true, + enableCustomLogo: false, + description: '', + sellToCountries: [], + + payment_surcharge: 'no_fee', + fixed_fee: '', + maximum_limit: '', + percentage: '', + surcharge_limit: '', + + activateExpiryDaysSetting: false, + orderDueDate: '10', + enableMollieComponents: false, +}; + +const alma: MollieGateway = { + country: 'france', // Belgium also supported + minAmount: '50.00', + maxAmount: '2000.00', + slug: 'alma', + name: 'Pay in 3 or 4 installments free of charge', + settings: { + ...defaultGatewaySettings, + title: 'Pay in 3 or 4 installments free of charge', + }, +}; + +const applepay: MollieGateway = { + country: 'germany', // Global availability + minAmount: '0.01', + slug: 'applepay', + name: 'Apple Pay', + settings: { + ...defaultGatewaySettings, + title: 'Apple Pay', + enableApplePayButtonOnCart: false, + enableApplePayButtonOnProduct: false, + enableApplePayExpressButtonOnCheckout: false, + }, +}; + +const bacs: MollieGateway = { + country: 'uk', + minAmount: '1.00', + slug: 'bacs', + name: 'BACS Direct Debit', + currency: 'GBP', + settings: { + ...defaultGatewaySettings, + title: 'BACS Direct Debit', + }, +}; + +const bancomatpay: MollieGateway = { + country: 'italy', + minAmount: '0.01', + slug: 'bancomatpay', + name: 'Bancomat Pay', + settings: { + ...defaultGatewaySettings, + title: 'Bancomat Pay', + }, +}; + +const bancontact: MollieGateway = { + country: 'belgium', + minAmount: '1.00', + maxAmount: '50000.00', + slug: 'bancontact', + name: 'Bancontact', + settings: { + ...defaultGatewaySettings, + title: 'Bancontact', + initialOrderStatus: 'on-hold', + }, +}; + +const banktransfer: MollieGateway = { + country: 'germany', // Europe + minAmount: '1.00', + slug: 'banktransfer', + name: 'Bank transfer', + settings: { + ...defaultGatewaySettings, + title: 'Bank transfer', + initialOrderStatus: 'on-hold', + orderDueDate: '12', + banktransferSkipMolliePaymentScreen: false, + }, +}; + +const belfius: MollieGateway = { + country: 'belgium', + minAmount: '0.01', + slug: 'belfius', + name: 'Belfius Pay Button', + settings: { + ...defaultGatewaySettings, + title: 'Belfius Pay Button', + initialOrderStatus: 'on-hold', + }, +}; + +const billie: MollieGateway = { + country: 'germany', // Netherlands also supported + minAmount: '100.00', + maxAmount: '50000.00', + slug: 'billie', + name: 'Pay by Invoice for Businesses - Billie', + settings: { + ...defaultGatewaySettings, + title: 'Pay by Invoice for Businesses - Billie', + }, +}; + +const blik: MollieGateway = { + country: 'poland', + minAmount: '1.00', + maxAmount: '10000.00', + slug: 'blik', + name: 'Blik', + currency: 'PLN', + settings: { + ...defaultGatewaySettings, + title: 'Blik', + }, +}; + +const creditcard: MollieGateway = { + country: 'germany', // Global availability + minAmount: '0.01', + slug: 'creditcard', + name: 'Card', + settings: { + ...defaultGatewaySettings, + title: 'Card', + enableMollieComponents: false, + enableMollieCreditcardIcons: false, + enableMollieCreditcardIconsAmex: false, + enableMollieCreditcardIconsCartaSi: false, + enableMollieCreditcardICarteBancaire: false, + enableMollieCreditcardIconsMaestro: false, + enableMollieCreditcardIconsMastercard: false, + enableMollieCreditcardIconsVisa: false, + enableMollieCreditcardIconsVpay: false, + }, +}; + +const directdebit: MollieGateway = { + country: 'germany', // Europe + minAmount: '1.00', + slug: 'directdebit', + name: 'SEPA Direct Debit', + settings: { + ...defaultGatewaySettings, + title: 'SEPA Direct Debit', + initialOrderStatus: 'on-hold', + }, +}; + +const eps: MollieGateway = { + country: 'austria', + minAmount: '0.01', + slug: 'eps', + name: 'eps', + settings: { + ...defaultGatewaySettings, + title: 'eps', + initialOrderStatus: 'on-hold', + }, +}; + +const giftcard: MollieGateway = { + country: 'germany', + minAmount: '0.01', + slug: 'giftcard', + name: 'Gift cards', + settings: { + ...defaultGatewaySettings, + title: 'Gift cards', + description: 'Select your gift card', + showIssuersDropdown: true, + issuersEmptyOption: 'Select your gift card', + }, +}; + +const ideal: MollieGateway = { + country: 'netherlands', + minAmount: '1.00', + maxAmount: '50000.00', + slug: 'ideal', + name: 'iDEAL', + settings: { + ...defaultGatewaySettings, + title: 'iDEAL', + initialOrderStatus: 'on-hold', + }, +}; + +const in3: MollieGateway = { + country: 'netherlands', + minAmount: '100.00', + maxAmount: '5000.00', + slug: 'in3', + name: 'iDEAL Pay in 3 instalments, 0% interest', + settings: { + ...defaultGatewaySettings, + title: 'iDEAL Pay in 3 instalments, 0% interest', + description: 'iDEAL Pay in 3 instalments, 0% interest', + }, +}; + +const kbc: MollieGateway = { + country: 'belgium', + minAmount: '1.00', + slug: 'kbc', + name: 'KBC/CBC Payment Button', + settings: { + ...defaultGatewaySettings, + title: 'KBC/CBC Payment Button', + description: 'Select your bank', + showIssuersDropdown: true, + issuersEmptyOption: 'Select your bank', + initialOrderStatus: 'on-hold', + }, +}; + +const klarna: MollieGateway = { + country: 'germany', // AT, BE, DK, FI, FR, DE, IT, IE, NL, NO, PT, ES, SE, IE, CH, UK + minAmount: '1.00', + slug: 'klarna', + name: 'Pay with Klarna', + settings: { + ...defaultGatewaySettings, + title: 'Pay with Klarna', + }, +}; + +const mybank: MollieGateway = { + country: 'italy', + minAmount: '1.00', + slug: 'mybank', + name: 'MyBank', + settings: { + ...defaultGatewaySettings, + title: 'MyBank', + }, +}; + +const paybybank: MollieGateway = { + country: 'uk', + minAmount: '1.00', + slug: 'paybybank', + name: 'Pay by Bank', + currency: 'GBP', + settings: { + ...defaultGatewaySettings, + title: 'Pay by Bank', + }, +}; + +const payconiq: MollieGateway = { + country: 'belgium', + minAmount: '0.01', + slug: 'payconiq', + name: 'Payconiq', + settings: { + ...defaultGatewaySettings, + title: 'Payconiq', + }, +}; + +const paypal: MollieGateway = { + country: 'germany', // Global availability + minAmount: '0.01', + slug: 'paypal', + name: 'PayPal', + settings: { + ...defaultGatewaySettings, + title: 'PayPal', + paypalDisplayOnCart: false, + paypalDisplayOnProduct: false, + paypalButtonTextLanguageAndColor: 'en-buy-pill-blue', + paypalMinimumAmountToDisplayButton: '0', + }, +}; + +const paysafecard: MollieGateway = { + country: 'germany', + minAmount: '1.00', + maxAmount: '1000.00', + slug: 'paysafecard', + name: 'paysafecard', + settings: { + ...defaultGatewaySettings, + title: 'paysafecard', + }, +}; + +const pointofsale: MollieGateway = { + country: 'germany', + minAmount: '1.00', + slug: 'pointofsale', + name: 'Point of sale', + settings: { + ...defaultGatewaySettings, + title: 'Point of sale', + }, +}; + +const przelewy24: MollieGateway = { + country: 'poland', + minAmount: '1.00', + slug: 'przelewy24', + name: 'Przelewy24', + settings: { + ...defaultGatewaySettings, + title: 'Przelewy24', + }, +}; + +const riverty: MollieGateway = { + country: 'germany', + minAmount: '50.00', + maxAmount: '2000.00', + slug: 'riverty', + name: 'Buy now, pay later with Riverty', + settings: { + ...defaultGatewaySettings, + title: 'Buy now, pay later with Riverty', + }, +}; + +const satispay: MollieGateway = { + country: 'italy', + minAmount: '1.00', + slug: 'satispay', + name: 'Satispay', + settings: { + ...defaultGatewaySettings, + title: 'Satispay', + }, +}; + +const trustly: MollieGateway = { + country: 'germany', // Europe + minAmount: '1.00', + slug: 'trustly', + name: 'Trustly', + settings: { + ...defaultGatewaySettings, + title: 'Trustly', + initialOrderStatus: 'on-hold', + }, +}; + +const twint: MollieGateway = { + country: 'switzerland', + minAmount: '0.01', + slug: 'twint', + name: 'TWINT', + currency: 'CHF', + settings: { + ...defaultGatewaySettings, + title: 'TWINT', + }, +}; + +const voucher: MollieGateway = { + country: 'germany', + minAmount: '1.00', + slug: 'voucher', + name: 'Vouchers', + settings: { + ...defaultGatewaySettings, + title: 'Vouchers', + voucherDefaultProductsCategory: 'no_category', + }, +}; + +// Deprecated gateways +const giropay: MollieGateway = { + country: 'germany', + minAmount: '1.00', + slug: 'giropay', + name: 'Giropay', + settings: { + ...defaultGatewaySettings, + title: 'Giropay', + initialOrderStatus: 'on-hold', + }, +}; + +const klarnapaylater: MollieGateway = { + country: 'germany', // Austria, Germany, Netherlands + minAmount: '50.00', + maxAmount: '2000.00', + slug: 'klarnapaylater', + name: 'Pay later.', + settings: { + ...defaultGatewaySettings, + title: 'Pay later.', + }, +}; + +const klarnapaynow: MollieGateway = { + country: 'germany', // Austria, Germany, Netherlands + minAmount: '50.00', + maxAmount: '2000.00', + slug: 'klarnapaynow', + name: 'Pay now.', + settings: { + ...defaultGatewaySettings, + title: 'Pay now.', + }, +}; + +const klarnasliceit: MollieGateway = { + country: 'germany', // Austria, Germany, Netherlands + minAmount: '50.00', + maxAmount: '2000.00', + slug: 'klarnasliceit', + name: 'Slice it.', + settings: { + ...defaultGatewaySettings, + title: 'Slice it.', + }, +}; + +export const gateways: { + [ key: string ]: MollieGateway; +} = { + alma, // >50.00 + // applepay, + // bacs, // currency: GBP + bancomatpay, + bancontact, + banktransfer, + belfius, + billie, // >100.00 + blik, // currency: PLN + creditcard, + directdebit, + eps, + giftcard, + ideal, + in3, // >100.00 + kbc, + klarna, + mybank, + // paybybank, // currency: GBP + payconiq, + paypal, + paysafecard, + // pointofsale, + przelewy24, + riverty, // >50.00 + satispay, + trustly, + twint, // currency: CHF + voucher, + + // Deprecated gateways + // giropay, + // klarnapaylater, // >50.00 + // klarnapaynow, // >50.00 + // klarnasliceit, // >50.00 +}; diff --git a/tests/qa/resources/index.ts b/tests/qa/resources/index.ts new file mode 100644 index 00000000..6587a341 --- /dev/null +++ b/tests/qa/resources/index.ts @@ -0,0 +1,22 @@ +export { + shopSettings, + shippingZones, + flatRate, + freeShipping, + guests, + customers, + taxSettings, + coupons, + orders, +} from '@inpsyde/playwright-utils/build/e2e/plugins/woocommerce'; + +export * from './products'; +export * from './gateways'; +export * from './cards'; +export * from './mollie-config'; +export * from './woocommerce-config'; +export * from './types'; + +export { default as molliePlugin } from './mollie-plugin'; +export { default as disableNoncePlugin } from './disable-nonce-plugin'; +export { default as subscriptionsPlugin } from './woocommerce-subscriptions-plugin'; diff --git a/tests/qa/resources/mollie-config.ts b/tests/qa/resources/mollie-config.ts new file mode 100644 index 00000000..62128e53 --- /dev/null +++ b/tests/qa/resources/mollie-config.ts @@ -0,0 +1,19 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from './types'; + +export const mollieConfigGeneral: { + [ key: string ]: MollieSettings.ApiKeys; +} = { + empty: { + testModeEnabled: 'yes', + liveApiKey: '', + testApiKey: '', + }, + default: { + testModeEnabled: 'yes', + liveApiKey: process.env.MOLLIE_LIVE_API_KEY, + testApiKey: process.env.MOLLIE_TEST_API_KEY, + }, +}; diff --git a/tests/qa/resources/mollie-plugin.ts b/tests/qa/resources/mollie-plugin.ts new file mode 100644 index 00000000..0e3c71d7 --- /dev/null +++ b/tests/qa/resources/mollie-plugin.ts @@ -0,0 +1,7 @@ +export default { + name: 'Mollie Payments for WooCommerce', + slug: 'mollie-payments-for-woocommerce', + zipFile: 'mollie-for-woocommerce.zip', + zipFilePath: './resources/files/mollie-payments-for-woocommerce.zip', + version: '7.8.1', +}; diff --git a/tests/qa/resources/products.ts b/tests/qa/resources/products.ts new file mode 100644 index 00000000..38f7f212 --- /dev/null +++ b/tests/qa/resources/products.ts @@ -0,0 +1,162 @@ +const mollieSurcharge10: WooCommerce.CreateProduct = { + name: 'Mollie Surcharge Test Product 10', + slug: 'mollie-product-surcharge-10', + type: 'simple', + regular_price: '10.00', + description: 'Mollie surcharge product, mollie surcharge product.', + short_description: 'Libre prodotto.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/cap-2.jpg', + }, + ], + sale_price: '10.00', + virtual: false, + downloadable: false, +}; + +const mollieSimple10: WooCommerce.CreateProduct = { + name: 'Mollie Simple Test Product 10', + slug: 'mollie-product-simple-10', + type: 'simple', + regular_price: '10.00', + description: + 'Our clothes are juicy, sweet, and ideal for a healthy snack or enhancing your favorite recipes.', + short_description: 'Fresh, crisp clothes perfect for snacks and desserts.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg', + }, + ], + virtual: false, + downloadable: false, +}; + +const mollieSimple50: WooCommerce.CreateProduct = { + name: 'Mollie Simple Test Product 50', + slug: 'mollie-product-simple-50', + type: 'simple', + regular_price: '50.00', + description: + 'Our clothes are juicy, sweet, and ideal for a healthy snack or enhancing your favorite recipes.', + short_description: 'Fresh, crisp clothes perfect for snacks and desserts.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg', + }, + ], + virtual: false, + downloadable: false, +}; + +const mollieSimple100: WooCommerce.CreateProduct = { + name: 'Mollie Simple Test Product 100', + slug: 'mollie-product-simple-100', + type: 'simple', + regular_price: '100.00', + description: + 'Our clothes are juicy, sweet, and ideal for a healthy snack or enhancing your favorite recipes.', + short_description: 'Fresh, crisp clothes perfect for snacks and desserts.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg', + }, + ], + virtual: false, + downloadable: false, +}; + +const mollieSimple18: WooCommerce.CreateProduct = { + name: 'Mollie Simple Test Product 18', + slug: 'mollie-product-simple-18', + type: 'simple', + regular_price: '20.00', + description: + 'Our clothes are juicy, sweet, and ideal for a healthy snack or enhancing your favorite recipes.', + short_description: 'Fresh, crisp clothes perfect for snacks and desserts.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/beanie-2.jpg', + }, + ], + sale_price: '18.00', + virtual: false, + downloadable: false, +}; + +const mollieVirtual10: WooCommerce.CreateProduct = { + name: 'Mollie Virtual Test Product 10', + slug: 'mollie-product-virtual-10', + type: 'simple', + regular_price: '10.00', + description: + 'Our clothes are juicy, sweet, and ideal for a healthy snack or enhancing your favorite recipes.', + short_description: 'Fresh, crisp clothes perfect for snacks and desserts.', + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/sunglasses-2.jpg', + }, + ], + virtual: true, + downloadable: true, +}; + +const mollieVariable10: WooCommerce.CreateProduct = { + name: 'Mollie Variable Test Product 10', + slug: 'mollie-product-variable-10', + type: 'variable', + regular_price: '10.00', + description: + 'Green and red clothes. Green and red clothes. Green and red clothes.', + short_description: 'Green and blue clothes.', + attributes: [ + { + name: 'Color', + variation: true, + options: [ 'Blue', 'Green' ], + }, + ], + default_attributes: [ + { + name: 'Color', + option: 'Blue', + }, + ], + variations: [ + { + attributes: [ + { + id: '0', + option: 'Blue', + }, + { + id: '0', + option: 'Green', + }, + ], + regular_price: '10.00', + stock_status: 'instock', + manage_stock: false, + }, + ], + images: [ + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-blue-1.jpg', + }, + { + src: 'https://woocommercecore.mystagingwebsite.com/wp-content/uploads/2017/12/hoodie-green-1.jpg', + }, + ], +}; + +export const products: { + [ key: string ]: WooCommerce.CreateProduct; +} = { + mollieSurcharge10, + mollieSimple10, + mollieSimple50, + mollieSimple100, + mollieSimple18, + mollieVirtual10, + mollieVariable10, +}; diff --git a/tests/qa/resources/types.ts b/tests/qa/resources/types.ts new file mode 100644 index 00000000..cb691ee4 --- /dev/null +++ b/tests/qa/resources/types.ts @@ -0,0 +1,245 @@ +export namespace MollieSettings { + export type ApiKeys = { + testModeEnabled?: 'yes' | 'no'; + liveApiKey?: string; + testApiKey?: string; + }; + + export type OrderStatusCancelledPayment = 'pending' | 'cancelled'; + + export type PaymentLocale = + | 'detect_by_browser' + | 'en_US' + | 'nl_NL' + | 'nl_BE' + | 'fr_FR' + | 'fr_BE' + | 'de_DE' + | 'de_AT' + | 'de_CH' + | 'es_ES' + | 'ca_ES' + | 'pt_PT' + | 'it_IT' + | 'nb_NO' + | 'sv_SE' + | 'fi_FI' + | 'da_DK' + | 'is_IS' + | 'hu_HU' + | 'pl_PL' + | 'lv_LV' + | 'lt_LT'; + + export type ApiMethod = 'order' | 'payment'; + + export type ApiPaymentDescription = + | '{orderNumber}' + | '{storeName}' + | '{customer.firstname}' + | '{customer.lastname}' + | '{customer.company}'; + + export type PaymentCapture = 'immediate_capture' | 'later_capture'; + + export type Advanced = { + debugLogEnabled?: boolean; + orderStatusCancelledPayments?: OrderStatusCancelledPayment; + paymentLocale?: PaymentLocale; + customerDetails?: boolean; + apiMethod?: ApiMethod; + apiPaymentDescription?: ApiPaymentDescription; + gatewayFeeLabel?: string; + removeOptionsAndTransients?: boolean; + placePaymentOnhold?: PaymentCapture; + }; + + export type PaymentSurcharge = + | 'no_fee' + | 'fixed_fee' + | 'percentage' + | 'fixed_fee_percentage'; + + export type InitialOrderStatus = 'on-hold' | 'pending'; + + export type PaypalButtonTextLanguageAndColor = + | 'en-buy-pill-blue' + | 'en-buy-rounded-blue' + | 'en-buy-pill-golden' + | 'en-buy-rounded-golden' + | 'en-buy-pill-gray' + | 'en-buy-rounded-gray' + | 'en-buy-pill-white' + | 'en-buy-rounded-white' + | 'en-checkout-pill-black' + | 'en-checkout-rounded-black' + | 'en-checkout-pill-blue' + | 'en-checkout-rounded-blue' + | 'en-checkout-pill-golden' + | 'en-checkout-rounded-golden' + | 'en-checkout-pill-gray' + | 'en-checkout-rounded-gray' + | 'en-checkout-pill-white' + | 'en-checkout-rounded-white' + | 'nl-buy-pill-black' + | 'nl-buy-rounded-black' + | 'nl-buy-pill-blue' + | 'nl-buy-rounded-blue' + | 'nl-buy-pill-golden' + | 'nl-buy-rounded-golden' + | 'nl-buy-pill-gray' + | 'nl-buy-rounded-gray' + | 'nl-buy-pill-white' + | 'nl-buy-rounded-white' + | 'nl-checkout-pill-black' + | 'nl-checkout-rounded-black' + | 'nl-checkout-pill-blue' + | 'nl-checkout-rounded-blue' + | 'nl-checkout-pill-golden' + | 'nl-checkout-rounded-golden' + | 'nl-checkout-pill-gray' + | 'nl-checkout-rounded-gray' + | 'nl-checkout-pill-white' + | 'nl-checkout-rounded-white' + | 'de-buy-pill-black' + | 'de-buy-rounded-black' + | 'de-buy-pill-blue' + | 'de-buy-rounded-blue' + | 'de-buy-pill-golden' + | 'de-buy-rounded-golden' + | 'de-buy-pill-gray' + | 'de-buy-rounded-gray' + | 'de-buy-pill-white' + | 'de-buy-rounded-white' + | 'de-checkout-pill-black' + | 'de-checkout-rounded-black' + | 'de-checkout-pill-blue' + | 'de-checkout-rounded-blue' + | 'de-checkout-pill-golden' + | 'de-checkout-rounded-golden' + | 'de-checkout-pill-gray' + | 'de-checkout-rounded-gray' + | 'de-checkout-pill-white' + | 'de-checkout-rounded-white' + | 'fr-buy-rounded-gold' + | 'fr-checkout-rounded-gold' + | 'fr-checkout-rounded-silver' + | 'pl-buy-rounded-gold' + | 'pl-checkout-rounded-gold' + | 'pl-checkout-rounded-silver'; + + export type VoucherProductCategory = + | 'no_category' + | 'meal' + | 'eco' + | 'gift'; + + export type Gateway = { + enableGateway?: boolean; + useApiTitle?: boolean; + title?: string; + displayLogo?: boolean; + enableCustomLogo?: boolean; + customLogoPath?: string; + description?: string; + sellToCountries?: string[]; + + payment_surcharge?: PaymentSurcharge; + fixed_fee?: string; + maximum_limit?: string; + percentage?: string; + surcharge_limit?: string; + + activateExpiryDaysSetting?: boolean; + orderDueDate?: string; + showIssuersDropdown?: boolean; + initialOrderStatus?: InitialOrderStatus; + enableMollieComponents?: boolean; + issuersEmptyOption?: string; + + banktransferSkipMolliePaymentScreen?: boolean; + + enableApplePayButtonOnCart?: boolean; + enableApplePayButtonOnProduct?: boolean; + enableApplePayExpressButtonOnCheckout?: boolean; + + paypalDisplayOnCart?: boolean; + paypalDisplayOnProduct?: boolean; + paypalButtonTextLanguageAndColor?: PaypalButtonTextLanguageAndColor; + paypalMinimumAmountToDisplayButton?: string; + + giftcardShowDropdown?: boolean; + + kbcShowBanksDropdown?: boolean; + + voucherDefaultProductsCategory?: VoucherProductCategory; + + enableMollieCreditcardIcons?: boolean; + enableMollieCreditcardIconsAmex?: boolean; + enableMollieCreditcardIconsCartaSi?: boolean; + enableMollieCreditcardICarteBancaire?: boolean; + enableMollieCreditcardIconsMaestro?: boolean; + enableMollieCreditcardIconsMastercard?: boolean; + enableMollieCreditcardIconsVisa?: boolean; + enableMollieCreditcardIconsVpay?: boolean; + }; +} + +export type MollieGateway = { + slug: string; + name: string; + country: string; + currency?: string; + minAmount?: string; + maxAmount?: string; + settings?: MollieSettings.Gateway; +}; + +export type MolliePaymentStatus = + | 'open' + | 'pending' + | 'paid' + | 'authorized' + | 'failed' + | 'canceled' + | 'expired'; + +export type BankIssuer = + | 'ABN AMRO' + | 'ING' + | 'Rabobank' + | 'ASN Bank' + | 'bunq' + | 'Knab' + | 'N26' + | 'NN' + | 'Regiobank' + | 'Revolut' + | 'SNS Bank' + | 'Triodos' + | 'Van Lanschot Kempen' + | 'Yoursafe' + | 'CBC' + | 'KBC'; + +export type MolliePayment = { + gateway: MollieGateway; + status: MolliePaymentStatus; + bankIssuer?: BankIssuer; + card?: WooCommerce.CreditCard; + isVaulted?: boolean; + saveToAccount?: boolean; + amount?: number; +}; + +export namespace MollieTestData { + export type PaymentStatus = { + testId: string; + gatewaySlug: string; + paymentStatus: MolliePaymentStatus; + orderStatus: WooCommerce.OrderStatus; + card?: WooCommerce.CreditCard; + bankIssuer?: string; + billingCompany?: string; + }; +} diff --git a/tests/qa/resources/woocommerce-config.ts b/tests/qa/resources/woocommerce-config.ts new file mode 100644 index 00000000..a60c35d1 --- /dev/null +++ b/tests/qa/resources/woocommerce-config.ts @@ -0,0 +1,52 @@ +/** + * Internal dependencies + */ +import { shopSettings, customers } from '.'; + +const country = 'germany'; + +export const shopConfigDefault = { + classicPages: false, // false = block cart and checkout (default), true = classic cart & checkout pages + wpDebugging: false, // WP Debugging plugin is deactivated + subscription: false, // WC Subscription plugin is deactivated + settings: shopSettings[ country ], // WC general settings + customer: customers[ country ], // registered customer +}; + +export const shopConfigClassic = { + ...shopConfigDefault, + classicPages: true, +}; + +export const shopConfigGermany = { + ...shopConfigDefault, + customer: customers.germany, +}; + +export const shopConfigUsa = { + ...shopConfigDefault, + wpDebugging: true, + settings: shopSettings.usa, + customer: customers.usa, +}; + +export const shopConfigMexico = { + ...shopConfigDefault, + settings: shopSettings.mexico, + customer: customers.mexico, +}; + +const shopConfigSubscription = { + // requireFinalConfirmation: false, + subscription: true, +}; + +export const shopConfigSubscriptionGermany = { + ...shopConfigGermany, + ...shopConfigSubscription, +}; + +export const shopConfigSubscriptionUsa = { + ...shopConfigUsa, + ...shopConfigSubscription, +}; diff --git a/tests/qa/resources/woocommerce-subscriptions-plugin.ts b/tests/qa/resources/woocommerce-subscriptions-plugin.ts new file mode 100644 index 00000000..a1435bb5 --- /dev/null +++ b/tests/qa/resources/woocommerce-subscriptions-plugin.ts @@ -0,0 +1,7 @@ +export default { + name: 'WooCommerce Subscriptions', + slug: 'woocommerce-subscriptions', + zipFile: 'woocommerce-subscriptions.zip', + zipFilePath: './resources/files/woocommerce-subscriptions.zip', + version: '', +}; diff --git a/tests/qa/tests/.setup/mollie-default.setup.ts b/tests/qa/tests/.setup/mollie-default.setup.ts new file mode 100644 index 00000000..104dd59e --- /dev/null +++ b/tests/qa/tests/.setup/mollie-default.setup.ts @@ -0,0 +1,9 @@ +/** + * Internal dependencies + */ +import { test as setup } from '../../utils'; + +setup( 'Setup and reconnect Mollie', async ( { utils } ) => { + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); diff --git a/tests/qa/tests/.setup/pages-block.setup.ts b/tests/qa/tests/.setup/pages-block.setup.ts new file mode 100644 index 00000000..85816ee0 --- /dev/null +++ b/tests/qa/tests/.setup/pages-block.setup.ts @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { test as setup } from '../../utils'; + +setup( 'Setup Block checkout pages', async ( { utils } ) => { + await utils.configureStore( { classicPages: false } ); +} ); diff --git a/tests/qa/tests/.setup/pages-classic.setup.ts b/tests/qa/tests/.setup/pages-classic.setup.ts new file mode 100644 index 00000000..270ec24a --- /dev/null +++ b/tests/qa/tests/.setup/pages-classic.setup.ts @@ -0,0 +1,8 @@ +/** + * Internal dependencies + */ +import { test as setup } from '../../utils'; + +setup( 'Setup Classic checkout pages', async ( { utils } ) => { + await utils.configureStore( { classicPages: true } ); +} ); diff --git a/tests/qa/tests/.setup/woocommerce.setup.ts b/tests/qa/tests/.setup/woocommerce.setup.ts new file mode 100644 index 00000000..13826852 --- /dev/null +++ b/tests/qa/tests/.setup/woocommerce.setup.ts @@ -0,0 +1,142 @@ +/** + * Internal dependencies + */ +import { test as setup } from '../../utils'; +import { + shopSettings, + shippingZones, + taxSettings, + products, + coupons, + customers, + disableNoncePlugin, + subscriptionsPlugin, +} from '../../resources'; + +// setup( 'Setup WooCommerce plugin, API, go Live', async ( { requestUtils } ) => {} ); + +setup( 'Setup theme', + async ( { requestUtils } ) => { + const slug = 'storefront'; + if( ! await requestUtils.isThemeInstalled( slug ) ) { + await requestUtils.installTheme( slug ); + } + await requestUtils.activateTheme( slug ); + } +); + +setup( 'Setup Disable Nonce Plugin', + async ( { requestUtils, plugins } ) => { + if ( + ! ( await requestUtils.isPluginInstalled( + disableNoncePlugin.slug + ) ) + ) { + await plugins.installPluginFromFile( + disableNoncePlugin.zipFilePath + ); + } + await requestUtils.activatePlugin( disableNoncePlugin.slug ); + } +); + +setup( 'Setup WooCommerce Subscriptions Plugin (deactivated)', + async ( { requestUtils, plugins } ) => { + if ( + ! ( await requestUtils.isPluginInstalled( + subscriptionsPlugin.slug + ) ) + ) { + await plugins.installPluginFromFile( + subscriptionsPlugin.zipFilePath + ); + } + await requestUtils.deactivatePlugin( subscriptionsPlugin.slug ); + } +); + +setup( 'Setup Disable WooCommerce Setup Plugin', + async ( { requestUtils, plugins } ) => { + const helperPluginSlug = 'disable-wc-setup-wizard'; + if ( ! ( await requestUtils.isPluginInstalled( helperPluginSlug ) ) ) { + await plugins.installPluginFromFile( + `./resources/files/${ helperPluginSlug }.zip` + ); + } + await requestUtils.activatePlugin( helperPluginSlug ); + } +); + +setup( 'Setup Block and Classic pages', + async ( { wooCommerceUtils } ) => { + await wooCommerceUtils.publishBlockCartPage(); + await wooCommerceUtils.publishBlockCheckoutPage(); + await wooCommerceUtils.publishClassicCartPage(); + await wooCommerceUtils.publishClassicCheckoutPage(); + } +); + +setup( 'Setup WooCommerce general settings', async ( { wooCommerceApi } ) => { + const country = 'germany'; + await wooCommerceApi.updateGeneralSettings( + shopSettings[ country ].general + ); +} ); + +setup( 'Setup WooCommerce shipping', + async ( { wooCommerceUtils } ) => { + await wooCommerceUtils.configureShippingZone( shippingZones.worldwide ); + } +); + +setup( 'Setup WooCommerce taxes (included)', + async ( { wooCommerceUtils } ) => { + await wooCommerceUtils.setTaxes( taxSettings.including ); + } +); + +setup( 'Setup Registered Customer', + async ( { wooCommerceUtils } ) => { + const country = 'germany'; + await wooCommerceUtils.createCustomer( customers[ country ] ); + } +); + +setup( 'Setup Delete Previous Orders', + async ( { wooCommerceApi } ) => { + await wooCommerceApi.deleteAllOrders(); + } +); + +setup( 'Setup coupons', async ( { wooCommerceUtils } ) => { + // create test coupons + const couponItems = {}; + const couponEntries = Object.entries( coupons ); + await Promise.all( + couponEntries.map( async ( [ key, coupon ] ) => { + const createdCoupon = await wooCommerceUtils.createCoupon( coupon ); + couponItems[ coupon.code ] = { id: createdCoupon.id }; + } ) + ); + // store created coupons as CART_ITEMS env var + process.env.COUPONS = JSON.stringify( couponItems ); +} ); + +setup( 'Setup products', async ( { wooCommerceUtils } ) => { + // create test products + const cartItems = {}; + const productEntries = Object.entries( products ); + await Promise.all( + productEntries.map( async ( [ key, product ] ) => { + // check if not subscription product - requires Supscriptions plugin + if ( ! product.slug.includes( 'subscription' ) ) { + const createdProduct = await wooCommerceUtils.createProduct( + product + ); + cartItems[ product.slug ] = { id: createdProduct.id }; + } + } ) + ); + // store created products as CART_ITEMS env var + process.env.PRODUCTS = JSON.stringify( cartItems ); +} ); diff --git a/tests/qa/tests/01-plugin-foundation/plugin-foundation.spec.ts b/tests/qa/tests/01-plugin-foundation/plugin-foundation.spec.ts new file mode 100644 index 00000000..64a4fb2e --- /dev/null +++ b/tests/qa/tests/01-plugin-foundation/plugin-foundation.spec.ts @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import { + testPluginInstallationFromFile, + testPluginReinstallationFromFile, + testPluginInstallationFromMarketplace, + testPluginDeactivation, + testPluginRemoval, +} from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { test, expect } from '../../utils'; +import { molliePlugin, gateways } from '../../resources'; + +testPluginInstallationFromFile( 'C419986', molliePlugin ); + +testPluginInstallationFromMarketplace( 'C3317', molliePlugin ); + +testPluginReinstallationFromFile( 'C3322', molliePlugin ); + +testPluginDeactivation( 'C3319', molliePlugin ); + +testPluginRemoval( 'C3318', molliePlugin ); + +test.describe( 'Plugin foundation', () => { + test.beforeAll( async ( { utils } ) => { + await utils.installActivateMollie(); + } ); + + test( 'C419984 | Plugin foundation - Mollie gateways are present in WooCommerce payment methods', async ( { + wooCommerceSettings, + } ) => { + await wooCommerceSettings.visit( 'payments' ); + for ( const key in gateways ) { + const gateway = gateways[ key ]; + const mollieGatewayname = `Mollie - ${ gateway.name }`; + await expect + .soft( wooCommerceSettings.gatewayLink( mollieGatewayname ) ) + .toBeVisible(); + } + } ); +} ); diff --git a/tests/qa/tests/02-merchant-setup/merchant-setup.spec.ts b/tests/qa/tests/02-merchant-setup/merchant-setup.spec.ts new file mode 100644 index 00000000..1d61e41b --- /dev/null +++ b/tests/qa/tests/02-merchant-setup/merchant-setup.spec.ts @@ -0,0 +1,32 @@ +/** + * Internal dependencies + */ +import { expect, test } from '../../utils'; + +test.beforeAll( async ( { utils } ) => { + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +test( 'C3511 | Validate an error message is returned when the test key is not valid/empty', async ( { + mollieSettingsApiKeys, + mollieSettingsAdvanced, +} ) => { + await mollieSettingsAdvanced.visit(); + await mollieSettingsAdvanced.cleanDb(); + await mollieSettingsApiKeys.visit(); + await expect( + mollieSettingsApiKeys.failedToConnectToMollieApiText() + ).toBeVisible(); +} ); + +test( 'C3510 | Validate that test/live keys are valid', async ( { + mollieSettingsApiKeys, +} ) => { + await mollieSettingsApiKeys.visit(); + await mollieSettingsApiKeys.setApiKeys(); + await mollieSettingsApiKeys.saveChanges(); + await expect( + mollieSettingsApiKeys.successfullyConnectedWithTestApiText() + ).toBeVisible(); +} ); diff --git a/tests/qa/tests/03-plugin-settings/mollie-settings-advanced.spec.ts b/tests/qa/tests/03-plugin-settings/mollie-settings-advanced.spec.ts new file mode 100644 index 00000000..a9aee2d3 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/mollie-settings-advanced.spec.ts @@ -0,0 +1,64 @@ +/** + * Internal dependencies + */ +import { test, expect } from '../../utils'; + +test.beforeAll( async ( { utils } ) => { + await utils.configureStore( { classicPages: true } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +test( 'C420152 | Validate that Mollie Advanced section is displayed per UI design', async ( { + mollieSettingsAdvanced, +} ) => { + await mollieSettingsAdvanced.visit(); + await expect( mollieSettingsAdvanced.heading() ).toBeVisible(); + await expect( mollieSettingsAdvanced.debugLogCheckbox() ).toBeVisible(); + await expect( + mollieSettingsAdvanced.orderStatusCancelledPaymentSelect() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.paymentScreenLanguageSelect() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.storeCustomerDetailsAtMollieCheckbox() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.selectAPIMethodSelect() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionInput() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionButton( '{orderNumber}' ) + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionButton( '{storeName}' ) + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionButton( + '{customer.firstname}' + ) + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionButton( + '{customer.lastname}' + ) + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.apiPaymentDescriptionButton( + '{customer.company}' + ) + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.surchargeGatewayFeeLabelInput() + ).toBeVisible(); + await expect( + mollieSettingsAdvanced.removeMollieDataFromDatabaseOnUninstall() + ).toBeVisible(); + await expect( mollieSettingsAdvanced.clearNowLink() ).toBeVisible(); + await expect( + mollieSettingsAdvanced.placingPaymentsOnHoldSelect() + ).toBeVisible(); +} ); diff --git a/tests/qa/tests/03-plugin-settings/mollie-settings-api-keys.spec.ts b/tests/qa/tests/03-plugin-settings/mollie-settings-api-keys.spec.ts new file mode 100644 index 00000000..f89a26b2 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/mollie-settings-api-keys.spec.ts @@ -0,0 +1,63 @@ +/** + * Internal dependencies + */ +import { expect, test } from '../../utils'; + +test.beforeAll( async ( { utils } ) => { + await utils.installActivateMollie(); +} ); + +test( 'C420150 | Validate that Mollie API Keys section is displayed per UI design', async ( { + mollieSettingsApiKeys, +} ) => { + await mollieSettingsApiKeys.visit(); + await expect( mollieSettingsApiKeys.heading() ).toBeVisible(); + await expect( + mollieSettingsApiKeys.molliePaymentModeSelect() + ).toBeVisible(); + await expect( mollieSettingsApiKeys.liveApiKeyInput() ).toBeVisible(); + await expect( + mollieSettingsApiKeys.molliePaymentModeSelect() + ).toBeVisible(); + await expect( mollieSettingsApiKeys.testApiKeyInput() ).toBeVisible(); +} ); + +test( 'C3333 | Validate that the ecommerce admin have access to Documentation/Support through the Setting page', async ( { + mollieSettingsApiKeys, + request, + page, +} ) => { + await mollieSettingsApiKeys.visit(); + const contactMollieSupportButton = + mollieSettingsApiKeys.contactMollieSupportButton(); + const contactSupportHref = await contactMollieSupportButton.getAttribute( + 'href' + ); + await expect( contactSupportHref ).toEqual( + 'https://www.mollie.com/contact/merchants' + ); + await expect( await request.get( contactSupportHref ) ).toBeOK(); + + const molliePluginDocumentationButton = + mollieSettingsApiKeys.molliePluginDocumentationButton(); + const pluginDocumentationHref = + await molliePluginDocumentationButton.getAttribute( 'href' ); + await expect( pluginDocumentationHref ).toEqual( + 'https://help.mollie.com/hc/en-us/sections/12858723658130-Mollie-for-WooCommerce' + ); + await page.goto( pluginDocumentationHref ); + await expect( page ).toHaveURL( /molliehelp\.zendesk\.com\/auth/ ); +} ); + +test.fixme( + 'C3330 | Validate that the ecommerce admin can activate debug mode', + async ( { mollieSettingsApiKeys } ) => { + await mollieSettingsApiKeys.visit(); + await mollieSettingsApiKeys.molliePaymentModeSelect().uncheck(); + await expect( + mollieSettingsApiKeys.testApiKeyInput() + ).not.toBeVisible(); + await mollieSettingsApiKeys.molliePaymentModeSelect().check(); + await expect( mollieSettingsApiKeys.testApiKeyInput() ).toBeVisible(); + } +); diff --git a/tests/qa/tests/03-plugin-settings/mollie-settings-gateway.spec.ts b/tests/qa/tests/03-plugin-settings/mollie-settings-gateway.spec.ts new file mode 100644 index 00000000..d1b24104 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/mollie-settings-gateway.spec.ts @@ -0,0 +1,104 @@ +/** + * Internal dependencies + */ +import { annotateGateway, test, expect } from '../../utils'; +import { gateways, guests, products } from '../../resources'; + +test.beforeAll( async ( { utils } ) => { + await utils.configureStore( { classicPages: true } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +// for( let key in gateways ) { +const key = 'eps'; +const gateway = gateways[ key ]; + +test.describe( `Payment method settings "${ gateway.name }"`, () => { + test.beforeEach( async ( { mollieSettingsGateway } ) => { + await mollieSettingsGateway.visit(); + await mollieSettingsGateway.setup( gateway.settings ); + } ); + + test( + `C3325 | Validate that the ecommerce admin can change the "${ gateway.name }" payment name`, + annotateGateway( gateway.slug ), + async ( { utils, mollieSettingsGateway, classicCheckout } ) => { + await mollieSettingsGateway.setup( { + title: `${ gateway.name } edited`, + } ); + await mollieSettingsGateway.saveChanges(); + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + await classicCheckout.fillCheckoutForm( guests[ gateway.country ] ); + await expect( + await classicCheckout.paymentOption( + `${ gateway.name } edited` + ) + ).toBeVisible(); + } + ); + + test( + `C3326 | Validate that the ecommerce admin can change the "${ gateway.name }" payment logo`, + annotateGateway( gateway.slug ), + async ( { utils, mollieSettingsGateway, classicCheckout } ) => { + await mollieSettingsGateway.setup( { + enableCustomLogo: true, + customLogoPath: './resources/files/mollie-test-logo.png', + } ); + await mollieSettingsGateway.saveChanges(); + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + await classicCheckout.fillCheckoutForm( guests[ gateway.country ] ); + const paymentOptionLogoSrc = await classicCheckout + .paymentOptionLogo( `${ gateway.name }` ) + .getAttribute( 'src' ); + await expect( paymentOptionLogoSrc ).toContain( + `mollie-test-logo` + ); + } + ); + + test( + `C3327 | Validate that the ecommerce admin can change the "${ gateway.name }" payment description`, + annotateGateway( gateway.slug ), + async ( { utils, mollieSettingsGateway, classicCheckout } ) => { + await mollieSettingsGateway.setup( { + description: `${ gateway.name } edited description`, + } ); + await mollieSettingsGateway.saveChanges(); + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + await classicCheckout.fillCheckoutForm( guests[ gateway.country ] ); + await classicCheckout.paymentOption( gateway.name ).click(); + await expect( + await classicCheckout.page.getByText( + `${ gateway.name } edited description` + ) + ).toBeVisible(); + } + ); + + test( + `C420329 | Validate selling only to specific countries for "${ gateway.name }"`, + annotateGateway( gateway.slug ), + async ( { utils, mollieSettingsGateway, classicCheckout } ) => { + await mollieSettingsGateway.setup( { + sellToCountries: [ 'Spain' ], + } ); + await mollieSettingsGateway.saveChanges(); + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + await classicCheckout.fillCheckoutForm( guests[ gateway.country ] ); + await expect( + classicCheckout.paymentOption( gateway.name ) + ).not.toBeVisible(); + } + ); +} ); +// } diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-over-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-over-limit.ts new file mode 100644 index 00000000..2ece5d07 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-over-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixedAndPercentageOverLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed and percentage over limit', + title: 'Validate fixed and percentage fee surcharge for total over limit for', + expectedAmount: 111.0, + expectedFeeText: '+ € 10 + 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee_percentage', + fixed_fee: '10', + maximum_limit: '10', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420318', gateway: 'applepay' }, + { testId: 'C89355', gateway: 'creditcard' }, + { testId: 'C130905', gateway: 'giftcard' }, + { testId: 'C129822', gateway: 'voucher' }, + { testId: 'C129511', gateway: 'bancontact' }, + { testId: 'C138020', gateway: 'belfius' }, + { testId: 'C354673', gateway: 'billie' }, + { testId: 'C133667', gateway: 'eps' }, + { testId: 'C130865', gateway: 'ideal' }, + { testId: 'C133677', gateway: 'kbc' }, + { testId: 'C420328', gateway: 'mybank' }, + { testId: 'C130895', gateway: 'paypal' }, + { testId: 'C420140', gateway: 'paysafecard' }, + { testId: 'C129812', gateway: 'przelewy24' }, + { testId: 'C136538', gateway: 'banktransfer' }, + { testId: 'C106917', gateway: 'in3' }, + // { testId: 'C130885', gateway: 'klarnapaylater' }, + // { testId: 'C136528', gateway: 'klarnapaynow' }, + // { testId: 'C106918', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-under-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-under-limit.ts new file mode 100644 index 00000000..08021939 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage-under-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixedAndPercentageUnderLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed and percentage under limit', + title: 'Validate fixed and percentage fee surcharge for total under limit for', + expectedAmount: 134.21, + expectedFeeText: '+ € 10 + 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee_percentage', + fixed_fee: '10', + maximum_limit: '150', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420315', gateway: 'applepay' }, + // { testId: 'C000', gateway: 'creditcard' }, + { testId: 'C130902', gateway: 'giftcard' }, + { testId: 'C129819', gateway: 'voucher' }, + { testId: 'C129508', gateway: 'bancontact' }, + { testId: 'C138017', gateway: 'belfius' }, + { testId: 'C354670', gateway: 'billie' }, + { testId: 'C133664', gateway: 'eps' }, + { testId: 'C130862', gateway: 'ideal' }, + { testId: 'C133674', gateway: 'kbc' }, + { testId: 'C420325', gateway: 'mybank' }, + { testId: 'C130892', gateway: 'paypal' }, + { testId: 'C420137', gateway: 'paysafecard' }, + { testId: 'C129809', gateway: 'przelewy24' }, + { testId: 'C136535', gateway: 'banktransfer' }, + { testId: 'C106914', gateway: 'in3' }, + // { testId: 'C130882', gateway: 'klarnapaylater' }, + // { testId: 'C136525', gateway: 'klarnapaynow' }, + // { testId: 'C1278122', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage.ts new file mode 100644 index 00000000..6dd8cfaf --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-and-percentage.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixedAndPercentage: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed and percentage', + title: 'Validate fixed and percentage fee surcharge for', + expectedAmount: 134.21, + expectedFeeText: '+ € 10 + 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee_percentage', + fixed_fee: '10', + maximum_limit: '0', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420312', gateway: 'applepay' }, + { testId: 'C89352', gateway: 'creditcard' }, + { testId: 'C130899', gateway: 'giftcard' }, + { testId: 'C129816', gateway: 'voucher' }, + { testId: 'C129505', gateway: 'bancontact' }, + { testId: 'C138014', gateway: 'belfius' }, + { testId: 'C354667', gateway: 'billie' }, + { testId: 'C133661', gateway: 'eps' }, + { testId: 'C130859', gateway: 'ideal' }, + { testId: 'C133671', gateway: 'kbc' }, + { testId: 'C420322', gateway: 'mybank' }, + { testId: 'C130889', gateway: 'paypal' }, + { testId: 'C420134', gateway: 'paysafecard' }, + { testId: 'C129806', gateway: 'przelewy24' }, + { testId: 'C136532', gateway: 'banktransfer' }, + { testId: 'C106911', gateway: 'in3' }, + // { testId: 'C130876', gateway: 'klarnapaylater' }, + // { testId: 'C136522', gateway: 'klarnapaynow' }, + // { testId: 'C127819', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-over-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-over-limit.ts new file mode 100644 index 00000000..875cd956 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-over-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixedOverLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed over limit', + title: 'Validate fixed fee surcharge fo total over limit for', + expectedAmount: 111.0, + expectedFeeText: '+ € 10 fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee', + fixed_fee: '10', + maximum_limit: '10', + percentage: '0', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C354671', gateway: 'applepay' }, + { testId: 'C89353', gateway: 'creditcard' }, + { testId: 'C130903', gateway: 'giftcard' }, + { testId: 'C129820', gateway: 'voucher' }, + { testId: 'C129509', gateway: 'bancontact' }, + { testId: 'C138018', gateway: 'belfius' }, + { testId: 'C354671', gateway: 'billie' }, + { testId: 'C133665', gateway: 'eps' }, + { testId: 'C130863', gateway: 'ideal' }, + { testId: 'C133675', gateway: 'kbc' }, + { testId: 'C420326', gateway: 'mybank' }, + { testId: 'C130893', gateway: 'paypal' }, + { testId: 'C420138', gateway: 'paysafecard' }, + { testId: 'C129810', gateway: 'przelewy24' }, + { testId: 'C136536', gateway: 'banktransfer' }, + { testId: 'C106915', gateway: 'in3' }, + // { testId: 'C130883', gateway: 'klarnapaylater' }, + // { testId: 'C136526', gateway: 'klarnapaynow' }, + // { testId: 'C128597', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-under-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-under-limit.ts new file mode 100644 index 00000000..4ce9f7e6 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed-under-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixedUnderLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed under Limit', + title: 'Validate fixed fee surcharge fo total under limit for', + expectedAmount: 122.0, + expectedFeeText: '+ € 10 fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee', + fixed_fee: '10', + maximum_limit: '150', + percentage: '0', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420313', gateway: 'applepay' }, + { testId: 'C89354', gateway: 'creditcard' }, + { testId: 'C130900', gateway: 'giftcard' }, + { testId: 'C129817', gateway: 'voucher' }, + { testId: 'C129506', gateway: 'bancontact' }, + { testId: 'C138015', gateway: 'belfius' }, + { testId: 'C354668', gateway: 'billie' }, + { testId: 'C133662', gateway: 'eps' }, + { testId: 'C130860', gateway: 'ideal' }, + { testId: 'C133672', gateway: 'kbc' }, + { testId: 'C420323', gateway: 'mybank' }, + { testId: 'C130890', gateway: 'paypal' }, + { testId: 'C420135', gateway: 'paysafecard' }, + { testId: 'C129807', gateway: 'przelewy24' }, + { testId: 'C136533', gateway: 'banktransfer' }, + { testId: 'C106912', gateway: 'in3' }, + // { testId: 'C130880', gateway: 'klarnapaylater' }, + // { testId: 'C136523', gateway: 'klarnapaynow' }, + // { testId: 'C1278120', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed.ts new file mode 100644 index 00000000..11db2824 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-fixed.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeFixed: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Fixed', + title: 'Validate fixed fee surcharge for', + expectedAmount: 122.0, + expectedFeeText: '+ € 10 fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'fixed_fee', + fixed_fee: '10', + maximum_limit: '0', + percentage: '0', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420310', gateway: 'applepay' }, + { testId: 'C94865', gateway: 'creditcard' }, + { testId: 'C130897', gateway: 'giftcard' }, + { testId: 'C129814', gateway: 'voucher' }, + { testId: 'C129503', gateway: 'bancontact' }, + { testId: 'C138012', gateway: 'belfius' }, + { testId: 'C354665', gateway: 'billie' }, + { testId: 'C133659', gateway: 'eps' }, + { testId: 'C130857', gateway: 'ideal' }, + { testId: 'C133669', gateway: 'kbc' }, + { testId: 'C420320', gateway: 'mybank' }, + { testId: 'C130887', gateway: 'paypal' }, + { testId: 'C420132', gateway: 'paysafecard' }, + { testId: 'C129804', gateway: 'przelewy24' }, + { testId: 'C136530', gateway: 'banktransfer' }, + { testId: 'C106909', gateway: 'in3' }, + // { testId: 'C130873', gateway: 'klarnapaylater' }, + // { testId: 'C136520', gateway: 'klarnapaynow' }, + // { testId: 'C127817', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-over-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-over-limit.ts new file mode 100644 index 00000000..923b4d84 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-over-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargePercentageOverLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Percentage over limit', + title: 'Validate percentage fee surcharge for total over limit for', + expectedAmount: 111.0, + expectedFeeText: '+ 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'percentage', + fixed_fee: '0', + maximum_limit: '10', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420317', gateway: 'applepay' }, + { testId: 'C89356', gateway: 'creditcard' }, + { testId: 'C130904', gateway: 'giftcard' }, + { testId: 'C129821', gateway: 'voucher' }, + { testId: 'C129510', gateway: 'bancontact' }, + { testId: 'C138019', gateway: 'belfius' }, + { testId: 'C354672', gateway: 'billie' }, + { testId: 'C133666', gateway: 'eps' }, + { testId: 'C130864', gateway: 'ideal' }, + { testId: 'C133676', gateway: 'kbc' }, + { testId: 'C420327', gateway: 'mybank' }, + { testId: 'C130894', gateway: 'paypal' }, + { testId: 'C420139', gateway: 'paysafecard' }, + { testId: 'C129811', gateway: 'przelewy24' }, + { testId: 'C136537', gateway: 'banktransfer' }, + { testId: 'C106916', gateway: 'in3' }, + // { testId: 'C130884', gateway: 'klarnapaylater' }, + // { testId: 'C136527', gateway: 'klarnapaynow' }, + // { testId: 'C129200', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-under-limit.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-under-limit.ts new file mode 100644 index 00000000..bd2f180b --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage-under-limit.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargePercentageUnderLimit: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Percentage under limit', + title: 'Validate percentage fee surcharge for total under limit for', + expectedAmount: 123.21, + expectedFeeText: '+ 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'percentage', + fixed_fee: '0', + maximum_limit: '150', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420314', gateway: 'applepay' }, + // { testId: 'C000', gateway: 'creditcard' }, + { testId: 'C130901', gateway: 'giftcard' }, + { testId: 'C129818', gateway: 'voucher' }, + { testId: 'C129507', gateway: 'bancontact' }, + { testId: 'C138016', gateway: 'belfius' }, + { testId: 'C354669', gateway: 'billie' }, + { testId: 'C133663', gateway: 'eps' }, + { testId: 'C130861', gateway: 'ideal' }, + { testId: 'C133673', gateway: 'kbc' }, + { testId: 'C420324', gateway: 'mybank' }, + { testId: 'C130891', gateway: 'paypal' }, + { testId: 'C420136', gateway: 'paysafecard' }, + { testId: 'C129808', gateway: 'przelewy24' }, + { testId: 'C136534', gateway: 'banktransfer' }, + { testId: 'C106913', gateway: 'in3' }, + // { testId: 'C130881', gateway: 'klarnapaylater' }, + // { testId: 'C136524', gateway: 'klarnapaynow' }, + // { testId: 'C1278121', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage.ts new file mode 100644 index 00000000..71fa0927 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-fee-percentage.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargePercentage: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - Percentage', + title: 'Validate percentage fee surcharge for', + expectedAmount: 123.21, + expectedFeeText: '+ 10% fee might apply (excl. VAT)', + settings: { + payment_surcharge: 'percentage', + fixed_fee: '0', + maximum_limit: '0', + percentage: '10', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420311', gateway: 'applepay' }, + { testId: 'C89351', gateway: 'creditcard' }, + { testId: 'C130898', gateway: 'giftcard' }, + { testId: 'C129815', gateway: 'voucher' }, + { testId: 'C129504', gateway: 'bancontact' }, + { testId: 'C138013', gateway: 'belfius' }, + { testId: 'C354666', gateway: 'billie' }, + { testId: 'C133660', gateway: 'eps' }, + { testId: 'C130858', gateway: 'ideal' }, + { testId: 'C133670', gateway: 'kbc' }, + { testId: 'C420321', gateway: 'mybank' }, + { testId: 'C130888', gateway: 'paypal' }, + { testId: 'C420133', gateway: 'paysafecard' }, + { testId: 'C129805', gateway: 'przelewy24' }, + { testId: 'C136531', gateway: 'banktransfer' }, + { testId: 'C106910', gateway: 'in3' }, + // { testId: 'C130875', gateway: 'klarnapaylater' }, + // { testId: 'C136521', gateway: 'klarnapaynow' }, + // { testId: 'C127818', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-no-fee.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-no-fee.ts new file mode 100644 index 00000000..51407122 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/data-surcharge-no-fee.ts @@ -0,0 +1,46 @@ +/** + * Internal dependencies + */ +import { MollieSettings } from '../../../../resources'; + +export const surchargeNoFee: { + describe: string; + title: string; + expectedAmount: number; + expectedFeeText: string; + settings: MollieSettings.Gateway; + tests: { testId: string; gateway: string }[]; +} = { + describe: 'Surcharge fee - No fee', + title: 'Validate no fee surcharge for', + expectedAmount: 111.0, + expectedFeeText: '', + settings: { + payment_surcharge: 'no_fee', + fixed_fee: '0', + maximum_limit: '0', + percentage: '0', + surcharge_limit: '0', + }, + tests: [ + // { testId: 'C420309', gateway: 'applepay' }, + // { testId: 'C000', gateway: 'creditcard' }, + { testId: 'C130896', gateway: 'giftcard' }, + { testId: 'C129813', gateway: 'voucher' }, + { testId: 'C129502', gateway: 'bancontact' }, + { testId: 'C138011', gateway: 'belfius' }, + { testId: 'C354664', gateway: 'billie' }, + { testId: 'C133658', gateway: 'eps' }, + { testId: 'C130856', gateway: 'ideal' }, + { testId: 'C133668', gateway: 'kbc' }, + { testId: 'C420319', gateway: 'mybank' }, + { testId: 'C130886', gateway: 'paypal' }, + { testId: 'C420131', gateway: 'paysafecard' }, + { testId: 'C129803', gateway: 'przelewy24' }, + { testId: 'C136529', gateway: 'banktransfer' }, + { testId: 'C106908', gateway: 'in3' }, + // { testId: 'C130871', gateway: 'klarnapaylater' }, + // { testId: 'C136519', gateway: 'klarnapaynow' }, + // { testId: 'C127227', gateway: 'klarnasliceit' }, + ], +}; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/.test-data/index.ts b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/index.ts new file mode 100644 index 00000000..80d06ddb --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/.test-data/index.ts @@ -0,0 +1,13 @@ +export * from './data-surcharge-no-fee'; + +export * from './data-surcharge-fee-fixed'; +export * from './data-surcharge-fee-fixed-under-limit'; +export * from './data-surcharge-fee-fixed-over-limit'; + +export * from './data-surcharge-fee-percentage'; +export * from './data-surcharge-fee-percentage-under-limit'; +export * from './data-surcharge-fee-percentage-over-limit'; + +export * from './data-surcharge-fee-fixed-and-percentage'; +export * from './data-surcharge-fee-fixed-and-percentage-under-limit'; +export * from './data-surcharge-fee-fixed-and-percentage-over-limit'; diff --git a/tests/qa/tests/03-plugin-settings/surcharge/surcharge.spec.ts b/tests/qa/tests/03-plugin-settings/surcharge/surcharge.spec.ts new file mode 100644 index 00000000..62db6836 --- /dev/null +++ b/tests/qa/tests/03-plugin-settings/surcharge/surcharge.spec.ts @@ -0,0 +1,80 @@ +/** + * Internal dependencies + */ +import { test, expect } from '../../../utils'; +import { + surchargeNoFee, + surchargeFixed, + surchargeFixedUnderLimit, + surchargeFixedOverLimit, + surchargePercentage, + surchargePercentageUnderLimit, + surchargePercentageOverLimit, + surchargeFixedAndPercentage, + surchargeFixedAndPercentageUnderLimit, + surchargeFixedAndPercentageOverLimit, +} from './.test-data'; +import { gateways, products, guests, flatRate } from '../../../resources'; + +const allTests = [ + surchargeNoFee, + surchargeFixed, + surchargeFixedUnderLimit, + surchargeFixedOverLimit, + surchargePercentage, + surchargePercentageUnderLimit, + surchargePercentageOverLimit, + surchargeFixedAndPercentage, + surchargeFixedAndPercentageUnderLimit, + surchargeFixedAndPercentageOverLimit, +]; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + await utils.configureStore( { classicPages: true } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const surcharge of allTests ) { + test.describe( surcharge.describe, () => { + for ( const tested of surcharge.tests ) { + const gateway = gateways[ tested.gateway ]; + const country = gateway.country; + + test( `${ tested.testId } | ${ surcharge.title } "${ gateway.name } "`, async ( { + mollieApi, + utils, + classicCheckout, + } ) => { + await mollieApi.updateMollieGateway( + gateway.slug, + surcharge.settings + ); + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + await classicCheckout.fillCheckoutForm( guests[ country ] ); + await classicCheckout.selectShippingMethod( + flatRate.settings.title + ); + await classicCheckout.paymentOption( gateway.name ).click(); + await classicCheckout.page.waitForTimeout( 2000 ); // timeout for progress spinner (can't catch the element) + const feeNotice = classicCheckout.paymentOptionFee( + gateway.name + ); + if ( surcharge.expectedFeeText ) { + await expect( feeNotice ).toContainText( + surcharge.expectedFeeText + ); + } else { + await expect( feeNotice ).not.toBeVisible(); + } + const totalAmount = await classicCheckout.captureTotalAmount(); + await expect( totalAmount ).toEqual( surcharge.expectedAmount ); + } ); + } + } ); +} diff --git a/tests/qa/tests/04-frontend-ui/frontend-ui.spec.ts b/tests/qa/tests/04-frontend-ui/frontend-ui.spec.ts new file mode 100644 index 00000000..bc5d8b90 --- /dev/null +++ b/tests/qa/tests/04-frontend-ui/frontend-ui.spec.ts @@ -0,0 +1,56 @@ +/** + * Internal dependencies + */ +import { test, expect } from '../../utils'; +import { + gateways, + guests, + MollieGateway, + products, + shopSettings, +} from '../../resources'; + +test.beforeAll( async ( { utils } ) => { + await utils.configureStore( { classicPages: true } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +test( 'C420154 | Validate correct gateways shown with Order API on Classic checkout', async ( { + utils, + classicCheckout, + wooCommerceApi, +} ) => { + test.setTimeout( 600000 ); + const excludedPaymentMethods = [ 'applepay', 'directdebit' ]; + let gateway: MollieGateway; + let guest: WooCommerce.CreateCustomer; + let countryCode: string; + + await utils.fillVisitorsCart( [ products.mollieSimple100 ] ); + await classicCheckout.visit(); + + for ( const key in gateways ) { + gateway = gateways[ key ]; + guest = guests[ gateway.country ]; + countryCode = guest.billing.country; + + if ( excludedPaymentMethods.includes( gateway.slug ) ) continue; + + await wooCommerceApi.updateGeneralSettings( { + woocommerce_currency: gateway.currency || 'EUR', + } ); + await classicCheckout.page.reload(); + await classicCheckout.billingCountryCombobox().click(); + await classicCheckout.billingCountryOptionByCode( countryCode ).click(); + await classicCheckout.page.waitForTimeout( 1000 ); + + await expect + .soft( await classicCheckout.paymentOption( gateway.name ) ) + .toBeVisible(); + } +} ); + +test.afterAll( async ( { wooCommerceApi } ) => { + await wooCommerceApi.updateGeneralSettings( shopSettings.germany.general ); +} ); diff --git a/tests/qa/tests/05-transaction/.test-data/data-conversion.ts b/tests/qa/tests/05-transaction/.test-data/data-conversion.ts new file mode 100644 index 00000000..2aaa52e5 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/data-conversion.ts @@ -0,0 +1,31 @@ +/** + * Internal dependencies + */ +import { + MollieTestData, + gateways, + guests, + orders, + products, +} from '../../../resources'; + +export const createShopOrder = ( + testData: MollieTestData.PaymentStatus +): WooCommerce.ShopOrder => { + const gateway = gateways[ testData.gatewaySlug ]; + const order: WooCommerce.ShopOrder = { + ...orders.default, + products: [ products.mollieSimple100 ], + payment: { + gateway, + billingCompany: testData.billingCompany, + card: testData.card, + bankIssuer: testData.bankIssuer, + status: testData.paymentStatus, + }, + orderStatus: testData.orderStatus, + customer: guests[ gateway.country ], + currency: gateway.currency, + }; + return order; +}; diff --git a/tests/qa/tests/05-transaction/.test-data/eur-data-checkout-classic.ts b/tests/qa/tests/05-transaction/.test-data/eur-data-checkout-classic.ts new file mode 100644 index 00000000..e3f9ec69 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/eur-data-checkout-classic.ts @@ -0,0 +1,612 @@ +/** + * Internal dependencies + */ +import { cards, MollieTestData } from '../../../resources'; + +export const paymentStatusCheckoutClassicEur: MollieTestData.PaymentStatus[] = [ + // { + // testId: '', + // gatewaySlug: 'applepay', + // paymentStatus: 'paid', + // orderStatus: 'processing', + // }, + { + testId: 'C3731', + gatewaySlug: 'in3', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3732', + gatewaySlug: 'in3', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3733', + gatewaySlug: 'in3', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3734', + gatewaySlug: 'in3', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3387', + gatewaySlug: 'bancontact', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3388', + gatewaySlug: 'bancontact', + paymentStatus: 'open', + orderStatus: 'pending', + }, + { + testId: 'C3389', + gatewaySlug: 'bancontact', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3390', + gatewaySlug: 'bancontact', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3391', + gatewaySlug: 'bancontact', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3424', + gatewaySlug: 'przelewy24', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3425', + gatewaySlug: 'przelewy24', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3426', + gatewaySlug: 'przelewy24', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3427', + gatewaySlug: 'przelewy24', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'voucher', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C3382', + gatewaySlug: 'ideal', + paymentStatus: 'paid', + bankIssuer: 'ING', + orderStatus: 'processing', + }, + { + testId: 'C3383', + gatewaySlug: 'ideal', + paymentStatus: 'open', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C3384', + gatewaySlug: 'ideal', + paymentStatus: 'failed', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C3385', + gatewaySlug: 'ideal', + paymentStatus: 'expired', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C3386', + gatewaySlug: 'ideal', + paymentStatus: 'canceled', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C3392', + gatewaySlug: 'paypal', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3393', + gatewaySlug: 'paypal', + paymentStatus: 'pending', + orderStatus: 'pending', + }, + { + testId: 'C3394', + gatewaySlug: 'paypal', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3395', + gatewaySlug: 'paypal', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3396', + gatewaySlug: 'paypal', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'giftcard', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C3412', + gatewaySlug: 'eps', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3413', + gatewaySlug: 'eps', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3414', + gatewaySlug: 'eps', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3415', + gatewaySlug: 'eps', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3419', + gatewaySlug: 'kbc', + paymentStatus: 'paid', + bankIssuer: 'KBC', + orderStatus: 'processing', + }, + { + testId: 'C3416', + gatewaySlug: 'kbc', + paymentStatus: 'failed', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C3417', + gatewaySlug: 'kbc', + paymentStatus: 'canceled', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C3418', + gatewaySlug: 'kbc', + paymentStatus: 'expired', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C3371', + gatewaySlug: 'creditcard', + paymentStatus: 'paid', + card: cards.visa, + orderStatus: 'processing', + }, + { + testId: 'C3372', + gatewaySlug: 'creditcard', + paymentStatus: 'open', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C3373', + gatewaySlug: 'creditcard', + paymentStatus: 'failed', + card: cards.visa, + orderStatus: 'pending', + }, + // { + // testId: 'C3375', + // gatewaySlug: 'creditcard', + // paymentStatus: 'canceled', + // card: cards.visa, + // orderStatus: 'pending', + // }, + { + testId: 'C3374', + gatewaySlug: 'creditcard', + paymentStatus: 'expired', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C3433', + gatewaySlug: 'banktransfer', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3432', + gatewaySlug: 'banktransfer', + paymentStatus: 'open', + orderStatus: 'on-hold', + }, + { + testId: 'C3434', + gatewaySlug: 'banktransfer', + paymentStatus: 'expired', + orderStatus: 'on-hold', + }, + { + testId: 'C420294', + gatewaySlug: 'mybank', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420295', + gatewaySlug: 'mybank', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420296', + gatewaySlug: 'mybank', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420297', + gatewaySlug: 'mybank', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3428', + gatewaySlug: 'belfius', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3429', + gatewaySlug: 'belfius', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3430', + gatewaySlug: 'belfius', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3431', + gatewaySlug: 'belfius', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C354674', + gatewaySlug: 'billie', + paymentStatus: 'authorized', + orderStatus: 'processing', + billingCompany: 'Syde', + }, + { + testId: 'C354675', + gatewaySlug: 'billie', + paymentStatus: 'failed', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C354676', + gatewaySlug: 'billie', + paymentStatus: 'canceled', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C354677', + gatewaySlug: 'billie', + paymentStatus: 'expired', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420141', + gatewaySlug: 'paysafecard', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420142', + gatewaySlug: 'paysafecard', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420143', + gatewaySlug: 'paysafecard', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007255', + gatewaySlug: 'klarna', + paymentStatus: 'authorized', + orderStatus: 'processing', + }, + { + testId: 'C3007256', + gatewaySlug: 'klarna', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007257', + gatewaySlug: 'klarna', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007258', + gatewaySlug: 'klarna', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007267', + gatewaySlug: 'bancomatpay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007268', + gatewaySlug: 'bancomatpay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007269', + gatewaySlug: 'bancomatpay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007270', + gatewaySlug: 'bancomatpay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3241639', + gatewaySlug: 'alma', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3241640', + gatewaySlug: 'alma', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3241641', + gatewaySlug: 'alma', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3241642', + gatewaySlug: 'alma', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3437842', + gatewaySlug: 'trustly', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3437843', + gatewaySlug: 'trustly', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3437844', + gatewaySlug: 'trustly', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3437845', + gatewaySlug: 'trustly', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622413', + gatewaySlug: 'riverty', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622414', + gatewaySlug: 'riverty', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622415', + gatewaySlug: 'riverty', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622416', + gatewaySlug: 'riverty', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622425', + gatewaySlug: 'payconiq', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622426', + gatewaySlug: 'payconiq', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622427', + gatewaySlug: 'payconiq', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622428', + gatewaySlug: 'payconiq', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3757251', + gatewaySlug: 'satispay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3757252', + gatewaySlug: 'satispay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3757253', + gatewaySlug: 'satispay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3757254', + gatewaySlug: 'satispay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + + /** + * Deprecated gateways + */ + + // { + // testId: 'C3401', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C3402', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3403', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3404', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3397', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C3398', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3399', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3400', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3408', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C3409', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3410', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C3411', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, +]; diff --git a/tests/qa/tests/05-transaction/.test-data/eur-data-checkout.ts b/tests/qa/tests/05-transaction/.test-data/eur-data-checkout.ts new file mode 100644 index 00000000..2172fc9d --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/eur-data-checkout.ts @@ -0,0 +1,612 @@ +/** + * Internal dependencies + */ +import { cards, MollieTestData } from '../../../resources'; + +export const paymentStatusCheckoutEur: MollieTestData.PaymentStatus[] = [ + // { + // testId: '', + // gatewaySlug: 'applepay', + // paymentStatus: 'paid', + // orderStatus: 'processing', + // }, + { + testId: 'C420219', + gatewaySlug: 'in3', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420220', + gatewaySlug: 'in3', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420221', + gatewaySlug: 'in3', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420222', + gatewaySlug: 'in3', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420230', + gatewaySlug: 'bancontact', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420231', + gatewaySlug: 'bancontact', + paymentStatus: 'open', + orderStatus: 'pending', + }, + { + testId: 'C420232', + gatewaySlug: 'bancontact', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420233', + gatewaySlug: 'bancontact', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420234', + gatewaySlug: 'bancontact', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420235', + gatewaySlug: 'przelewy24', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420236', + gatewaySlug: 'przelewy24', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420237', + gatewaySlug: 'przelewy24', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420238', + gatewaySlug: 'przelewy24', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'voucher', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C420244', + gatewaySlug: 'ideal', + paymentStatus: 'paid', + bankIssuer: 'ING', + orderStatus: 'processing', + }, + { + testId: 'C420245', + gatewaySlug: 'ideal', + paymentStatus: 'open', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420246', + gatewaySlug: 'ideal', + paymentStatus: 'failed', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420248', + gatewaySlug: 'ideal', + paymentStatus: 'canceled', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420247', + gatewaySlug: 'ideal', + paymentStatus: 'expired', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420253', + gatewaySlug: 'paypal', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420254', + gatewaySlug: 'paypal', + paymentStatus: 'pending', + orderStatus: 'pending', + }, + { + testId: 'C420255', + gatewaySlug: 'paypal', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420256', + gatewaySlug: 'paypal', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420257', + gatewaySlug: 'paypal', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'giftcard', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C420260', + gatewaySlug: 'eps', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420261', + gatewaySlug: 'eps', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420262', + gatewaySlug: 'eps', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420263', + gatewaySlug: 'eps', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420267', + gatewaySlug: 'kbc', + paymentStatus: 'paid', + bankIssuer: 'KBC', + orderStatus: 'processing', + }, + { + testId: 'C420264', + gatewaySlug: 'kbc', + paymentStatus: 'failed', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420265', + gatewaySlug: 'kbc', + paymentStatus: 'canceled', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420266', + gatewaySlug: 'kbc', + paymentStatus: 'expired', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420268', + gatewaySlug: 'creditcard', + paymentStatus: 'paid', + card: cards.visa, + orderStatus: 'processing', + }, + { + testId: 'C420269', + gatewaySlug: 'creditcard', + paymentStatus: 'open', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C420270', + gatewaySlug: 'creditcard', + paymentStatus: 'failed', + card: cards.visa, + orderStatus: 'pending', + }, + // { + // testId: 'C420272', + // gatewaySlug: 'creditcard', + // paymentStatus: 'canceled', + // card: cards.visa, + // orderStatus: 'pending', + // }, + { + testId: 'C420271', + gatewaySlug: 'creditcard', + paymentStatus: 'expired', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C420284', + gatewaySlug: 'banktransfer', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420283', + gatewaySlug: 'banktransfer', + paymentStatus: 'open', + orderStatus: 'on-hold', + }, + { + testId: 'C420285', + gatewaySlug: 'banktransfer', + paymentStatus: 'expired', + orderStatus: 'on-hold', + }, + { + testId: 'C420286', + gatewaySlug: 'mybank', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420287', + gatewaySlug: 'mybank', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420288', + gatewaySlug: 'mybank', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420289', + gatewaySlug: 'mybank', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420298', + gatewaySlug: 'belfius', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420299', + gatewaySlug: 'belfius', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420300', + gatewaySlug: 'belfius', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420301', + gatewaySlug: 'belfius', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420302', + gatewaySlug: 'billie', + paymentStatus: 'authorized', + orderStatus: 'processing', + billingCompany: 'Syde', + }, + { + testId: 'C420303', + gatewaySlug: 'billie', + paymentStatus: 'failed', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420304', + gatewaySlug: 'billie', + paymentStatus: 'canceled', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420305', + gatewaySlug: 'billie', + paymentStatus: 'expired', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420306', + gatewaySlug: 'paysafecard', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420307', + gatewaySlug: 'paysafecard', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420308', + gatewaySlug: 'paysafecard', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007259', + gatewaySlug: 'klarna', + paymentStatus: 'authorized', + orderStatus: 'processing', + }, + { + testId: 'C3007260', + gatewaySlug: 'klarna', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007261', + gatewaySlug: 'klarna', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007262', + gatewaySlug: 'klarna', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007263', + gatewaySlug: 'bancomatpay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007264', + gatewaySlug: 'bancomatpay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007265', + gatewaySlug: 'bancomatpay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007266', + gatewaySlug: 'bancomatpay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3241643', + gatewaySlug: 'alma', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3241644', + gatewaySlug: 'alma', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3241645', + gatewaySlug: 'alma', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3241646', + gatewaySlug: 'alma', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3437846', + gatewaySlug: 'trustly', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3437847', + gatewaySlug: 'trustly', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3437848', + gatewaySlug: 'trustly', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3437849', + gatewaySlug: 'trustly', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622417', + gatewaySlug: 'riverty', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622418', + gatewaySlug: 'riverty', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622419', + gatewaySlug: 'riverty', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622420', + gatewaySlug: 'riverty', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622429', + gatewaySlug: 'payconiq', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622430', + gatewaySlug: 'payconiq', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622431', + gatewaySlug: 'payconiq', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622432', + gatewaySlug: 'payconiq', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3757247', + gatewaySlug: 'satispay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3757248', + gatewaySlug: 'satispay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3757249', + gatewaySlug: 'satispay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3757250', + gatewaySlug: 'satispay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + + /** + * Deprecated gateways + */ + + // { + // testId: 'C420249', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420250', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420251', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420252', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420279', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420280', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420281', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420282', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420223', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420224', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420225', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420226', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, +]; diff --git a/tests/qa/tests/05-transaction/.test-data/eur-data-pay-for-order.ts b/tests/qa/tests/05-transaction/.test-data/eur-data-pay-for-order.ts new file mode 100644 index 00000000..13aa38a4 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/eur-data-pay-for-order.ts @@ -0,0 +1,612 @@ +/** + * Internal dependencies + */ +import { cards, MollieTestData } from '../../../resources'; + +export const paymentStatusPayForOrderEur: MollieTestData.PaymentStatus[] = [ + // { + // testId: '', + // gatewaySlug: 'applepay', + // paymentStatus: 'paid', + // orderStatus: 'processing', + // }, + { + testId: 'C420334', + gatewaySlug: 'in3', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420335', + gatewaySlug: 'in3', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420336', + gatewaySlug: 'in3', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420337', + gatewaySlug: 'in3', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420345', + gatewaySlug: 'bancontact', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420346', + gatewaySlug: 'bancontact', + paymentStatus: 'open', + orderStatus: 'pending', + }, + { + testId: 'C420347', + gatewaySlug: 'bancontact', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420348', + gatewaySlug: 'bancontact', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420349', + gatewaySlug: 'bancontact', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420350', + gatewaySlug: 'przelewy24', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420351', + gatewaySlug: 'przelewy24', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420352', + gatewaySlug: 'przelewy24', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420353', + gatewaySlug: 'przelewy24', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'voucher', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C420359', + gatewaySlug: 'ideal', + paymentStatus: 'paid', + bankIssuer: 'ING', + orderStatus: 'processing', + }, + { + testId: 'C420360', + gatewaySlug: 'ideal', + paymentStatus: 'open', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420361', + gatewaySlug: 'ideal', + paymentStatus: 'failed', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420363', + gatewaySlug: 'ideal', + paymentStatus: 'canceled', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420362', + gatewaySlug: 'ideal', + paymentStatus: 'expired', + bankIssuer: 'ING', + orderStatus: 'pending', + }, + { + testId: 'C420368', + gatewaySlug: 'paypal', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420369', + gatewaySlug: 'paypal', + paymentStatus: 'pending', + orderStatus: 'pending', + }, + { + testId: 'C420370', + gatewaySlug: 'paypal', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420371', + gatewaySlug: 'paypal', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420372', + gatewaySlug: 'paypal', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + // { + // testId: '', + // gatewaySlug: 'giftcard', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + { + testId: 'C420375', + gatewaySlug: 'eps', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420376', + gatewaySlug: 'eps', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420377', + gatewaySlug: 'eps', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420378', + gatewaySlug: 'eps', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420379', + gatewaySlug: 'kbc', + paymentStatus: 'paid', + bankIssuer: 'KBC', + orderStatus: 'processing', + }, + { + testId: 'C420380', + gatewaySlug: 'kbc', + paymentStatus: 'failed', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420381', + gatewaySlug: 'kbc', + paymentStatus: 'canceled', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420382', + gatewaySlug: 'kbc', + paymentStatus: 'expired', + bankIssuer: 'KBC', + orderStatus: 'pending', + }, + { + testId: 'C420383', + gatewaySlug: 'creditcard', + paymentStatus: 'paid', + card: cards.visa, + orderStatus: 'processing', + }, + { + testId: 'C420384', + gatewaySlug: 'creditcard', + paymentStatus: 'open', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C420385', + gatewaySlug: 'creditcard', + paymentStatus: 'failed', + card: cards.visa, + orderStatus: 'pending', + }, + // { + // testId: 'C420387', + // gatewaySlug: 'creditcard', + // paymentStatus: 'canceled', + // card: cards.visa, + // orderStatus: 'pending', + // }, + { + testId: 'C420386', + gatewaySlug: 'creditcard', + paymentStatus: 'expired', + card: cards.visa, + orderStatus: 'pending', + }, + { + testId: 'C420399', + gatewaySlug: 'banktransfer', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420398', + gatewaySlug: 'banktransfer', + paymentStatus: 'open', + orderStatus: 'on-hold', + }, + { + testId: 'C420400', + gatewaySlug: 'banktransfer', + paymentStatus: 'expired', + orderStatus: 'on-hold', + }, + { + testId: 'C420401', + gatewaySlug: 'mybank', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420402', + gatewaySlug: 'mybank', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420403', + gatewaySlug: 'mybank', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420404', + gatewaySlug: 'mybank', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420409', + gatewaySlug: 'belfius', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420410', + gatewaySlug: 'belfius', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C420411', + gatewaySlug: 'belfius', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420412', + gatewaySlug: 'belfius', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C420413', + gatewaySlug: 'billie', + paymentStatus: 'authorized', + orderStatus: 'processing', + billingCompany: 'Syde', + }, + { + testId: 'C420414', + gatewaySlug: 'billie', + paymentStatus: 'failed', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420415', + gatewaySlug: 'billie', + paymentStatus: 'canceled', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420416', + gatewaySlug: 'billie', + paymentStatus: 'expired', + orderStatus: 'pending', + billingCompany: 'Syde', + }, + { + testId: 'C420417', + gatewaySlug: 'paysafecard', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C420418', + gatewaySlug: 'paysafecard', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C420419', + gatewaySlug: 'paysafecard', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007283', + gatewaySlug: 'klarna', + paymentStatus: 'authorized', + orderStatus: 'processing', + }, + { + testId: 'C3007284', + gatewaySlug: 'klarna', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007285', + gatewaySlug: 'klarna', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007286', + gatewaySlug: 'klarna', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007291', + gatewaySlug: 'bancomatpay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007292', + gatewaySlug: 'bancomatpay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007293', + gatewaySlug: 'bancomatpay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007294', + gatewaySlug: 'bancomatpay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3241647', + gatewaySlug: 'alma', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3241648', + gatewaySlug: 'alma', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3241649', + gatewaySlug: 'alma', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3241650', + gatewaySlug: 'alma', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3437850', + gatewaySlug: 'trustly', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3437851', + gatewaySlug: 'trustly', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3437852', + gatewaySlug: 'trustly', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3437853', + gatewaySlug: 'trustly', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622421', + gatewaySlug: 'riverty', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622422', + gatewaySlug: 'riverty', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622423', + gatewaySlug: 'riverty', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622424', + gatewaySlug: 'riverty', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3622433', + gatewaySlug: 'payconiq', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3622434', + gatewaySlug: 'payconiq', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3622435', + gatewaySlug: 'payconiq', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3622436', + gatewaySlug: 'payconiq', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3757243', + gatewaySlug: 'satispay', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3757244', + gatewaySlug: 'satispay', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3757245', + gatewaySlug: 'satispay', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3757246', + gatewaySlug: 'satispay', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + + /** + * Deprecated gateways + */ + + // { + // testId: 'C420364', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420365', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420366', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420367', + // gatewaySlug: 'klarnapaylater', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420394', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420395', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420396', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420397', + // gatewaySlug: 'klarnapaynow', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420338', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'authorized', + // orderStatus: 'processing', + // }, + // { + // testId: 'C420339', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'failed', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420340', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'canceled', + // orderStatus: 'pending', + // }, + // { + // testId: 'C420341', + // gatewaySlug: 'klarnasliceit', + // paymentStatus: 'expired', + // orderStatus: 'pending', + // }, +]; diff --git a/tests/qa/tests/05-transaction/.test-data/index.ts b/tests/qa/tests/05-transaction/.test-data/index.ts new file mode 100644 index 00000000..de733c53 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/index.ts @@ -0,0 +1,7 @@ +export * from './data-conversion'; +export * from './eur-data-checkout-classic'; +export * from './eur-data-checkout'; +export * from './eur-data-pay-for-order'; +export * from './non-eur-data-checkout-classic'; +export * from './non-eur-data-checkout'; +export * from './non-eur-data-pay-for-order'; diff --git a/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout-classic.ts b/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout-classic.ts new file mode 100644 index 00000000..8a0bd075 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout-classic.ts @@ -0,0 +1,56 @@ +/** + * Internal dependencies + */ +import { MollieTestData } from '../../../resources'; + +export const paymentStatusCheckoutClassicNonEur: MollieTestData.PaymentStatus[] = + [ + { + testId: 'C300724', + gatewaySlug: 'twint', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007248', + gatewaySlug: 'twint', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007249', + gatewaySlug: 'twint', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007250', + gatewaySlug: 'twint', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007251', + gatewaySlug: 'blik', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007252', + gatewaySlug: 'blik', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007253', + gatewaySlug: 'blik', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007254', + gatewaySlug: 'blik', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + ]; diff --git a/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout.ts b/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout.ts new file mode 100644 index 00000000..a3f1c6df --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/non-eur-data-checkout.ts @@ -0,0 +1,55 @@ +/** + * Internal dependencies + */ +import { MollieTestData } from '../../../resources'; + +export const paymentStatusCheckoutNonEur: MollieTestData.PaymentStatus[] = [ + { + testId: 'C3007271', + gatewaySlug: 'twint', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007272', + gatewaySlug: 'twint', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007273', + gatewaySlug: 'twint', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007274', + gatewaySlug: 'twint', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007275', + gatewaySlug: 'blik', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007276', + gatewaySlug: 'blik', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007277', + gatewaySlug: 'blik', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007278', + gatewaySlug: 'blik', + paymentStatus: 'expired', + orderStatus: 'pending', + }, +]; diff --git a/tests/qa/tests/05-transaction/.test-data/non-eur-data-pay-for-order.ts b/tests/qa/tests/05-transaction/.test-data/non-eur-data-pay-for-order.ts new file mode 100644 index 00000000..31e85072 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-data/non-eur-data-pay-for-order.ts @@ -0,0 +1,55 @@ +/** + * Internal dependencies + */ +import { MollieTestData } from '../../../resources'; + +export const paymentStatusPayForOrderNonEur: MollieTestData.PaymentStatus[] = [ + { + testId: 'C3007279', + gatewaySlug: 'twint', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007280', + gatewaySlug: 'twint', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007281', + gatewaySlug: 'twint', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007282', + gatewaySlug: 'twint', + paymentStatus: 'expired', + orderStatus: 'pending', + }, + { + testId: 'C3007287', + gatewaySlug: 'blik', + paymentStatus: 'paid', + orderStatus: 'processing', + }, + { + testId: 'C3007288', + gatewaySlug: 'blik', + paymentStatus: 'failed', + orderStatus: 'pending', + }, + { + testId: 'C3007289', + gatewaySlug: 'blik', + paymentStatus: 'canceled', + orderStatus: 'pending', + }, + { + testId: 'C3007290', + gatewaySlug: 'blik', + paymentStatus: 'expired', + orderStatus: 'pending', + }, +]; diff --git a/tests/qa/tests/05-transaction/.test-scenarios/checkout-classic.scenario.ts b/tests/qa/tests/05-transaction/.test-scenarios/checkout-classic.scenario.ts new file mode 100644 index 00000000..744d9b98 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-scenarios/checkout-classic.scenario.ts @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { countTotals } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { test } from '../../../utils'; + +export const testPaymentStatusCheckoutClassic = ( testId: string, order ) => { + test( `${ testId } | Classic checkout - ${ order.payment.gateway.name } - Payment status "${ order.payment.status }" creates order with status "${ order.orderStatus }"`, async ( { + wooCommerceApi, + transaction, + wooCommerceOrderEdit, + } ) => { + const currency = order.payment.gateway.currency; + if ( currency !== undefined && currency !== 'EUR' ) { + await wooCommerceApi.updateGeneralSettings( { + woocommerce_currency: currency, + } ); + } + order.payment.amount = ( await countTotals( order ) ).order; + const orderId = await transaction.onClassicCheckout( order ); + await wooCommerceOrderEdit.assertOrderDetails( + Number( orderId ), + order + ); + } ); +}; diff --git a/tests/qa/tests/05-transaction/.test-scenarios/checkout.scenario.ts b/tests/qa/tests/05-transaction/.test-scenarios/checkout.scenario.ts new file mode 100644 index 00000000..7d595213 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-scenarios/checkout.scenario.ts @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { countTotals } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { test } from '../../../utils'; + +export const testPaymentStatusCheckout = ( testId: string, order ) => { + test( `${ testId } | Checkout - ${ order.payment.gateway.name } - Payment status "${ order.payment.status }" creates order with status "${ order.orderStatus }"`, async ( { + wooCommerceApi, + transaction, + wooCommerceOrderEdit, + } ) => { + const currency = order.payment.gateway.currency; + if ( currency !== undefined && currency !== 'EUR' ) { + await wooCommerceApi.updateGeneralSettings( { + woocommerce_currency: currency, + } ); + } + order.payment.amount = ( await countTotals( order ) ).order; + const orderId = await transaction.onCheckout( order ); + await wooCommerceOrderEdit.assertOrderDetails( + Number( orderId ), + order + ); + } ); +}; diff --git a/tests/qa/tests/05-transaction/.test-scenarios/index.ts b/tests/qa/tests/05-transaction/.test-scenarios/index.ts new file mode 100644 index 00000000..a2c8706a --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-scenarios/index.ts @@ -0,0 +1,3 @@ +export * from './checkout-classic.scenario'; +export * from './checkout.scenario'; +export * from './pay-for-order.scenario'; diff --git a/tests/qa/tests/05-transaction/.test-scenarios/pay-for-order.scenario.ts b/tests/qa/tests/05-transaction/.test-scenarios/pay-for-order.scenario.ts new file mode 100644 index 00000000..add26969 --- /dev/null +++ b/tests/qa/tests/05-transaction/.test-scenarios/pay-for-order.scenario.ts @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { countTotals } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { test } from '../../../utils'; + +export const testPaymentStatusPayForOrder = ( testId: string, order ) => { + test( `${ testId } | Pay for order - ${ order.payment.gateway.name } - Payment status "${ order.payment.status }" creates order with status "${ order.orderStatus }"`, async ( { + wooCommerceApi, + transaction, + wooCommerceOrderEdit, + } ) => { + const currency = order.payment.gateway.currency; + if ( currency !== undefined && currency !== 'EUR' ) { + await wooCommerceApi.updateGeneralSettings( { + woocommerce_currency: currency, + } ); + } + order.payment.amount = ( await countTotals( order ) ).order; + const orderId = await transaction.onPayForOrder( order ); + await wooCommerceOrderEdit.assertOrderDetails( + Number( orderId ), + order + ); + } ); +}; diff --git a/tests/qa/tests/05-transaction/eur-checkout-classic.spec.ts b/tests/qa/tests/05-transaction/eur-checkout-classic.spec.ts new file mode 100644 index 00000000..56fb1be0 --- /dev/null +++ b/tests/qa/tests/05-transaction/eur-checkout-classic.spec.ts @@ -0,0 +1,27 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusCheckoutClassic } from './.test-scenarios'; +import { createShopOrder, paymentStatusCheckoutClassicEur } from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: true, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusCheckoutClassicEur ) { + const order = createShopOrder( testData ); + testPaymentStatusCheckoutClassic( testData.testId, order ); +} diff --git a/tests/qa/tests/05-transaction/eur-checkout.spec.ts b/tests/qa/tests/05-transaction/eur-checkout.spec.ts new file mode 100644 index 00000000..fa7a84bf --- /dev/null +++ b/tests/qa/tests/05-transaction/eur-checkout.spec.ts @@ -0,0 +1,27 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusCheckout } from './.test-scenarios'; +import { createShopOrder, paymentStatusCheckoutEur } from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: false, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusCheckoutEur ) { + const order = createShopOrder( testData ); + testPaymentStatusCheckout( testData.testId, order ); +} diff --git a/tests/qa/tests/05-transaction/eur-pay-for-order.spec.ts b/tests/qa/tests/05-transaction/eur-pay-for-order.spec.ts new file mode 100644 index 00000000..e7dd7c4c --- /dev/null +++ b/tests/qa/tests/05-transaction/eur-pay-for-order.spec.ts @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusPayForOrder } from './.test-scenarios'; +import { createShopOrder, paymentStatusPayForOrderEur } from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: false, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusPayForOrderEur ) { + const order = createShopOrder( testData ); + testPaymentStatusPayForOrder( testData.testId, order ); +} diff --git a/tests/qa/tests/05-transaction/non-eur-checkout-classic.spec.ts b/tests/qa/tests/05-transaction/non-eur-checkout-classic.spec.ts new file mode 100644 index 00000000..a3ba4622 --- /dev/null +++ b/tests/qa/tests/05-transaction/non-eur-checkout-classic.spec.ts @@ -0,0 +1,29 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusCheckoutClassic } from './.test-scenarios'; +import { + createShopOrder, + paymentStatusCheckoutClassicNonEur, +} from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: true, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusCheckoutClassicNonEur ) { + const order = createShopOrder( testData ); + testPaymentStatusCheckoutClassic( testData.testId, order ); +} diff --git a/tests/qa/tests/05-transaction/non-eur-checkout.spec.ts b/tests/qa/tests/05-transaction/non-eur-checkout.spec.ts new file mode 100644 index 00000000..0c06a26e --- /dev/null +++ b/tests/qa/tests/05-transaction/non-eur-checkout.spec.ts @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusCheckout } from './.test-scenarios'; +import { createShopOrder, paymentStatusCheckoutNonEur } from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: false, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusCheckoutNonEur ) { + const order = createShopOrder( testData ); + testPaymentStatusCheckout( testData.testId, order ); +} diff --git a/tests/qa/tests/05-transaction/non-eur-pay-for-order.spec.ts b/tests/qa/tests/05-transaction/non-eur-pay-for-order.spec.ts new file mode 100644 index 00000000..861bacfc --- /dev/null +++ b/tests/qa/tests/05-transaction/non-eur-pay-for-order.spec.ts @@ -0,0 +1,26 @@ +/** + * Internal dependencies + */ +import { test } from '../../utils'; +import { testPaymentStatusPayForOrder } from './.test-scenarios'; +import { createShopOrder, paymentStatusPayForOrderNonEur } from './.test-data'; +import { shopSettings } from '../../resources'; + +test.beforeAll( async ( { utils }, testInfo ) => { + if ( testInfo.project.name !== 'all' ) { + return; + } + await utils.configureStore( { + settings: { + general: shopSettings.germany.general, + }, + classicPages: false, + } ); + await utils.installActivateMollie(); + await utils.cleanReconnectMollie(); +} ); + +for ( const testData of paymentStatusPayForOrderNonEur ) { + const order = createShopOrder( testData ); + testPaymentStatusPayForOrder( testData.testId, order ); +} diff --git a/tests/qa/tsconfig.json b/tests/qa/tsconfig.json new file mode 100644 index 00000000..2169c886 --- /dev/null +++ b/tests/qa/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2019", + "types": ["node"], + "esModuleInterop": true, + "skipLibCheck": true, + "strict": false, + "baseUrl": ".", + "resolveJsonModule": true + } + } \ No newline at end of file diff --git a/tests/qa/utils/admin/index.ts b/tests/qa/utils/admin/index.ts new file mode 100644 index 00000000..a3f2f558 --- /dev/null +++ b/tests/qa/utils/admin/index.ts @@ -0,0 +1,6 @@ +export * from './mollie-settings-page'; +export * from './mollie-settings-api-keys'; +export * from './mollie-settings-payment-methods'; +export * from './mollie-settings-advanced'; +export * from './mollie-settings-gateway'; +export * from './woocommerce-order-edit'; diff --git a/tests/qa/utils/admin/mollie-settings-advanced.ts b/tests/qa/utils/admin/mollie-settings-advanced.ts new file mode 100644 index 00000000..f5c2906e --- /dev/null +++ b/tests/qa/utils/admin/mollie-settings-advanced.ts @@ -0,0 +1,116 @@ +/** + * Internal dependencies + */ +import { MollieSettingsPage } from './mollie-settings-page'; +import { MollieSettings } from '../../resources'; +import { urls } from '../urls'; + +export class MollieSettingsAdvanced extends MollieSettingsPage { + url = urls.mollie.admin.settings.advanced; + tabText = 'Advanced settings'; + headingText = 'Mollie advanced settings'; + + // Locators + debugLogCheckbox = () => + this.page.locator( '#mollie-payments-for-woocommerce_debug' ); + orderStatusCancelledPaymentSelect = () => + this.page.locator( + '#mollie-payments-for-woocommerce_order_status_cancelled_payments' + ); + paymentScreenLanguageSelect = () => + this.page.locator( '#mollie-payments-for-woocommerce_payment_locale' ); + storeCustomerDetailsAtMollieCheckbox = () => + this.page.locator( + '#mollie-payments-for-woocommerce_customer_details' + ); + selectAPIMethodSelect = () => + this.page.locator( '#mollie-payments-for-woocommerce_api_switch' ); + apiPaymentDescriptionInput = () => + this.page.locator( + '#mollie-payments-for-woocommerce_api_payment_description' + ); + apiPaymentDescriptionButton = ( + name: MollieSettings.ApiPaymentDescription + ) => this.page.locator( `button[data-tag="${ name }"]` ); + surchargeGatewayFeeLabelInput = () => + this.page.locator( '#mollie-payments-for-woocommerce_gatewayFeeLabel' ); + removeMollieDataFromDatabaseOnUninstall = () => + this.page.locator( + '#mollie-payments-for-woocommerce_removeOptionsAndTransients' + ); + clearNowLink = () => + this.page.locator( + 'label[for="mollie-payments-for-woocommerce_removeOptionsAndTransients"] a' + ); + placingPaymentsOnHoldSelect = () => + this.page.locator( + '#mollie-payments-for-woocommerce_place_payment_onhold' + ); + + // Actions + + /** + * Setup Mollie Advanced settings + * + * @param data + */ + setup = async ( data: MollieSettings.Advanced ) => { + if ( data.debugLogEnabled !== undefined ) { + await this.debugLogCheckbox().setChecked( data.debugLogEnabled ); + } + + if ( data.orderStatusCancelledPayments !== undefined ) { + await this.orderStatusCancelledPaymentSelect().selectOption( + data.orderStatusCancelledPayments + ); + } + + if ( data.paymentLocale !== undefined ) { + await this.paymentScreenLanguageSelect().selectOption( + data.paymentLocale + ); + } + + if ( data.customerDetails !== undefined ) { + await this.storeCustomerDetailsAtMollieCheckbox().setChecked( + data.customerDetails + ); + } + + if ( data.apiMethod !== undefined ) { + await this.selectAPIMethodSelect().selectOption( data.apiMethod ); + } + + if ( data.apiPaymentDescription !== undefined ) { + await this.apiPaymentDescriptionInput().clear(); + await this.apiPaymentDescriptionButton( + data.apiPaymentDescription + ).click(); + } + + if ( data.gatewayFeeLabel !== undefined ) { + await this.surchargeGatewayFeeLabelInput().fill( + data.gatewayFeeLabel + ); + } + + if ( data.removeOptionsAndTransients !== undefined ) { + await this.removeMollieDataFromDatabaseOnUninstall().setChecked( + data.removeOptionsAndTransients + ); + } + + if ( data.placePaymentOnhold !== undefined ) { + await this.placingPaymentsOnHoldSelect().selectOption( + data.placePaymentOnhold + ); + } + }; + + cleanDb = async () => { + await this.clearNowLink().click(); + await this.page.waitForLoadState(); + }; + + // Assertions +} diff --git a/tests/qa/utils/admin/mollie-settings-api-keys.ts b/tests/qa/utils/admin/mollie-settings-api-keys.ts new file mode 100644 index 00000000..2bdecdfb --- /dev/null +++ b/tests/qa/utils/admin/mollie-settings-api-keys.ts @@ -0,0 +1,59 @@ +/** + * Internal dependencies + */ +import { mollieConfigGeneral, MollieSettings } from '../../resources'; +import { urls } from '../urls'; +import { MollieSettingsPage } from './mollie-settings-page'; + +export class MollieSettingsApiKeys extends MollieSettingsPage { + url = urls.mollie.admin.settings.home; + tabText = 'API Keys'; + headingText = 'Mollie API Keys'; + + // Locators + successfullyConnectedWithTestApiText = () => + this.page.getByText( 'Successfully connected with Test API' ); + failedToConnectToMollieApiText = () => + this.page.getByText( + 'Failed to connect to Mollie API - check your API keys' + ); + molliePaymentModeSelect = () => + this.page.locator( + '#mollie-payments-for-woocommerce_test_mode_enabled' + ); + liveApiKeyInput = () => + this.page.locator( '#mollie-payments-for-woocommerce_live_api_key' ); + testApiKeyInput = () => + this.page.locator( '#mollie-payments-for-woocommerce_test_api_key' ); + + // Actions + + /** + * Setup Mollie General settings + * + * @param data + */ + setup = async ( data: MollieSettings.ApiKeys ) => { + if ( data.testModeEnabled !== undefined ) { + await this.molliePaymentModeSelect().selectOption( + data.testModeEnabled + ); + } + + if ( data.liveApiKey !== undefined ) { + await this.liveApiKeyInput().fill( data.liveApiKey ); + } + + if ( data.testApiKey !== undefined ) { + await this.testApiKeyInput().fill( data.testApiKey ); + } + }; + + setApiKeys = async ( + data: MollieSettings.ApiKeys = mollieConfigGeneral.default + ) => { + await this.setup( data ); + }; + + // Assertions +} diff --git a/tests/qa/utils/admin/mollie-settings-gateway.ts b/tests/qa/utils/admin/mollie-settings-gateway.ts new file mode 100644 index 00000000..c7b6074a --- /dev/null +++ b/tests/qa/utils/admin/mollie-settings-gateway.ts @@ -0,0 +1,399 @@ +/** + * External dependencies + */ +import { WooCommerceAdminPage } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { gateways, MollieGateway, MollieSettings } from '../../resources'; +import { urls } from '../urls'; + +export class MollieSettingsGateway extends WooCommerceAdminPage { + url: string; + gateway: MollieGateway; + + constructor( { page, gatewaySlug } ) { + super( { page } ); + this.url = urls.mollie.admin.settings.gateway + gatewaySlug; + this.gateway = gateways[ gatewaySlug ]; + } + + // Locators + enableGatewayCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_enabled` + ); + useApiDynamicTitleAndGatewayLogoCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_use_api_title` + ); + titleInput = () => + this.page.locator( `#mollie_wc_gateway_${ this.gateway.slug }_title` ); + displayLogoCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_display_logo` + ); + enableCustomLogoCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_enable_custom_logo` + ); + uploadCustomLogoButton = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_upload_logo` + ); + descriptionTextarea = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_description` + ); + + sellToSpecificCountriesCombobox = () => + this.page.getByPlaceholder( 'Choose countries' ); + selectAllButton = () => this.page.locator( 'a.select_all.button' ); + selectNoneButton = () => this.page.locator( 'a.select_none.button' ); + + paymentSurchargeSelect = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_payment_surcharge` + ); + paymentSurchargeFixedAmountInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_fixed_fee` + ); + surchargeOnlyUnderLimitInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_maximum_limit` + ); + paymentSurchargePercentageAmountInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_percentage` + ); + paymentSurchargeLimitInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_surcharge_limit` + ); + + activateExpiryTimeSettingCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_activate_expiry_days_setting` + ); + expiryTimeInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_order_dueDate` + ); + showIssuersDropdownCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_issuers_dropdown_shown` + ); + initialOrderStatusSelect = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_initial_order_status` + ); + skipMolliePaymentScreenCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_skip_mollie_payment_screen` + ); + enableMollieComponentsCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_components_enabled` + ); + + enableApplePayButtonOnCartCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_apple_pay_button_enabled_cart` + ); + enableApplePayButtonOnProductCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_apple_pay_button_enabled_product` + ); + enableApplePayExpressButtonOnCheckoutCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_apple_pay_button_enabled_express_checkout` + ); + + paypalDisplayOnCartCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_paypal_button_enabled_cart` + ); + paypalDisplayOnProductCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_paypal_button_enabled_product` + ); + paypalButtonTextLanguageAndColorSelect = () => + this.page.locator( `#mollie_wc_gateway_${ this.gateway.slug }_color` ); + paypalMinimumAmountToDisplayButtonInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_paypal_button_minimum_amount` + ); + + giftcardsShowDropdownCheckbox = () => this.showIssuersDropdownCheckbox(); + kbcShowBanksDropdownCheckbox = () => this.showIssuersDropdownCheckbox(); + kbcIssuersEmptyOptionInput = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_issuers_empty_option` + ); + + voucherDefaultProductsCategorySelect = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mealvoucher_category_default` + ); + + enableIconsSelectorCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_enabler` + ); + showAmericanExpressIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_amex` + ); + showCartaSiIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_cartasi` + ); + showCarteBancaireIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_cartebancaire` + ); + showMaestroIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_maestro` + ); + showMastercardIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_mastercard` + ); + showVisaIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_visa` + ); + showVpayIconCheckbox = () => + this.page.locator( + `#mollie_wc_gateway_${ this.gateway.slug }_mollie_creditcard_icons_vpay` + ); + + // Actions + + /** + * Setup Mollie gateway settings + * + * @param data + */ + setup = async ( data: MollieSettings.Gateway = this.gateway.settings ) => { + if ( data.enableGateway !== undefined ) { + await this.enableGatewayCheckbox().setChecked( data.enableGateway ); + } + + if ( data.useApiTitle !== undefined ) { + await this.useApiDynamicTitleAndGatewayLogoCheckbox().setChecked( + data.useApiTitle + ); + } + + if ( data.title ) { + await this.titleInput().fill( data.title ); + } + + if ( data.displayLogo !== undefined ) { + await this.displayLogoCheckbox().setChecked( data.displayLogo ); + } + + if ( data.enableCustomLogo !== undefined ) { + await this.enableCustomLogoCheckbox().setChecked( + data.enableCustomLogo + ); + } + + if ( data.enableCustomLogo === true && data.customLogoPath ) { + await this.uploadCustomLogoButton().setInputFiles( + './resources/files/mollie-test-logo.png' + ); + } + + if ( data.description !== undefined ) { + await this.descriptionTextarea().fill( data.description ); + } + + if ( data.sellToCountries && data.sellToCountries.length > 0 ) { + await this.selectNoneButton().click(); + if ( data.sellToCountries.length ) { + for ( const country of data.sellToCountries ) { + await this.sellToSpecificCountriesCombobox().click(); + await this.dropdownOption( country ).click(); + } + } + } + + if ( data.payment_surcharge ) { + await this.paymentSurchargeSelect().selectOption( + data.payment_surcharge + ); + + if ( data.fixed_fee ) { + await this.paymentSurchargeFixedAmountInput().fill( + data.fixed_fee + ); + } + + if ( data.maximum_limit ) { + await this.surchargeOnlyUnderLimitInput().fill( + data.maximum_limit + ); + } + + if ( data.percentage ) { + await this.paymentSurchargePercentageAmountInput().fill( + data.percentage + ); + } + + if ( data.surcharge_limit ) { + await this.paymentSurchargeLimitInput().fill( + data.surcharge_limit + ); + } + } + + if ( data.activateExpiryDaysSetting !== undefined ) { + await this.activateExpiryTimeSettingCheckbox().setChecked( + data.activateExpiryDaysSetting + ); + } + + if ( data.orderDueDate ) { + await this.expiryTimeInput().fill( data.orderDueDate ); + } + + if ( data.showIssuersDropdown ) { + await this.showIssuersDropdownCheckbox().setChecked( + data.showIssuersDropdown + ); + } + + if ( data.initialOrderStatus ) { + await this.initialOrderStatusSelect().selectOption( + data.initialOrderStatus + ); + } + + if ( data.banktransferSkipMolliePaymentScreen !== undefined ) { + await this.skipMolliePaymentScreenCheckbox().setChecked( + data.banktransferSkipMolliePaymentScreen + ); + } + + if ( data.enableApplePayButtonOnCart !== undefined ) { + await this.enableApplePayButtonOnCartCheckbox().setChecked( + data.enableApplePayButtonOnCart + ); + } + + if ( data.enableApplePayButtonOnProduct !== undefined ) { + await this.enableApplePayButtonOnProductCheckbox().setChecked( + data.enableApplePayButtonOnProduct + ); + } + + if ( data.enableApplePayExpressButtonOnCheckout !== undefined ) { + await this.enableApplePayExpressButtonOnCheckoutCheckbox().setChecked( + data.enableApplePayExpressButtonOnCheckout + ); + } + + if ( data.paypalDisplayOnCart !== undefined ) { + await this.paypalDisplayOnCartCheckbox().setChecked( + data.paypalDisplayOnCart + ); + } + + if ( data.paypalDisplayOnProduct !== undefined ) { + await this.paypalDisplayOnProductCheckbox().setChecked( + data.paypalDisplayOnProduct + ); + } + + if ( data.paypalButtonTextLanguageAndColor ) { + await this.paypalButtonTextLanguageAndColorSelect().selectOption( + data.paypalButtonTextLanguageAndColor + ); + } + + if ( data.paypalMinimumAmountToDisplayButton ) { + await this.paypalMinimumAmountToDisplayButtonInput().fill( + data.paypalMinimumAmountToDisplayButton + ); + } + + if ( data.giftcardShowDropdown !== undefined ) { + await this.giftcardsShowDropdownCheckbox().setChecked( + data.giftcardShowDropdown + ); + } + + if ( data.kbcShowBanksDropdown !== undefined ) { + await this.kbcShowBanksDropdownCheckbox().setChecked( + data.kbcShowBanksDropdown + ); + } + + if ( data.issuersEmptyOption ) { + await this.kbcIssuersEmptyOptionInput().fill( + data.issuersEmptyOption + ); + } + + if ( data.voucherDefaultProductsCategory ) { + await this.voucherDefaultProductsCategorySelect().selectOption( + data.voucherDefaultProductsCategory + ); + } + + if ( data.enableMollieCreditcardIcons !== undefined ) { + await this.enableIconsSelectorCheckbox().setChecked( + data.enableMollieCreditcardIcons + ); + } + + if ( data.enableMollieCreditcardIconsAmex !== undefined ) { + await this.showAmericanExpressIconCheckbox().setChecked( + data.enableMollieCreditcardIconsAmex + ); + } + + if ( data.enableMollieCreditcardIconsCartaSi !== undefined ) { + await this.showCartaSiIconCheckbox().setChecked( + data.enableMollieCreditcardIconsCartaSi + ); + } + + if ( data.enableMollieCreditcardICarteBancaire !== undefined ) { + await this.showCarteBancaireIconCheckbox().setChecked( + data.enableMollieCreditcardICarteBancaire + ); + } + + if ( data.enableMollieCreditcardIconsMaestro !== undefined ) { + await this.showMaestroIconCheckbox().setChecked( + data.enableMollieCreditcardIconsMaestro + ); + } + + if ( data.enableMollieCreditcardIconsMastercard !== undefined ) { + await this.showMastercardIconCheckbox().setChecked( + data.enableMollieCreditcardIconsMastercard + ); + } + + if ( data.enableMollieCreditcardIconsVisa !== undefined ) { + await this.showVisaIconCheckbox().setChecked( + data.enableMollieCreditcardIconsVisa + ); + } + + if ( data.enableMollieCreditcardIconsVpay !== undefined ) { + await this.showVpayIconCheckbox().setChecked( + data.enableMollieCreditcardIconsVpay + ); + } + }; + + // Assertions +} diff --git a/tests/qa/utils/admin/mollie-settings-page.ts b/tests/qa/utils/admin/mollie-settings-page.ts new file mode 100644 index 00000000..f6aa6659 --- /dev/null +++ b/tests/qa/utils/admin/mollie-settings-page.ts @@ -0,0 +1,26 @@ +/** + * External dependencies + */ +import { WooCommerceAdminPage } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { urls } from '../urls'; + +export class MollieSettingsPage extends WooCommerceAdminPage { + url = urls.mollie.admin.settings.home; + tabText: string; + headingText: string; + + // Locators + heading = () => + this.page.getByRole( 'heading', { name: String( this.headingText ) } ); + molliePluginDocumentationButton = () => + this.page.getByRole( 'link', { name: 'Mollie Plugin Documentation' } ); + contactMollieSupportButton = () => + this.page.getByRole( 'link', { name: 'Contact Mollie Support' } ); + + // Actions + + // Assertions +} diff --git a/tests/qa/utils/admin/mollie-settings-payment-methods.ts b/tests/qa/utils/admin/mollie-settings-payment-methods.ts new file mode 100644 index 00000000..be931bae --- /dev/null +++ b/tests/qa/utils/admin/mollie-settings-payment-methods.ts @@ -0,0 +1,20 @@ +/** + * External dependencies + */ +import { WooCommerceAdminPage } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { urls } from '../urls'; + +export class MollieSettingsPaymentMethods extends WooCommerceAdminPage { + url = urls.mollie.admin.settings.paymentMethods; + tabText: 'Payment methods'; + headingText: string; + + // Locators + + // Actions + + // Assertions +} diff --git a/tests/qa/utils/admin/woocommerce-order-edit.ts b/tests/qa/utils/admin/woocommerce-order-edit.ts new file mode 100644 index 00000000..93bd5719 --- /dev/null +++ b/tests/qa/utils/admin/woocommerce-order-edit.ts @@ -0,0 +1,166 @@ +/** + * External dependencies + */ +import { expect } from '@playwright/test'; +import { + WooCommerceOrderEdit as wooCommerceOrderEditBase, + formatMoney, +} from '@inpsyde/playwright-utils/build'; + +const { WLOP_NAME } = process.env; + +export class WooCommerceOrderEdit extends wooCommerceOrderEditBase { + // Locators + transactionIdText = ( transactionId ) => + this.orderNumberContainer().getByText( `(${ transactionId })` ); + billingDataTransactionIdInput = () => + this.billingDataContainer().getByLabel( 'Transaction ID' ); + + refundViaWorldlineButton = () => + this.page.locator( '.do-api-refund', { hasText: WLOP_NAME } ); + + productsTable = () => this.page.locator( '#order_line_items' ); + productRow = ( name ) => this.productsTable().getByRole( 'row', { name } ); + productRefundQtyInput = ( name ) => + this.productRow( name ).locator( '.refund_order_item_qty' ); + productRefundTotalInput = ( name ) => + this.productRow( name ).locator( '.refund_line_total' ); + productRefundTaxInput = ( name ) => + this.productRow( name ).locator( '.refund_line_tax' ); + + firstRefundTotalInput = () => + this.productsTable().locator( '.refund_line_total' ).first(); + + shippingTable = () => this.page.locator( '#order_shipping_line_items' ); + shippingRow = ( name ) => this.shippingTable().getByRole( 'row', { name } ); + shippingRefundTotalInput = ( name ) => + this.shippingRow( name ).locator( '.refund_line_total' ); + shippingRefundTaxInput = ( name ) => + this.shippingRow( name ).locator( '.refund_line_tax' ); + + totalWorldlineRefunded = () => + this.totalsTableRow( `${ WLOP_NAME } Refunded:` ); + totalWorldlineNetTotal = () => + this.totalsTableRow( `${ WLOP_NAME } Net Total:` ); + + // Actions + /** + * Performs Worldline refund + * + * @param amount + */ + makeRefund = async ( amount?: string ) => { + await this.refundButton().click(); + if ( ! amount ) { + const totalAmount = + ( await this.totalAvailableToRefund().textContent() ) || ''; + amount = parseFloat( + totalAmount.replace( /[^\d.-]+/g, '' ).trim() + ).toFixed( 2 ); + } + await this.firstRefundTotalInput().fill( amount ); + await this.page.on( 'dialog', ( dialog ) => dialog.accept() ); + // await this.page.on('dialog', dialog => dialog.accept()); + await this.refundViaWorldlineButton().click(); + }; + + /** + * Performs Worldline refund for specific product + * + * @param productName + * @param qty + */ + makeRefundForProduct = async ( productName: string, qty: number = 1 ) => { + await this.refundButton().click(); + await this.lineItemRefundQuantityInput( productName ).fill( + String( qty ) + ); + await this.page.on( 'dialog', ( dialog ) => dialog.accept() ); + // await this.page.on('dialog', dialog => dialog.accept()); + await this.refundViaWorldlineButton().click(); + }; + + // Assertions + + /** + * Asserts data provided on the order page + * + * @param orderId + * @param orderData + * @param millieData + */ + assertOrderDetails = async ( + orderId: number, + orderData: WooCommerce.ShopOrder, + millieData? + ) => { + await super.assertOrderDetails( orderId, orderData ); + + if ( ! millieData ) { + return; + } + + // Transaction ID + if ( + millieData.transaction_id !== undefined && + millieData.orderTotal > 0 + ) { + } + }; + + assertRefundRequested = async ( amount: string, currency? ) => { + const orderNote = this.orderNoteWithText( + `${ WLOP_NAME }: Your refund request for ${ await formatMoney( + Number( amount ), + currency + ) } has been submitted and is pending approval.` + ); + await this.retryLocatorVisibility( orderNote ); + await expect( orderNote ).toBeVisible(); + }; + + /** + * Asserts refund has been finished: + * - Order note received + * - Processed refund ID is present + * - Order status is expected + * + * @param wlopRefundId + * @param orderStatus + * @param amount + * @param currency + */ + assertRefundFinished = async ( + wlopRefundId: string, + orderStatus: WooCommerce.OrderStatus, + amount: string, + currency? + ) => { + const orderNote = this.orderNoteWithText( + `${ WLOP_NAME }: ${ await formatMoney( + Number( amount ), + currency + ) } was refunded.` + ); + const refundProcessedText = this.page.getByText( + `Refund processed. ${ WLOP_NAME } transaction ID: ${ wlopRefundId }` + ); + await this.retryLocatorVisibility( orderNote ); + await expect( orderNote ).toBeVisible(); + await expect( refundProcessedText ).toBeVisible(); + await this.assertOrderStatus( orderStatus ); + }; + + retryLocatorVisibility = async ( locator, retries = 20 ) => { + let i = 0; + while ( i < retries ) { + await this.page.reload(); + if ( await locator.isVisible() ) { + return true; + } + await this.page.waitForTimeout( 1000 ); + i++; + } + return false; + }; +} diff --git a/tests/qa/utils/frontend/checkout.ts b/tests/qa/utils/frontend/checkout.ts new file mode 100644 index 00000000..a6dc7622 --- /dev/null +++ b/tests/qa/utils/frontend/checkout.ts @@ -0,0 +1,116 @@ +/** + * External dependencies + */ +import { Checkout as CheckoutBase } from '@inpsyde/playwright-utils/build'; + +export class Checkout extends CheckoutBase { + // Locators + cardNumberInput = () => + this.page + .frameLocator( '[title="cardNumber input"]' ) + .locator( '#cardNumber' ); + cardHolderInput = () => + this.page + .frameLocator( '[title="cardHolder input"]' ) + .locator( '#cardHolder' ); + cardExpiryDateInput = () => + this.page + .frameLocator( '[title="expiryDate input"]' ) + .locator( '#expiryDate' ); + cardVerificationCodeInput = () => + this.page + .frameLocator( '[title="verificationCode input"]' ) + .locator( '#verificationCode' ); + giftCardSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_giftcard"]' + ); + kbcIssuerSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_kbc"]' + ); + billieBillingCompanyInput = () => + this.paymentOptionsContainer().locator( '#billing-company' ); + in3PhoneInput = () => + this.paymentOptionsContainer().locator( '#billing-phone' ); + in3BirthDateInput = () => + this.paymentOptionsContainer().locator( '#billing-birthdate' ); + + // Actions + + /** + * Makes order on Checkout: + * - fills checkout form + * - selects shipping method + * - selects gateway + * - clicks Place Order button + * + * @param data + */ + makeOrder = async ( data: WooCommerce.ShopOrder ) => { + await this.visit(); + await this.applyCoupons( data.coupons ); + await this.fillCheckoutForm( data.customer ); + await this.selectShippingMethod( data.shipping.settings.title ); + await this.paymentOption( data.payment.gateway.name ).click(); + + if ( + data.payment.gateway.slug === 'kbc' && + data.payment.gateway.settings.kbcShowBanksDropdown + ) { + await this.kbcIssuerSelect().selectOption( + data.payment.bankIssuer + ); + } + + if ( data.payment.gateway.slug === 'in3' ) { + const phoneInput = this.in3PhoneInput(); + if ( await phoneInput.isVisible() ) { + await phoneInput.fill( data.customer.billing.phone ); + } + const birthDateInput = this.in3BirthDateInput(); + if ( await birthDateInput.isVisible() ) { + await birthDateInput.click(); + for ( const char of data.customer.birth_date ) { + await this.page.keyboard.type( char ); + await this.page.waitForTimeout( 100 ); + } + } + } + + if ( + data.payment.gateway.slug === 'billie' && + ( await this.billieBillingCompanyInput().isVisible() ) + ) { + await this.billieBillingCompanyInput().fill( + data.payment.billingCompany + ); + } + + if ( + data.payment.gateway.slug === 'giftcard' && + data.payment.gateway.settings.giftcardsShowDropdown && + ( await this.giftCardSelect().isVisible() ) + ) { + await this.giftCardSelect().selectOption( 'fashioncheque' ); + } + + if ( + data.payment.gateway.slug === 'creditcard' && + data.payment.gateway.settings.enableMollieComponents + ) { + await this.cardNumberInput().fill( data.payment.card.card_number ); + await this.cardHolderInput().fill( data.payment.card.card_holder ); + await this.cardExpiryDateInput().fill( + data.payment.card.expiration_date + ); + await this.cardVerificationCodeInput().fill( + data.payment.card.card_cvv + ); + } + + await this.placeOrder(); + }; + + // Assertions +} diff --git a/tests/qa/utils/frontend/classic-checkout.ts b/tests/qa/utils/frontend/classic-checkout.ts new file mode 100644 index 00000000..42208a5e --- /dev/null +++ b/tests/qa/utils/frontend/classic-checkout.ts @@ -0,0 +1,124 @@ +/** + * External dependencies + */ +import { ClassicCheckout as ClassicCheckoutBase } from '@inpsyde/playwright-utils/build'; + +export class ClassicCheckout extends ClassicCheckoutBase { + // Locators + cardNumberInput = () => + this.page + .frameLocator( '[title="cardNumber input"]' ) + .locator( '#cardNumber' ); + cardHolderInput = () => + this.page + .frameLocator( '[title="cardHolder input"]' ) + .locator( '#cardHolder' ); + cardExpiryDateInput = () => + this.page + .frameLocator( '[title="expiryDate input"]' ) + .locator( '#expiryDate' ); + cardVerificationCodeInput = () => + this.page + .frameLocator( '[title="verificationCode input"]' ) + .locator( '#verificationCode' ); + giftCardSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_giftcard"]' + ); + kbcIssuerSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_kbc"]' + ); + billieBillingCompanyInput = () => + this.paymentOptionsContainer().locator( '#billing_company' ); + in3PhoneInput = () => + this.paymentOptionsContainer().locator( '#billing_phone_in3' ); + in3BirthDateInput = () => + this.paymentOptionsContainer().locator( '#billing_birthdate_in3' ); + paymentOptionFee = ( name: string ) => + this.paymentOptionsContainer() + .locator( 'li', { + has: this.page.locator( `label:text-is("${ name }")` ), + } ) + .locator( 'p.mollie-gateway-fee' ); + paymentOptionLogo = ( name: string ) => + this.paymentOptionsContainer() + .locator( 'li', { + has: this.page.locator( `label:text-is("${ name }")` ), + } ) + .locator( 'img.mollie-gateway-icon' ); + + // Actions + + /** + * Makes order on Classic Checkout: + * - fills checkout form + * - selects shipping method + * - selects gateway + * - clicks Place Order button + * + * @param data + */ + makeOrder = async ( data: WooCommerce.ShopOrder ) => { + await this.visit(); + await this.applyCoupons( data.coupons ); + await this.fillCheckoutForm( data.customer ); + await this.selectShippingMethod( data.shipping.settings.title ); + await this.paymentOption( data.payment.gateway.name ).click(); + if ( + data.payment.gateway.slug === 'kbc' && + data.payment.gateway.settings.kbcShowBanksDropdown + ) { + await this.kbcIssuerSelect().selectOption( + data.payment.bankIssuer + ); + } + + if ( data.payment.gateway.slug === 'in3' ) { + const phoneInput = this.in3PhoneInput(); + if ( await phoneInput.isVisible() ) { + await phoneInput.fill( data.customer.billing.phone ); + } + const birthDateInput = this.in3BirthDateInput(); + if ( await birthDateInput.isVisible() ) { + await birthDateInput.click(); + for ( const char of data.customer.birth_date ) { + await this.page.keyboard.type( char ); + await this.page.waitForTimeout( 100 ); + } + } + } + + if ( + data.payment.gateway.slug === 'billie' && + ( await this.billieBillingCompanyInput().isVisible() ) + ) { + await this.billieBillingCompanyInput().fill( + data.payment.billingCompany + ); + } + if ( + data.payment.gateway.slug === 'giftcard' && + data.payment.gateway.settings.giftcardsShowDropdown && + ( await this.giftCardSelect().isVisible() ) + ) { + await this.giftCardSelect().selectOption( 'fashioncheque' ); + } + if ( + data.payment.gateway.slug === 'creditcard' && + data.payment.gateway.settings.enableMollieComponents + ) { + await this.cardNumberInput().fill( data.payment.card.card_number ); + await this.cardHolderInput().fill( data.payment.card.card_holder ); + await this.cardExpiryDateInput().fill( + data.payment.card.expiration_date + ); + await this.cardVerificationCodeInput().fill( + data.payment.card.card_cvv + ); + } + await this.placeOrder(); + }; + + // Assertions +} diff --git a/tests/qa/utils/frontend/index.ts b/tests/qa/utils/frontend/index.ts new file mode 100644 index 00000000..57c10611 --- /dev/null +++ b/tests/qa/utils/frontend/index.ts @@ -0,0 +1,4 @@ +export * from './checkout'; +export * from './classic-checkout'; +export * from './pay-for-order'; +export * from './mollie-hosted-checkout'; diff --git a/tests/qa/utils/frontend/mollie-hosted-checkout.ts b/tests/qa/utils/frontend/mollie-hosted-checkout.ts new file mode 100644 index 00000000..38eb59a6 --- /dev/null +++ b/tests/qa/utils/frontend/mollie-hosted-checkout.ts @@ -0,0 +1,121 @@ +/** + * External dependencies + */ +import { WpPage, expect } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { urls } from '../urls'; +import { + BankIssuer, + MolliePayment, + MolliePaymentStatus, +} from '../../resources'; + +export class MollieHostedCheckout extends WpPage { + url = urls.mollie.hostedCheckout; + mollieUrlRegex = /mollie\.com\/checkout/; + testModeUrlRegex = /checkout\/test-mode/; + issuerSelectionUrlRegex = /select-issuer/; + creditCardUrlRegex = /credit-card\/embedded/; + expiredUrlRegex = /test-mode\/completed/; + + // Locators + totalAmountHeader = () => this.page.locator( 'div.header__amount ' ); + orderNumberHeader = () => this.page.locator( 'div.header__info ' ); + selectIssuerButton = ( bankIssuer: BankIssuer ) => + this.page.locator( 'ul.payment-method-list' ).getByText( bankIssuer ); + paymentStatusRadio = ( paymentStatus: MolliePaymentStatus ) => + this.page.locator( `input[type="radio"][value="${ paymentStatus }"]` ); + cardNumberInput = () => + this.page + .frameLocator( '[title="cardNumber input"]' ) + .locator( '#cardNumber' ); + cardHolderInput = () => + this.page + .frameLocator( '[title="cardHolder input"]' ) + .locator( '#cardHolder' ); + cardExpiryDateInput = () => + this.page + .frameLocator( '[title="expiryDate input"]' ) + .locator( '#expiryDate' ); + cardVerificationCodeInput = () => + this.page + .frameLocator( '[title="verificationCode input"]' ) + .locator( '#verificationCode' ); + payButton = () => this.page.locator( '#submit-button' ); + continueButton = () => this.page.locator( 'button[name="submit"]' ); + + // Actions + + capturePaymentAmount = async () => { + const amountText = await this.totalAmountHeader().textContent(); + const amount = parseFloat( + amountText.replace( /[^0-9,.]/g, '' ).replace( ',', '.' ) + ); + + return parseFloat( amount.toFixed( 2 ) ); + }; + + captureOrderNumber = async () => { + const orderText = await this.orderNumberHeader().textContent(); + const orderNumber = orderText.match( /\d+/ )?.[ 0 ]; + return parseInt( orderNumber ); + }; + + payWithBank = async ( issuer: BankIssuer ) => { + await this.page.waitForURL( this.issuerSelectionUrlRegex ); + await this.selectIssuerButton( issuer ).click(); + await this.page.waitForLoadState(); + }; + + payWithCard = async ( card: WooCommerce.CreditCard ) => { + await this.page.waitForURL( this.mollieUrlRegex ); + await this.cardNumberInput().fill( card.card_number ); + await this.cardHolderInput().fill( card.card_holder ); + await this.cardExpiryDateInput().fill( card.expiration_date ); + await this.cardVerificationCodeInput().fill( card.card_cvv ); + await this.payButton().click(); + await this.page.waitForLoadState(); + }; + + pay = async ( payment: MolliePayment ) => { + await this.page.waitForURL( this.mollieUrlRegex ); + await this.assertPaymentAmount( payment.amount ); + + if ( payment.gateway.slug === 'ideal' ) { + await this.payWithBank( payment.bankIssuer ); + } + + if ( + payment.gateway.slug === 'kbc' && + ! payment.gateway.settings.kbcShowBanksDropdown + ) { + await this.payWithBank( payment.bankIssuer ); + } + + if ( + payment.gateway.slug === 'creditcard' && + ! payment.gateway.settings.enableMollieComponents + ) { + await this.payWithCard( payment.card ); + } + + await this.page.waitForURL( this.testModeUrlRegex ); + const orderNumber = this.captureOrderNumber(); + await this.paymentStatusRadio( payment.status ).click(); + await this.continueButton().click(); + await this.page.waitForLoadState(); + if ( payment.status ) return orderNumber; + }; + + // Assertions + assertUrl = async () => { + await expect( this.page.url() ).toContain( this.url ); + }; + + assertPaymentAmount = async ( expectedTotalAmount: number ) => { + const totalAmount = await this.capturePaymentAmount(); + await expect( totalAmount ).toEqual( expectedTotalAmount ); + }; +} diff --git a/tests/qa/utils/frontend/pay-for-order.ts b/tests/qa/utils/frontend/pay-for-order.ts new file mode 100644 index 00000000..ec146674 --- /dev/null +++ b/tests/qa/utils/frontend/pay-for-order.ts @@ -0,0 +1,113 @@ +/** + * External dependencies + */ +import { PayForOrder as PayForOrderBase } from '@inpsyde/playwright-utils/build'; + +export class PayForOrder extends PayForOrderBase { + // Locators + cardNumberInput = () => + this.page + .frameLocator( '[title="cardNumber input"]' ) + .locator( '#cardNumber' ); + cardHolderInput = () => + this.page + .frameLocator( '[title="cardHolder input"]' ) + .locator( '#cardHolder' ); + cardExpiryDateInput = () => + this.page + .frameLocator( '[title="expiryDate input"]' ) + .locator( '#expiryDate' ); + cardVerificationCodeInput = () => + this.page + .frameLocator( '[title="verificationCode input"]' ) + .locator( '#verificationCode' ); + giftCardSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_giftcard"]' + ); + kbcIssuerSelect = () => + this.page.locator( + 'select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_kbc"]' + ); + billieBillingCompanyInput = () => this.page.locator( '#billing_company' ); + in3PhoneInput = () => this.page.locator( '#billing_phone_in3' ); + in3BirthDateInput = () => this.page.locator( '#billing_birthdate_in3' ); + + // Actions + + /** + * Makes order on Pay for order page: + * - selects gateway + * - clicks Place Order button + * + * @param orderId + * @param orderKey + * @param data + */ + makeOrder = async ( + orderId: number, + orderKey: string, + data: WooCommerce.ShopOrder + ) => { + await this.visit( orderId, orderKey ); + await this.paymentOption( data.payment.gateway.name ).click(); + + if ( + data.payment.gateway.slug === 'kbc' && + data.payment.gateway.settings.kbcShowBanksDropdown + ) { + await this.kbcIssuerSelect().selectOption( + data.payment.bankIssuer + ); + } + + if ( data.payment.gateway.slug === 'in3' ) { + const phoneInput = this.in3PhoneInput(); + if ( await phoneInput.isVisible() ) { + await phoneInput.fill( data.customer.billing.phone ); + } + const birthDateInput = this.in3BirthDateInput(); + if ( await birthDateInput.isVisible() ) { + await birthDateInput.click(); + for ( const char of data.customer.birth_date ) { + await this.page.keyboard.type( char ); + await this.page.waitForTimeout( 100 ); + } + } + } + + if ( + data.payment.gateway.slug === 'billie' && + ( await this.billieBillingCompanyInput().isVisible() ) + ) { + await this.billieBillingCompanyInput().fill( + data.payment.billingCompany + ); + } + + if ( + data.payment.gateway.slug === 'giftcard' && + data.payment.gateway.settings.giftcardsShowDropdown + ) { + await this.giftCardSelect().selectOption( 'fashioncheque' ); + } + + if ( + data.payment.gateway.slug === 'creditcard' && + data.payment.gateway.settings.enableMollieComponents + ) { + await this.cardNumberInput().fill( data.payment.card.card_number ); + await this.cardHolderInput().fill( data.payment.card.card_holder ); + await this.cardExpiryDateInput().fill( + data.payment.card.expiration_date + ); + await this.cardVerificationCodeInput().fill( + data.payment.card.card_cvv + ); + } + + await this.payForOrderButton().click(); + }; + + // Assertions +} diff --git a/tests/qa/utils/helpers.ts b/tests/qa/utils/helpers.ts new file mode 100644 index 00000000..93960974 --- /dev/null +++ b/tests/qa/utils/helpers.ts @@ -0,0 +1,255 @@ +/** + * Sets annotation about tested customer + * If tested customer is registered (has non-empty username), + * then his billing.country will be added to annotation for example: customer-germany + * Only one customer per country is used. + * customer-germany - is a name of storage state file to use in the test. + * + * @default {} - empty annotation for guest + * @param customer + * @return object with test annotation + */ +export function annotateVisitor( customer: WooCommerce.CreateCustomer ) { + const storageStateName = getCustomerStorageStateName( customer ); + return { + annotation: { + type: 'visitor', + description: storageStateName, + }, + }; +} + +export function annotateGateway( gatewaySlug: string ) { + return { + annotation: { + type: 'mollieGateway', + description: gatewaySlug, + }, + }; +} + +/** + * Builds storage state file name for customer + * + * @param customer + * @return 'goest' or 'customer-' + */ +export function getCustomerStorageStateName( + customer: WooCommerce.CreateCustomer +) { + // check is tested customer is guest (has empty username) + if ( ! customer.username ) { + return 'guest'; + } + // for registered customers + const visitorCountry = codeToCountry( customer.billing.country ); + return `customer-${ visitorCountry }`; +} + +/** + * Converts customer.billing.country (code) to country name + * + * @param countryCode + * @return country name in lower case + */ +export function codeToCountry( countryCode: string ) { + const countries = { + AF: 'afghanistan', + AL: 'albania', + DZ: 'algeria', + AD: 'andorra', + AO: 'angola', + AG: 'antigua-and-barbuda', + AR: 'argentina', + AM: 'armenia', + AU: 'australia', + AT: 'austria', + AZ: 'azerbaijan', + BS: 'bahamas', + BH: 'bahrain', + BD: 'bangladesh', + BB: 'barbados', + BY: 'belarus', + BE: 'belgium', + BZ: 'belize', + BJ: 'benin', + BT: 'bhutan', + BO: 'bolivia', + BA: 'bosnia-and-herzegovina', + BW: 'botswana', + BR: 'brazil', + BN: 'brunei', + BG: 'bulgaria', + BF: 'burkina-faso', + BI: 'burundi', + CV: 'cape-verde', + KH: 'cambodia', + CM: 'cameroon', + CA: 'canada', + CF: 'central-african-republic', + TD: 'chad', + CL: 'chile', + CN: 'china', + CO: 'colombia', + KM: 'comoros', + CG: 'congo', + CD: 'democratic-republic-of-the-congo', + CR: 'costa-rica', + CI: 'cote-d-ivoire', + HR: 'croatia', + CU: 'cuba', + CY: 'cyprus', + CZ: 'czech-republic', + DK: 'denmark', + DJ: 'djibouti', + DM: 'dominica', + DO: 'dominican-republic', + EC: 'ecuador', + EG: 'egypt', + SV: 'el-salvador', + GQ: 'equatorial-guinea', + ER: 'eritrea', + EE: 'estonia', + SZ: 'eswatini', + ET: 'ethiopia', + FJ: 'fiji', + FI: 'finland', + FR: 'france', + GA: 'gabon', + GM: 'gambia', + GE: 'georgia', + DE: 'germany', + GH: 'ghana', + GR: 'greece', + GD: 'grenada', + GT: 'guatemala', + GN: 'guinea', + GW: 'guinea-bissau', + GY: 'guyana', + HT: 'haiti', + HN: 'honduras', + HU: 'hungary', + IS: 'iceland', + IN: 'india', + ID: 'indonesia', + IR: 'iran', + IQ: 'iraq', + IE: 'ireland', + IL: 'israel', + IT: 'italy', + JM: 'jamaica', + JP: 'japan', + JO: 'jordan', + KZ: 'kazakhstan', + KE: 'kenya', + KI: 'kiribati', + KP: 'north-korea', + KR: 'south-korea', + KW: 'kuwait', + KG: 'kyrgyzstan', + LA: 'laos', + LV: 'latvia', + LB: 'lebanon', + LS: 'lesotho', + LR: 'liberia', + LY: 'libya', + LI: 'liechtenstein', + LT: 'lithuania', + LU: 'luxembourg', + MG: 'madagascar', + MW: 'malawi', + MY: 'malaysia', + MV: 'maldives', + ML: 'mali', + MT: 'malta', + MH: 'marshall-islands', + MR: 'mauritania', + MU: 'mauritius', + MX: 'mexico', + FM: 'micronesia', + MD: 'moldova', + MC: 'monaco', + MN: 'mongolia', + ME: 'montenegro', + MA: 'morocco', + MZ: 'mozambique', + MM: 'myanmar', + NA: 'namibia', + NR: 'nauru', + NP: 'nepal', + NL: 'netherlands', + NZ: 'new-zealand', + NI: 'nicaragua', + NE: 'niger', + NG: 'nigeria', + MK: 'north-macedonia', + NO: 'norway', + OM: 'oman', + PK: 'pakistan', + PW: 'palau', + PS: 'palestine', + PA: 'panama', + PG: 'papua-new-guinea', + PY: 'paraguay', + PE: 'peru', + PH: 'philippines', + PL: 'poland', + PT: 'portugal', + QA: 'qatar', + RO: 'romania', + RU: 'russia', + RW: 'rwanda', + KN: 'saint-kitts-and-nevis', + LC: 'saint-lucia', + VC: 'saint-vincent-and-the-grenadines', + WS: 'samoa', + SM: 'san-marino', + ST: 'sao-tome-and-principe', + SA: 'saudi-arabia', + SN: 'senegal', + RS: 'serbia', + SC: 'seychelles', + SL: 'sierra-leone', + SG: 'singapore', + SK: 'slovakia', + SI: 'slovenia', + SB: 'solomon-islands', + SO: 'somalia', + ZA: 'south-africa', + SS: 'south-sudan', + ES: 'spain', + LK: 'sri-lanka', + SD: 'sudan', + SR: 'suriname', + SE: 'sweden', + CH: 'switzerland', + SY: 'syria', + TW: 'taiwan', + TJ: 'tajikistan', + TZ: 'tanzania', + TH: 'thailand', + TL: 'timor-leste', + TG: 'togo', + TO: 'tonga', + TT: 'trinidad-and-tobago', + TN: 'tunisia', + TR: 'turkey', + TM: 'turkmenistan', + TV: 'tuvalu', + UG: 'uganda', + UA: 'ukraine', + AE: 'united-arab-emirates', + GB: 'united-kingdom', + US: 'usa', + UY: 'uruguay', + UZ: 'uzbekistan', + VU: 'vanuatu', + VA: 'vatican-city', + VE: 'venezuela', + VN: 'vietnam', + YE: 'yemen', + ZM: 'zambia', + ZW: 'zimbabwe', + }; + return countries[ countryCode ]; +} diff --git a/tests/qa/utils/index.ts b/tests/qa/utils/index.ts new file mode 100644 index 00000000..819c33ca --- /dev/null +++ b/tests/qa/utils/index.ts @@ -0,0 +1,8 @@ +export * from './test'; +export * from './helpers'; +export * from './mollie-api'; +export * from './urls'; +export * from './utils'; +export * from './admin'; +export * from './frontend'; +export * from './transaction'; diff --git a/tests/qa/utils/mollie-api.ts b/tests/qa/utils/mollie-api.ts new file mode 100644 index 00000000..71c3cb70 --- /dev/null +++ b/tests/qa/utils/mollie-api.ts @@ -0,0 +1,23 @@ +/** + * External dependencies + */ +import { WooCommerceApi } from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { MollieSettings } from '../resources'; + +export class MollieApi extends WooCommerceApi { + updateMollieGateway = async ( + gatewaySlug: string, + settings: MollieSettings.Gateway + ) => { + const requestData = { settings }; + const response = await this.wcRequest( + 'put', + `payment_gateways/mollie_wc_gateway_${ gatewaySlug }`, + requestData + ); + return response; + }; +} diff --git a/tests/qa/utils/test.ts b/tests/qa/utils/test.ts new file mode 100644 index 00000000..0a19ecd9 --- /dev/null +++ b/tests/qa/utils/test.ts @@ -0,0 +1,177 @@ +/** + * External dependencies + */ +import fs from 'fs'; +import { APIRequestContext, Page } from '@playwright/test'; +import { + test as base, + CustomerAccount, + CustomerPaymentMethods, + expect, + OrderReceived, + WooCommerceApi, +} from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { + MollieSettingsApiKeys, + MollieSettingsPaymentMethods, + MollieSettingsAdvanced, + WooCommerceOrderEdit, + MollieSettingsGateway, +} from './admin'; +import { + Checkout, + ClassicCheckout, + PayForOrder, + MollieHostedCheckout, +} from './frontend'; +import { MollieApi, Transaction, Utils } from '.'; + +const test = base.extend< { + // Dashboard fixtures + mollieApi: MollieApi; + mollieSettingsApiKeys: MollieSettingsApiKeys; + mollieSettingsPaymentMethods: MollieSettingsPaymentMethods; + mollieSettingsAdvanced: MollieSettingsAdvanced; + mollieSettingsGateway: MollieSettingsGateway; + + // Frontend fixtures + visitorPage: Page; + visitorRequest: APIRequestContext; + visitorWooCommerceApi: WooCommerceApi; + wooCommerceOrderEdit: WooCommerceOrderEdit; + checkout: Checkout; + classicCheckout: ClassicCheckout; + payForOrder: PayForOrder; + orderReceived: OrderReceived; + mollieHostedCheckout: MollieHostedCheckout; + + // Complex fixtures + utils: Utils; + transaction: Transaction; +} >( { + // Dashboard pages operated by Admin + mollieApi: async ( { request }, use ) => { + await use( new MollieApi( { request } ) ); + }, + mollieSettingsApiKeys: async ( { page }, use ) => { + await use( new MollieSettingsApiKeys( { page } ) ); + }, + mollieSettingsPaymentMethods: async ( { page }, use ) => { + await use( new MollieSettingsPaymentMethods( { page } ) ); + }, + mollieSettingsAdvanced: async ( { page }, use ) => { + await use( new MollieSettingsAdvanced( { page } ) ); + }, + mollieSettingsGateway: async ( { page }, use, testInfo ) => { + const gatewaySlug = testInfo.annotations?.find( + ( el ) => el.type === 'mollieGateway' + )?.description; + await use( new MollieSettingsGateway( { page, gatewaySlug } ) ); + }, + wooCommerceOrderEdit: async ( { page }, use ) => { + await use( new WooCommerceOrderEdit( { page } ) ); + }, + + visitorPage: async ( { browser }, use, testInfo ) => { + // check if visitor is specified in test otherwise use guest + const storageStateName = + testInfo.annotations?.find( ( el ) => el.type === 'visitor' ) + ?.description || 'guest'; + const storageStatePath = `${ process.env.STORAGE_STATE_PATH }/${ storageStateName }.json`; + // apply current visitor's storage state to the context + const context = await browser.newContext( { + storageState: fs.existsSync( storageStatePath ) + ? storageStatePath + : undefined, + } ); + const page = await context.newPage(); + await use( page ); + await page.close(); + await context.close(); + }, + visitorRequest: async ( { visitorPage }, use ) => { + const request = visitorPage.request; + await use( request ); + }, + visitorWooCommerceApi: async ( { visitorRequest }, use ) => { + await use( new WooCommerceApi( { request: visitorRequest } ) ); + }, + + // Front pages operated by visitor + checkout: async ( { visitorPage }, use ) => { + await use( new Checkout( { page: visitorPage } ) ); + }, + classicCheckout: async ( { visitorPage }, use ) => { + await use( new ClassicCheckout( { page: visitorPage } ) ); + }, + payForOrder: async ( { visitorPage }, use ) => { + await use( new PayForOrder( { page: visitorPage } ) ); + }, + orderReceived: async ( { visitorPage }, use ) => { + await use( new OrderReceived( { page: visitorPage } ) ); + }, + customerAccount: async ( { visitorPage }, use ) => { + await use( new CustomerAccount( { page: visitorPage } ) ); + }, + customerPaymentMethods: async ( { visitorPage }, use ) => { + await use( new CustomerPaymentMethods( { page: visitorPage } ) ); + }, + mollieHostedCheckout: async ( { visitorPage }, use ) => { + await use( new MollieHostedCheckout( { page: visitorPage } ) ); + }, + + // Complex fixtures + utils: async ( + { + plugins, + wooCommerceUtils, + requestUtils, + wooCommerceApi, + visitorWooCommerceApi, + mollieSettingsApiKeys, + mollieSettingsAdvanced, + }, + use + ) => { + await use( + new Utils( { + plugins, + wooCommerceUtils, + requestUtils, + wooCommerceApi, + visitorWooCommerceApi, + mollieSettingsApiKeys, + mollieSettingsAdvanced, + } ) + ); + }, + transaction: async ( + { + wooCommerceUtils, + orderReceived, + checkout, + classicCheckout, + payForOrder, + mollieHostedCheckout, + utils, + }, + use + ) => { + await use( + new Transaction( { + wooCommerceUtils, + orderReceived, + checkout, + classicCheckout, + payForOrder, + mollieHostedCheckout, + utils, + } ) + ); + }, +} ); + +export { test, expect }; diff --git a/tests/qa/utils/transaction.ts b/tests/qa/utils/transaction.ts new file mode 100644 index 00000000..f136ae2b --- /dev/null +++ b/tests/qa/utils/transaction.ts @@ -0,0 +1,96 @@ +/** + * External dependencies + */ +import { + OrderReceived, + WooCommerceUtils, + expect, +} from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { + ClassicCheckout, + PayForOrder, + Checkout, + MollieHostedCheckout, +} from './frontend'; +import { Utils } from './utils'; + +export class Transaction { + wooCommerceUtils: WooCommerceUtils; + orderReceived: OrderReceived; + checkout: Checkout; + classicCheckout: ClassicCheckout; + payForOrder: PayForOrder; + mollieHostedCheckout: MollieHostedCheckout; + utils: Utils; + + constructor( { + wooCommerceUtils, + orderReceived, + checkout, + classicCheckout, + payForOrder, + mollieHostedCheckout, + utils, + } ) { + this.wooCommerceUtils = wooCommerceUtils; + this.orderReceived = orderReceived; + this.checkout = checkout; + this.classicCheckout = classicCheckout; + this.payForOrder = payForOrder; + this.mollieHostedCheckout = mollieHostedCheckout; + this.utils = utils; + } + + onCheckout = async ( data: WooCommerce.ShopOrder ) => { + await this.utils.fillVisitorsCart( data.products ); + await this.checkout.makeOrder( data ); + return this.processMolliePaymentByStatus( data ); + }; + + onClassicCheckout = async ( data: WooCommerce.ShopOrder ) => { + await this.utils.fillVisitorsCart( data.products ); + await this.classicCheckout.makeOrder( data ); + return this.processMolliePaymentByStatus( data ); + }; + + onPayForOrder = async ( data: WooCommerce.ShopOrder ) => { + const order = await this.wooCommerceUtils.createApiOrder( data ); + await this.payForOrder.makeOrder( order.id, order.order_key, data ); + return this.processMolliePaymentByStatus( data ); + }; + + processMolliePaymentByStatus = async ( data: WooCommerce.ShopOrder ) => { + let orderNumber; + const mollieOrderNumber = await this.mollieHostedCheckout.pay( + data.payment + ); + + switch ( data.payment.status ) { + case 'paid': + case 'pending': + case 'authorized': + await this.orderReceived.assertOrderDetails( data ); + orderNumber = await this.orderReceived.getOrderNumber(); + await expect( mollieOrderNumber ).toEqual( orderNumber ); + break; + + case 'failed': + case 'canceled': + await expect( this.payForOrder.heading() ).toBeVisible(); + orderNumber = await this.payForOrder.getOrderNumberFromUrl(); + await expect( mollieOrderNumber ).toEqual( orderNumber ); + break; + + case 'expired': + await expect( this.mollieHostedCheckout.page ).toHaveURL( + this.mollieHostedCheckout.expiredUrlRegex + ); + break; + } + + return mollieOrderNumber; + }; +} diff --git a/tests/qa/utils/urls.ts b/tests/qa/utils/urls.ts new file mode 100644 index 00000000..9fd32256 --- /dev/null +++ b/tests/qa/utils/urls.ts @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +import { + urls as urlsBase, + wooCommerceUrls, +} from '@inpsyde/playwright-utils/build'; + +export const urls = { + ...urlsBase.frontend, + ...wooCommerceUrls.frontend, + admin: urlsBase.admin, + wooCommerce: { + admin: wooCommerceUrls.admin, + }, + mollie: { + admin: { + settings: { + home: './wp-admin/admin.php?page=wc-settings&tab=mollie_settings', + apiKeys: + './wp-admin/admin.php?page=wc-settings&tab=mollie_settings§ion=mollie_api_keys', + paymentMethods: + './wp-admin/admin.php?page=wc-settings&tab=mollie_settings§ion=mollie_payment_methods', + advanced: + './wp-admin/admin.php?page=wc-settings&tab=mollie_settings§ion=mollie_advanced', + gateway: + './wp-admin/admin.php?page=wc-settings&tab=checkout§ion=mollie_wc_gateway_', + }, + }, + hostedCheckout: 'https://www.mollie.com/checkout', + }, +}; diff --git a/tests/qa/utils/utils.ts b/tests/qa/utils/utils.ts new file mode 100644 index 00000000..df826f7f --- /dev/null +++ b/tests/qa/utils/utils.ts @@ -0,0 +1,146 @@ +/** + * External dependencies + */ +import { + WooCommerceApi, + RequestUtils, + Plugins, + WooCommerceUtils, + restLogin, +} from '@inpsyde/playwright-utils/build'; +/** + * Internal dependencies + */ +import { + MollieSettingsApiKeys, + MollieSettingsAdvanced, + getCustomerStorageStateName, +} from '.'; +import { + MollieSettings, + molliePlugin, + mollieConfigGeneral, +} from '../resources'; + +export class Utils { + plugins: Plugins; + wooCommerceUtils: WooCommerceUtils; + requestUtils: RequestUtils; + wooCommerceApi: WooCommerceApi; + visitorWooCommerceApi: WooCommerceApi; + mollieSettingsApiKeys: MollieSettingsApiKeys; + mollieSettingsAdvanced: MollieSettingsAdvanced; + + constructor( { + plugins, + wooCommerceUtils, + requestUtils, + wooCommerceApi, + visitorWooCommerceApi, + mollieSettingsApiKeys, + mollieSettingsAdvanced, + } ) { + this.plugins = plugins; + this.wooCommerceUtils = wooCommerceUtils; + this.requestUtils = requestUtils; + this.wooCommerceApi = wooCommerceApi; + this.visitorWooCommerceApi = visitorWooCommerceApi; + this.mollieSettingsApiKeys = mollieSettingsApiKeys; + this.mollieSettingsAdvanced = mollieSettingsAdvanced; + } + + // Tested plugin preconditions + + installActivateMollie = async () => { + if ( + ! ( await this.requestUtils.isPluginInstalled( molliePlugin.slug ) ) + ) { + await this.plugins.installPluginFromFile( + molliePlugin.zipFilePath + ); + } + await this.requestUtils.activatePlugin( molliePlugin.slug ); + }; + + cleanMollieDb = async () => { + await this.mollieSettingsAdvanced.visit(); + await this.mollieSettingsAdvanced.cleanDb(); + }; + + connectMollieApi = async ( + data: MollieSettings.ApiKeys = mollieConfigGeneral.default + ) => { + await this.mollieSettingsApiKeys.visit(); + await this.mollieSettingsApiKeys.setup( data ); + await this.mollieSettingsApiKeys.saveChanges(); + }; + + cleanReconnectMollie = async () => { + await this.connectMollieApi(); + await this.cleanMollieDb(); + await this.connectMollieApi(); + }; + + /** + * Pays for order on checkout page + * + * @param products + */ + fillVisitorsCart = async ( products: WooCommerce.CreateProduct[] ) => { + const cartProducts = await this.wooCommerceUtils.createCartProducts( + products + ); + await this.visitorWooCommerceApi.clearCart(); + await this.visitorWooCommerceApi.addProductsToCart( cartProducts ); + }; + + restoreCustomer = async ( customer: WooCommerce.CreateCustomer ) => { + await this.wooCommerceUtils.deleteCustomer( customer ); + await this.wooCommerceUtils.createCustomer( customer ); + const storageStateName = getCustomerStorageStateName( customer ); + const storageStatePath = `${ process.env.STORAGE_STATE_PATH }/${ storageStateName }.json`; + await restLogin( { + baseURL: process.env.WP_BASE_URL, + httpCredentials: { + username: process.env.WP_BASIC_AUTH_USER, + password: process.env.WP_BASIC_AUTH_PASS, + }, + storageStatePath, + user: { + username: customer.username, + password: customer.password, + }, + } ); + }; + + /** + * Configures store according to the data provided + * + * @param {Object} data see /resources/woocommerce-config.ts + */ + configureStore = async ( data ) => { + if ( data.classicPages === true ) { + await this.wooCommerceUtils.activateClassicCartPage(); + await this.wooCommerceUtils.activateClassicCheckoutPage(); + } + + if ( data.classicPages === false ) { + await this.wooCommerceUtils.activateBlockCartPage(); + await this.wooCommerceUtils.activateBlockCheckoutPage(); + } + + if ( data.settings?.general ) { + await this.wooCommerceApi.updateGeneralSettings( + data.settings.general + ); + } + + if ( data.taxes ) { + await this.wooCommerceUtils.setTaxes( data.taxes ); + } + + if ( data.customer ) { + await this.restoreCustomer( data.customer ); + } + }; +}