diff --git a/.idea/php.xml b/.idea/php.xml index 34031bf4..a9af48f7 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -98,7 +98,6 @@ - @@ -126,10 +125,6 @@ - - - - diff --git a/tests/Playwright/.gitignore b/tests/Playwright/.gitignore index d6ff675a..68c5d18f 100644 --- a/tests/Playwright/.gitignore +++ b/tests/Playwright/.gitignore @@ -1,5 +1,5 @@ -node_modules -pw-browsers -test-results -.env -yarn.lock +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/tests/Playwright/README.md b/tests/Playwright/README.md deleted file mode 100644 index 832dbe95..00000000 --- a/tests/Playwright/README.md +++ /dev/null @@ -1,13 +0,0 @@ - -### Setup E2E tests -In your test environment -- Import the products -- -Check the language of the site, must be English unless specified -- Update the env with url and credentials -- VSCode has a playwright plugin -- Install and activate basic auth plugin: https://github.com/WP-API/Basic-Auth -- Run ngrok to expose the site and be able to test the webhooks -``` -$ npx playwright test -``` - diff --git a/tests/Playwright/package.json b/tests/Playwright/package.json index e6be7d45..d4530e4d 100644 --- a/tests/Playwright/package.json +++ b/tests/Playwright/package.json @@ -1,7 +1,14 @@ { - "license": "MIT", - "dependencies": { - "@playwright/test": "^1.34.2", - "dotenv": "^16.0.3" + "name": "playwright", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.43.1", + "@types/node": "^20.12.7" } } diff --git a/tests/Playwright/playwright.config.js b/tests/Playwright/playwright.config.js index 92960937..b15af2e1 100644 --- a/tests/Playwright/playwright.config.js +++ b/tests/Playwright/playwright.config.js @@ -1,130 +1,79 @@ // @ts-check -const {defineConfig, devices} = require('@playwright/test'); +const { defineConfig, devices } = require('@playwright/test'); /** * Read environment variables from file. * https://github.com/motdotla/dotenv */ -require('dotenv').config(); -const testRailOptions = { - // Whether to add with all annotations; default is false - embedAnnotationsAsProperties: true, - // Where to put the report. - outputFile: './test-results/junit-report.xml' -}; +// require('dotenv').config(); + /** * @see https://playwright.dev/docs/test-configuration */ module.exports = defineConfig({ - retries: 0, - testDir: './tests', - /* Run tests in files in parallel */ - fullyParallel: false, - //timeout: 120000, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: [ - ['line'], - ['junit', testRailOptions] - ], - //globalSetup: './globalSetup.js', + testDir: './tests', + /* 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 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - baseURL: process.env.BASEURL, - storageState: './storageState.json', - extraHTTPHeaders: {'ngrok-skip-browser-warning': '123'}, - //actionTimeout: 120000, - ignoreHTTPSErrors: true, - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - video: { - mode: 'on-first-retry', - size: {width: 1280, height: 720}, - dir: './videos' - } + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, }, - /* Configure projects for major browsers */ - projects: [ - { - name: 'setup-default-settings-merchant', - testMatch: './tests/Shared/setup-default-settings-merchant.spec.js', - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_DEFAULT_80 - } - }, - /*{ - name: 'setup-settings-merchant', - testMatch: './tests/Shared/setup-default-settings-merchant.spec.js', - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_SETTINGS_80 - } - }, - { - name: 'setup-payment-api-merchant', - testMatch: './tests/Shared/setup-default-settings-merchant.spec.js', - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_PAYMENT_80 - } - }, - { - name: 'plugins-page-80', - testDir: './tests/Plugins page', - dependencies: ['setup-settings-merchant'], - use: { - ...devices['Desktop Chrome'], - testIdAttribute: 'data-slug', - baseURL: process.env.BASEURL_SETTINGS_80 - } - }, - { - name: 'woo-payments-tab-80', - testDir: './tests/WooCommerce Payments tab', - dependencies: ['setup-default-settings-merchant'], - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_DEFAULT_80 - } - },*/ - { - name: 'transaction-scenarios-orders-80', - testDir: './tests/transaction', - dependencies: ['setup-default-settings-merchant'], - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_DEFAULT_80 - } - }, - /*{ - name: 'transaction-scenarios-payments-80', - testDir: './tests/Transaction Scenarios', - dependencies: ['setup-payment-api-merchant'], - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_PAYMENT_80 - } - }, - { - name: 'mollie-settings-tab-80', - testDir: './tests/Mollie Settings tab', - dependencies: ['setup-settings-merchant'], - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_SETTINGS_80 - } - }, - { - name: 'error-handling-80', - testDir: './tests/Error Handling', - dependencies: ['setup-default-settings-merchant'], - use: { - ...devices['Desktop Chrome'], - baseURL: process.env.BASEURL_DEFAULT_80 - } - },*/ - ], + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, }); diff --git a/tests/Playwright/tests/Shared/base-test.js b/tests/Playwright/tests/Shared/base-test.js deleted file mode 100644 index e8039fce..00000000 --- a/tests/Playwright/tests/Shared/base-test.js +++ /dev/null @@ -1,22 +0,0 @@ -const base = require('@playwright/test'); -const {allProducts} = require('./products'); -const {allMethods} = require('./gateways'); - -exports.test = base.test.extend({ - products: [allProducts, { option: true }], - gateways: [allMethods, { option: true }], - baseURL: async ({}, use) => { - await use(process.env.BASEURL); - }, - context: async ({ browser, baseURL }, use) => { - // Additional options can be included when creating the context - const context = await browser.newContext({baseURL}); - await use(context); - await context.close(); - }, - page: async ({ context }, use) => { - const page = await context.newPage(); - await use(page); - await page.close(); - }, -}); diff --git a/tests/Playwright/tests/Shared/gateways.js b/tests/Playwright/tests/Shared/gateways.js deleted file mode 100644 index b6e3138b..00000000 --- a/tests/Playwright/tests/Shared/gateways.js +++ /dev/null @@ -1,17 +0,0 @@ -const methodsConfig = require('./methodsConfig.json') - - -const banktransfer = methodsConfig.banktransfer; -const ideal = methodsConfig.ideal; -const creditcard = methodsConfig.creditcard; -const paypal = methodsConfig.paypal; -const normalizedName = (name) => { - name = name.replace('\", \"mollie-payments-for-woocommerce\")', ''); - return name.replace('__(\"', ''); -} -const getMethodNames = () => { - return Object.values(methodsConfig).map((method) => normalizedName(method.defaultTitle)); -}; -const allMethodsIds = Object.keys(methodsConfig); -const allMethods = methodsConfig; -module.exports = {banktransfer, ideal, creditcard, paypal, normalizedName, getMethodNames, allMethods, allMethodsIds}; diff --git a/tests/Playwright/tests/Shared/manualOrder.js b/tests/Playwright/tests/Shared/manualOrder.js deleted file mode 100644 index cd58ef5e..00000000 --- a/tests/Playwright/tests/Shared/manualOrder.js +++ /dev/null @@ -1,38 +0,0 @@ -export const manualOrder = { - set_paid: false, - billing: { - first_name: "Tester", - last_name: "testing", - address_1: "969 Market", - address_2: "", - city: "San Francisco", - state: "CA", - postcode: "94103", - country: "US", - email: "john.doe@example.com", - phone: "(555) 555-5555" - }, - shipping: { - first_name: "John", - last_name: "Doe", - address_1: "969 Market", - address_2: "", - city: "San Francisco", - state: "CA", - postcode: "94103", - country: "US" - }, - line_items: [ - { - product_id: 14, - quantity: 1 - } - ], - shipping_lines: [ - { - method_id: "flat_rate", - method_title: "Flat Rate", - total: "0.00" - } - ] -}; diff --git a/tests/Playwright/tests/Shared/methodsConfig.json b/tests/Playwright/tests/Shared/methodsConfig.json deleted file mode 100644 index ea8e300f..00000000 --- a/tests/Playwright/tests/Shared/methodsConfig.json +++ /dev/null @@ -1,325 +0,0 @@ -{ - "applepay": { - "id": "applepay", - "defaultTitle": "__(\"Apple Pay\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Apple Pay\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds", - "subscriptions" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "Subscription": true - }, - "bancontact": { - "id": "bancontact", - "defaultTitle": "__(\"Bancontact\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "banktransfer": { - "id": "banktransfer", - "defaultTitle": "__(\"Bank transfer\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": true, - "confirmationDelayed": true, - "SEPA": false, - "customRedirect": true - }, - "belfius": { - "id": "belfius", - "defaultTitle": "__(\"Belfius Pay Button\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "billie": { - "id": "billie", - "defaultTitle": "__(\"Billie\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Billie, all default WooCommerce checkout fields should be enabled and required.\",\"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true, - "errorMessage": "__(\"Company field is empty. To proceed with Billie payment the company field is required.\",\"mollie-payments-for-woocommerce\")", - "companyPlaceholder": "__(\"To proceed with Billie, please enter your company name here.\", \"mollie-payments-for-woocommerce\")" - }, - "creditcard": { - "id": "creditcard", - "defaultTitle": "__(\"Credit/Debit Card\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds", - "subscriptions" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "Subscription": true - }, - "eps": { - "id": "eps", - "defaultTitle": "__(\"eps\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "giftcard": { - "id": "giftcard", - "defaultTitle": "__(\"Gift cards\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "__(\"Select your gift card\", \"mollie-payments-for-woocommerce\")", - "paymentFields": true, - "instructions": false, - "supports": [ - "products" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false - }, - "giropay": { - "id": "giropay", - "defaultTitle": "__(\"giropay\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "ideal": { - "id": "ideal", - "defaultTitle": "__(\"iDEAL\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "__(\"Select your bank\", \"mollie-payments-for-woocommerce\")", - "paymentFields": true, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "in3": { - "id": "in3", - "defaultTitle": "__(\"Pay in 3 instalments, 0% interest\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "__(\"Pay in 3 instalments, 0% interest\",\"mollie-payments-for-woocommerce\")", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true - }, - "kbc": { - "id": "kbc", - "defaultTitle": "__(\"KBC/CBC Payment Button\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "__(\"Select your bank\", \"mollie-payments-for-woocommerce\")", - "paymentFields": true, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "klarnapaylater": { - "id": "klarnapaylater", - "defaultTitle": "__(\"Pay later.\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Klarna, all default WooCommerce checkout fields should be enabled and required.\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true - }, - "klarnapaynow": { - "id": "klarnapaynow", - "defaultTitle": "__(\"Pay now.\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Klarna, all default WooCommerce checkout fields should be enabled and required.\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true - }, - "klarnasliceit": { - "id": "klarnasliceit", - "defaultTitle": "__(\"Slice it.\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Klarna, all default WooCommerce checkout fields should be enabled and required.\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true - }, - "mybank": { - "id": "mybank", - "defaultTitle": "__(\"MyBank\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via MyBank\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": true - }, - "paypal": { - "id": "paypal", - "defaultTitle": "__(\"PayPal\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false - }, - "paysafecard": { - "id": "paysafecard", - "defaultTitle": "__(\"paysafecard\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false - }, - "przelewy24": { - "id": "przelewy24", - "defaultTitle": "__(\"Przelewy24\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "__(\"To accept payments via Przelewy24, a customer email is required for every payment.\", \"mollie-payments-for-woocommerce\")", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false - }, - "sofort": { - "id": "sofort", - "defaultTitle": "__(\"SOFORT Banking\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": true, - "supports": [ - "products", - "refunds" - ], - "filtersOnBuild": false, - "confirmationDelayed": true, - "SEPA": true - }, - "voucher": { - "id": "voucher", - "defaultTitle": "__(\"Vouchers\", \"mollie-payments-for-woocommerce\")", - "settingsDescription": "", - "defaultDescription": "", - "paymentFields": false, - "instructions": false, - "supports": [ - "products" - ], - "filtersOnBuild": false, - "confirmationDelayed": false, - "SEPA": false, - "orderMandatory": true - } -} diff --git a/tests/Playwright/tests/Shared/mollieUtils.js b/tests/Playwright/tests/Shared/mollieUtils.js deleted file mode 100644 index 4a46791a..00000000 --- a/tests/Playwright/tests/Shared/mollieUtils.js +++ /dev/null @@ -1,260 +0,0 @@ -const {sharedUrl: {mollieSettingsTab}} = require('../Shared/sharedUrl'); -const {loginAdmin, selectOptionSetting, fillNumberSettings} = require("./wpUtils"); -const {wooOrderPaidPage, wooOrderDetailsPageOnPaid, wooOrderRetryPage, wooOrderDetailsPageOnFailed, wooOrderCanceledPage, wooOrderDetailsPageOnCanceled} = require('../Shared/testMollieInWooPage'); -const {addProductToCart, fillCustomerInCheckout} = require('../Shared/wooUtils'); -const {normalizedName} = require("./gateways"); -const {expect} = require("@playwright/test"); -const {fillCustomerInCheckoutBlock, selectPaymentMethodInCheckout, captureTotalAmountCheckout, - captureTotalAmountBlockCheckout, parseTotalAmount -} = require("./wooUtils"); - -const settingsNames = { - surcharge: 'payment_surcharge', - noFee: 'no_fee', - fixedFee: 'fixed_fee', - percentage: 'percentage', - fixedFeePercentage: 'fixed_fee_percentage', - limitFee: 'maximum_limit', - components: 'mollie_components_enabled', -} - -const noticeLines = { - paid: (method) => `Order completed using Mollie - ${method} payment`, - open: (method) => `${method} payment started`, - completed: (method) => `Order completed using Mollie - ${method} payment`, - failed: (method) => `${method} payment started`, - canceled: (method) => `${method} payment started`, - expired: (method) => `${method} payment started`, - authorized: (method) => `Order authorized using Mollie - ${method} payment`, -} -/** - * @param {import('@playwright/test').Page} page - */ -const setOrderAPI = async (page) => { - await page.goto(mollieSettingsTab + '§ion=advanced'); - await page.selectOption('select#mollie-payments-for-woocommerce_api_switch', 'order') - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -/** - * @param {import('@playwright/test').Page} page - */ -const setPaymentAPI = async (page) => { - await page.goto(mollieSettingsTab + '§ion=advanced'); - await page.selectOption('select#mollie-payments-for-woocommerce_api_switch', 'payment') - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -/** - * @param {import('@playwright/test').Page} page - * @param status - */ -const markStatusInMollie = async (page, status) =>{ - const mollieHeader = await page.innerText('.header__info'); - const mollieOrder = mollieHeader.substring(6, mollieHeader.length) - await page.locator('text=' + status).click(); - await page.locator('text=Continue').click(); - return mollieOrder; -} - -const fillCreditCardForm = async (page) => { - let container = await page.locator('div[data-testid="mollie-container--cardHolder"]'); - let input = await container.locator('input[data-component-type="cardHolder"][type="text"]'); - await input.fill('Name'); - container = await page.locator('div[data-testid="mollie-container--cardNumber"]'); - input = await container.locator('input[data-component-type="cardNumber"][type="text"]'); - await input.fill('4543474002249996'); - container = await page.locator('div[data-testid="mollie-container--expiryDate"]'); - input = await container.locator('input[data-component-type="expiryDate"][type="text"]'); - await input.fill('12/25'); - container = await page.locator('div[data-testid="mollie-container--verificationCode"]'); - input = await container.locator('input[data-component-type="verificationCode"][type="text"]'); - await input.fill('123'); - - await page.getByRole('button', { name: 'Pay ›' }).click(); -}; -const processMollieCheckout = async (page, status) => { - const expectedUrl = 'https://www.mollie.com/checkout/test-mode?'; - const creditCardUrl = 'https://www.mollie.com/checkout/credit-card'; - if (page.url().toString().startsWith(creditCardUrl)) { - await fillCreditCardForm(page); - await page.waitForTimeout(5000); - return await markStatusInMollie(page, status);} - - if (page.url().toString().startsWith(expectedUrl)) { - return await markStatusInMollie(page, status); - } else { - // find the first button - const button = await page.$('button'); - await button.click(); - return await markStatusInMollie(page, status); - } -} - -/** - * @param {import('@playwright/test').Page} page - */ -const insertCorrectAPIKeys = async (page) =>{ - await page.goto(mollieSettingsTab); - await page.locator(`input[name="mollie-payments-for-woocommerce_live_api_key"]`).fill(process.env.MOLLIE_LIVE_API_KEY); - await page.locator(`input[name="mollie-payments-for-woocommerce_test_mode_enabled"]`).check(); - await page.locator(`input[name="mollie-payments-for-woocommerce_test_api_key"]`).fill(process.env.MOLLIE_TEST_API_KEY); - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -/** - * @param {import('@playwright/test').Page} page - */ -const insertIncorrectAPIKeys = async (page) =>{ - await page.goto(mollieSettingsTab); - await page.locator(`input[name="mollie-payments-for-woocommerce_live_api_key"]`).fill('live_1234567890'); - await page.locator(`input[name="mollie-payments-for-woocommerce_test_mode_enabled"]`).check(); - await page.locator(`input[name="mollie-payments-for-woocommerce_test_api_key"]`).fill('test_1234567890'); - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -/** - * @param {import('@playwright/test').Page} page - */ -const resetSettings = async (page) => { - await page.goto(mollieSettingsTab + '§ion=advanced'); - await Promise.all([ - page.waitForNavigation(), - await page.locator('text=clear now').click() - ]); -} - -/** - * @param {import('@playwright/test').Page} page - * @param testedProduct - * @param testedGateway - * @param productQuantity - */ -const beforePlacingOrder = async (page, testedProduct, testedGateway, productQuantity, checkoutUrl) => { - //Capture WooCommerce total amount - const totalAmount = await captureTotalAmountCheckout(page); - - // CUSTOMER DETAILS - await fillCustomerInCheckout(page); - - // Check testedGateway option NO ISSUERS DROPDOWN - const title = normalizedName(testedGateway.defaultTitle); - await selectPaymentMethodInCheckout(page, title); - if (testedGateway.paymentFields) { - await page.locator(`select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_${testedGateway.id}"]`).selectOption({index: 1}); - } - // Click text=Place order - await Promise.all([ - page.waitForNavigation(/*{ url: 'https://www.mollie.com/checkout/test-mode?method=GATEWAY&token=XXX' }*/), - page.locator('text=Place order').click() - ]); - return totalAmount; -} - -const beforePlacingOrderBlock = async (page, testedProduct, testedGateway, productQuantity, checkoutUrl) => { - await page.goto(checkoutUrl); - - //Capture WooCommerce total amount - const totalAmount = await captureTotalAmountBlockCheckout(page); - // CUSTOMER DETAILS - //await fillCustomerInCheckoutBlock(page); - - // Check testedGateway option NO ISSUERS DROPDOWN - const title = normalizedName(testedGateway.defaultTitle); - await page.getByText(title, { exact: true }).click(); - if (testedGateway.paymentFields) { - await page.locator(`select[name="mollie-payments-for-woocommerce_issuer_mollie_wc_gateway_${testedGateway.id}"]`).selectOption({index: 1}); - } - await page.getByRole('button', { name: 'Place Order' }).click(); - await page.waitForTimeout(2000) - return totalAmount; -} - -/** - * @param {import('@playwright/test').Page} page - * @param testedProduct - * @param testedGateway - * @param productQuantity - * @param status - */ -const checkoutTransaction = async (page, testedProduct, testedGateway, productQuantity = 1, status = "Paid", checkoutUrl ='/checkout/') => { - let whichCheckout = checkoutUrl === '/checkout/' ? 'classic' : 'block'; - let totalAmount; - if (whichCheckout === 'classic') { - totalAmount = await beforePlacingOrder(page, testedProduct, testedGateway, productQuantity, checkoutUrl); - } else { - totalAmount = await beforePlacingOrderBlock(page, testedProduct, testedGateway, productQuantity, checkoutUrl); - } - // IN MOLLIE - // Capture order number in Mollie and mark as required - await page.waitForTimeout(2000); - const mollieOrder = await processMollieCheckout(page, status); - - return {mollieOrder: mollieOrder, totalAmount: totalAmount}; -} - -const classicCheckoutPaidTransactionFullRefund = async (page, testedProduct, testedGateway) => { - await beforePlacingOrder(page, testedProduct, testedGateway); - const mollieOrder = await markStatusInMollie(page, "Paid"); - await wooOrderDetailsPageOnPaid(page, mollieOrder, testedGateway); - await page.locator('text=This order is no longer editable. Refund >> button').click(); - await page.locator('input[class="refund_order_item_qty"]').fill('1'); - page.on('dialog', dialog => dialog.accept()); - await page.getByRole('button', {name: 'Mollie'}).click(); - await expect(page.locator('#select2-order_status-container')).toContainText("Refunded"); -} - -const classicCheckoutPaidTransactionPartialRefund = async (page, testedProduct, testedGateway) => { - await beforePlacingOrder(page, testedProduct, testedGateway); - const mollieOrder = await markStatusInMollie(page, "Paid"); - await wooOrderDetailsPageOnPaid(page, mollieOrder, testedGateway); - await page.locator('text=This order is no longer editable. Refund >> button').click(); - await page.locator('input[class="refund_order_item_qty"]').fill('0.5'); - page.on('dialog', dialog => dialog.accept()); - await page.locator('#woocommerce-order-items > div.inside > div.wc-order-data-row.wc-order-refund-items.wc-order-data-row-toggle > div.refund-actions > button.button.button-primary.do-api-refund').click(); - await expect(page.locator('#select2-order_status-container')).toContainText("Processing"); - await expect(page.getByText('EUR9.90 refunded')).toBeVisible(); -} - -const checkExpiredAtMollie = async (page) => { - //this assumes the page is mollie checkout - await expect(page.getByText('The payment has been set to expired successfully.')).toBeVisible(); -} - -const noFeeAdded = async (page, method, products, expectedAmount) => { - const result = await checkoutTransaction(page, products.simple, method) - let received = result.totalAmount.slice(0, -1).trim(); - received = parseTotalAmount(received); - expect(received).toEqual(expectedAmount); -} - -module.exports = { - setOrderAPI, - setPaymentAPI, - markStatusInMollie, - insertAPIKeys: insertCorrectAPIKeys, - insertIncorrectAPIKeys, - resetSettings, - beforePlacingOrder, - beforePlacingOrderBlock, - checkoutTransaction, - classicCheckoutPaidTransactionFullRefund, - classicCheckoutPaidTransactionPartialRefund, - checkExpiredAtMollie, - processMollieCheckout, - settingsNames, - noticeLines, - noFeeAdded -}; diff --git a/tests/Playwright/tests/Shared/products.js b/tests/Playwright/tests/Shared/products.js deleted file mode 100644 index 8633bf32..00000000 --- a/tests/Playwright/tests/Shared/products.js +++ /dev/null @@ -1,59 +0,0 @@ -const allProducts = { - simple: { - 'id': 14, - "title": "Beanie", - 'link': '/product/beanie/', - 'sku': 'woo-beanie', - 'sale_price': '18,00 €', - 'regular_price': '20,00 €', - 'price': '18,00 €', - 'virtual': 'no', - 'downloadable': 'no', - }, - virtual: { - 'id': 18, - "title": "Album", - 'link': '/product/album/', - 'sku': 'woo-album', - 'sale_price': '15,00 €', - 'regular_price': '20,00 €', - 'price': '15,00 €', - 'virtual': 'yes', - 'downloadable': 'yes', - }, - variation: { - 'id': 13, - "title": "V-Neck T-Shirt", - 'link': "/product/v-neck-t-shirt/", - 'sku': "woo-vneck-tee", - 'sale_price': '', - 'regular_price': '', - 'price': '', - 'virtual': 'no', - 'downloadable': 'no', - }, variationRed: { - 'id': 20, - "title": "V-Neck T-Shirt - Red", - 'link': '/product/v-neck-t-shirt/?attribute_pa_color=red', - 'sku': "woo-vneck-tee-red", - 'sale_price': '', - 'regular_price': '20,00 €', - 'price': '20,00 €', - 'virtual': 'no', - 'downloadable': 'no', - }, - variationGreen: { - 'id': 21, - "title": "V-Neck T-Shirt - Green", - 'link': '/product/v-neck-t-shirt/?attribute_pa_color=green', - 'sku': "woo-vneck-tee-green", - 'sale_price': '', - 'regular_price': '20,00 €', - 'price': '20,00 €', - 'virtual': 'no', - 'downloadable': 'no', - } -}; - - -module.exports = {allProducts}; diff --git a/tests/Playwright/tests/Shared/sharedUrl.js b/tests/Playwright/tests/Shared/sharedUrl.js deleted file mode 100644 index 584d419d..00000000 --- a/tests/Playwright/tests/Shared/sharedUrl.js +++ /dev/null @@ -1,6 +0,0 @@ -export const sharedUrl = { - mollieSettingsTab: '/wp-admin/admin.php?page=wc-settings&tab=mollie_settings', - gatewaySettingsRoot: '/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=mollie_wc_gateway_', - paypalSettings : '/wp-admin/admin.php?page=wc-settings&tab=checkout§ion=mollie_wc_gateway_paypal', - blocksCheckout: '/checkout-block/' -} diff --git a/tests/Playwright/tests/Shared/test-logo.png b/tests/Playwright/tests/Shared/test-logo.png deleted file mode 100644 index c493571d..00000000 Binary files a/tests/Playwright/tests/Shared/test-logo.png and /dev/null differ diff --git a/tests/Playwright/tests/Shared/testMollieInWooPage.js b/tests/Playwright/tests/Shared/testMollieInWooPage.js deleted file mode 100644 index a4f3ff28..00000000 --- a/tests/Playwright/tests/Shared/testMollieInWooPage.js +++ /dev/null @@ -1,50 +0,0 @@ -import {normalizedName} from "./gateways"; -import {fetchOrderNotes, fetchOrderStatus} from "./wooUtils"; - -const { expect } = require('@playwright/test'); -const {sharedUrl} = require("./sharedUrl"); - -async function gotoWPPage(page, url) { - await page.goto(url); -} - -async function gotoMollieGeneralSettings(page) { - await gotoWPPage(page, sharedUrl.mollieSettingsTab); -} - -export const wooOrderPaidPage = async (page, mollieOrder, totalAmount, testedGateway) => { - // Check order number - await expect(page.locator('li.woocommerce-order-overview__order.order')).toContainText(mollieOrder); - // Check total amount in order - await expect(page.locator('li.woocommerce-order-overview__total.total > strong > span > bdi')).toContainText(totalAmount); - - if(testedGateway.id !== 'paypal'){ - // Check customer in billing details - await expect(page.getByText('My company nameJulia CallasCalle Drutal22100 BerlinGermany 1234566788 test@test.')).toBeVisible; - } - // Check Mollie method appears - const methodName = normalizedName(testedGateway.defaultTitle); - await expect(page.getByRole('cell', { name: methodName})).toBeVisible(); -} - -export const wooOrderRetryPage = async (page) => { - // Check we are in retry page - const regex = new RegExp(/checkout\/order-pay/); - await expect(page).toHaveURL(regex); -} - -export const wooOrderCanceledPage = async (page, mollieOrder, totalAmount, testedGateway) => { - await expect(page.locator('#wp--skip-link--target > div.wp-container-7.entry-content.wp-block-post-content > div > div > p')).toContainText('cancelled'); -} - -export const wooOrderDetailsPage = async (page, mollieOrder, testedGateway, status, notice) => { - // Check order is in status processing - const orderStatus = await fetchOrderStatus(mollieOrder); - await expect(orderStatus.toUpperCase()).toBe(status.toUpperCase()); - - // Check order notes has correct text - const orderNotesArray = await fetchOrderNotes(mollieOrder); - const lastOrderNote = orderNotesArray[0].note; - - //await expect(lastOrderNote.toLowerCase()).toContain(notice.toLowerCase()); -} diff --git a/tests/Playwright/tests/Shared/wooUtils.js b/tests/Playwright/tests/Shared/wooUtils.js deleted file mode 100644 index 10e194df..00000000 --- a/tests/Playwright/tests/Shared/wooUtils.js +++ /dev/null @@ -1,275 +0,0 @@ -const path = require("path"); -const fs = require("fs"); -const { request } = require('@playwright/test'); -const wooUrls = { - settingsPaymentTab: '/wp-admin/admin.php?page=wc-settings&tab=checkout' -} -const WooCommerceRestApi = require("@woocommerce/woocommerce-rest-api").default; -async function gotoWPPage(page, url) { - await page.goto(url); -} -async function gotoWooPaymentTab(page) { - await gotoWPPage(page, wooUrls.settingsPaymentTab); -} -/** - * - * @param baseUrl - * @param productId - * @param productQuantity - */ -const addProductToCart = async (baseUrl, productId, productQuantity) => { - const context = await request.newContext(); - const cartResponse = await context.post(`${baseUrl}/wp-json/wc/store/v1/cart/add-item`, { - data: { - id: productId, - quantity: productQuantity - } - }); - - // Check if the product was added successfully - if (cartResponse.ok()) { - //console.log('Product added to cart:', await cartResponse.json()); - } else { - console.error('Failed to add product to cart:', cartResponse.status(), await cartResponse.text()); - } -} - -const emptyCart = async (baseUrl) => { - const context = await request.newContext(); - const cartItemsResponse = await context.get(`${baseUrl}/wp-json/wc/store/v1/cart/items`); - - if (cartItemsResponse.ok()) { - const items = await cartItemsResponse.json(); - for (const item of items) { - const removeResponse = await context.post(`${baseUrl}/wp-json/wc/store/v1/cart/remove-item`, { - data: { - key: item.key - } - }); - if (!removeResponse.ok()) { - console.error('Failed to remove item from cart:', removeResponse.status(), await removeResponse.text()); - } - } - console.log('All items removed from cart'); - } else { - console.error('Failed to retrieve cart items:', cartItemsResponse.status(), await cartItemsResponse.text()); - } -} - -/** - * @param {import('@playwright/test').Page} page - */ -const fillCustomerInCheckout = async (page, country = "DE") => { - await page.locator('input[name="billing_first_name"]').fill('Julia'); - await page.locator('input[name="billing_last_name"]').fill('Callas'); - await page.selectOption('select#billing_country', country); - await page.locator('input[name="billing_city"]').fill('Berlin'); - await page.locator('input[name="billing_address_1"]').fill('Calle Drutal'); - await page.locator('input[name="billing_postcode"]').fill('22100'); - await page.locator('input[name="billing_phone"]').fill('1234566788'); - await page.locator('input[name="billing_email"]').fill('test@test.com'); - const canFillCompany = await page.locator('input[name="billing_company"]').isVisible(); - if (canFillCompany) { - await page.locator('input[name="billing_company"]').fill('Test company'); - } - const canFillBirthDate = await page.locator('input[name="billing_birthdate"]').isVisible(); - if (canFillBirthDate) { - await page.locator('input[name="billing_birthdate"]').fill('01-01-1990'); - } -} - -/** - * @param {import('@playwright/test').Page} page - */ -const fillCustomerInCheckoutBlock = async (page, country = 'Germany') => { - await page.getByLabel('First name').fill('Julia'); - await page.getByLabel('Last name').fill('Callas'); - await page.getByLabel('Country/Region').fill(country); - await page.getByLabel('City').fill('Berlin'); - await page.getByLabel('Address', { exact: true }).fill('Calle Drutal'); - await page.getByLabel('Postal code').fill('22100'); - await page.getByLabel('Phone').fill('1234566788'); - await page.getByLabel('Email address').fill('test@test.com'); - const canFillCompany = await page.getByLabel('Company').isVisible(); - if (canFillCompany) { - await page.getByLabel('Company').fill('Test company'); - } - const canFillBirthDate = await page.locator('input[name="billing_birthdate"]').isVisible(); - if (canFillBirthDate) { - await page.locator('input[name="billing_birthdate"]').fill('01-01-1990'); - } -} - -/** - * @param {import('@playwright/test').Page} page - */ -const fillCustomerInBlockCheckout = async (page) => { - // Fill input[name="billing_first_name"] - await page.locator('input[name="billing_first_name"]').fill('Julia'); - // Fill input[name="billing_last_name"] - await page.locator('input[name="billing_last_name"]').fill('Callas'); -} - -const selectPaymentMethodInCheckout = async (page, paymentMethod) => { - await page.locator('label').filter({ hasText: paymentMethod }).click(); -} - -const placeOrderCheckout = async (page) => { - // Click text=Place order - await page.locator('text=Place order').click() -} - -const placeOrderPayPage = async (page) => { - // Click text=Place order - await page.getByRole('button', { name: 'Pay for order' }).click() -} - -const captureTotalAmountCheckout = async (page) => { - return await page.innerText('.order-total > td > strong > span > bdi'); -} - -const parseTotalAmount = (totalAmount) => { - // "€30.80" => 30.80 - const numberStr = totalAmount.replace(/[^\d.]/g, ''); - return parseFloat(numberStr); -} - -const captureTotalAmountPayPage = async (page) => { - const totalSelector = 'tr:last-child >> td.product-total >> .woocommerce-Price-amount.amount >> bdi'; - return await page.innerText(totalSelector); -} - -const captureTotalAmountBlockCheckout = async (page) => { - let totalLine = await page.locator('div').filter({ hasText: /^Total/ }).first() - let totalAmount = await totalLine.innerText('.woocommerce-Price-amount amount > bdi'); - // totalAmount is "Total\n72,00 €" and we need to remove the "Total\n" part - return totalAmount.substring(6, totalAmount.length); -} - - -const WooCommerce = new WooCommerceRestApi({ - url: process.env.BASEURL, - consumerKey: process.env.WOO_REST_CONSUMER_KEY, - consumerSecret: process.env.WOO_REST_CONSUMER_SECRET, - version: 'wc/v3' -}); -const createManualOrder = async (page, productId, quantity=1, country='DE', postcode='') => { - try { - const order = manualOrder(productId, quantity, country, postcode) - const response = await WooCommerce.post("orders", order); - const url = `/checkout/order-pay/${response.data.id}?pay_for_order=true&key=${response.data.order_key}`; - return { - url: url, - orderId: response.data.id, - orderKey: response.data.order_key - }; - } catch (error) { - console.log(error.response.data); - } -} - -const updateMethodSetting = async (method, payload) => { - method = 'mollie_wc_gateway_'+method.toLowerCase(); - try { - const response = await WooCommerce.put( - `payment_gateways/${method}`, - payload); - return response.data; - } catch (error) { - console.log(error.response.data); - } -} - -const fetchOrderStatus = async (orderId) => { - try { - const response = await WooCommerce.get(`orders/${orderId}`); - return response.data.status; // This will contain the order's status - } catch (error) { - console.log('Error fetching order status:', error); - return null; - } -}; -const fetchOrderNotes = async (orderId) => { - try { - const response = await WooCommerce.get(`orders/${orderId}/notes`); - return response.data; // This will contain an array of order notes - } catch (error) { - console.log('Error fetching order notes:', error); - return null; - } -}; - -const getLogByName = async (name, dirname) => { - const currentDate = new Date().toISOString().split('T')[0]; - // Construct the relative path to the log file - const logsDirectory = path.join(dirname, '..', '..', '..', '.ddev', 'wordpress', 'wp-content', 'uploads', 'wc-logs'); - const files = fs.readdirSync(logsDirectory); - const matchingFiles = files.filter(file => file.includes(`${name}-${currentDate}-`)); - // Select the first matching file - const logFileName = matchingFiles[0]; - const logFilePath = path.join(logsDirectory, logFileName); - return fs.readFileSync(logFilePath, 'utf-8'); -} - -const manualOrder = (productId, productQuantity, country, postcode) => { - return { - set_paid: false, - billing: { - first_name: "Tester", - last_name: "testing", - address_1: "969 Market", - address_2: "", - city: "San Francisco", - state: "CA", - postcode: postcode, - country: country, - email: "john.doe@example.com", - phone: "(555) 555-5555" - }, - shipping: { - first_name: "John", - last_name: "Doe", - address_1: "969 Market", - address_2: "", - city: "San Francisco", - state: "CA", - postcode: postcode, - country: country - }, - line_items: [ - { - product_id: productId, - quantity: productQuantity - } - ], - shipping_lines: [ - { - method_id: "flat_rate", - method_title: "Flat Rate", - total: "0.00" - } - ] - }; -}; - - -module.exports = { - addProductToCart, - fillCustomerInCheckout, - fillCustomerInBlockCheckout, - fillCustomerInCheckoutBlock, - gotoWooPaymentTab, - placeOrderCheckout, - emptyCart, - placeOrderPayPage, - selectPaymentMethodInCheckout, - captureTotalAmountCheckout, - captureTotalAmountBlockCheckout, - captureTotalAmountPayPage, - createManualOrder, - getLogByName, - fetchOrderStatus, - fetchOrderNotes, - updateMethodSetting, - parseTotalAmount -} diff --git a/tests/Playwright/tests/Shared/wpUtils.js b/tests/Playwright/tests/Shared/wpUtils.js deleted file mode 100644 index ae8e4a11..00000000 --- a/tests/Playwright/tests/Shared/wpUtils.js +++ /dev/null @@ -1,77 +0,0 @@ -async function gotoWPPage(page, url) { - await page.goto(url); -} - -async function gotoWPLogin(page) { - await gotoWPPage(page, '/wp-login.php'); -} - -async function gotoWPPlugins(page) { - await gotoWPPage(page, '/wp-admin/plugins.php'); -} - -const loginAdmin = async (page) => { - await gotoWPLogin(page); - await page.locator('#user_login').fill(process.env.E2E_AUTH_USERNAME); - await page.locator('#user_pass').fill(process.env.E2E_AUTH_PW); - await Promise.all([ - page.waitForNavigation(), - page.locator('input:has-text("Log In")').click() - ]); -} - -async function deactivateWPPlugin(page, pluginName) { - await page.getByRole('link', {name: `Deactivate ${pluginName}`, exact: true}).click(); -} - -async function activateWPPlugin(page, pluginName) { - await page.getByRole('cell', {name: `${pluginName} Activate ${pluginName} | Delete ${pluginName}`}).getByRole('link', {name: `Activate ${pluginName}`}).click(); -} - -const enableCheckboxSetting = async (page, settingName, settingsTabUrl) => { - await page.goto(settingsTabUrl); - await page.locator(`input[name="${settingName}"]`).check(); - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -const disableCheckboxSetting = async (page, settingName, settingsTabUrl) => { - await page.goto(settingsTabUrl); - await page.locator(`input[name="${settingName}"]`).uncheck(); - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -async function saveSettings(page) { - await Promise.all([ - page.waitForNavigation(), - page.locator('text=Save changes').click() - ]); -} - -const selectOptionSetting = async (page, settingName, settingsTabUrl, optionValue) => { - await page.goto(settingsTabUrl); - await page.selectOption(`select[name="${settingName}"]`, optionValue); - await saveSettings(page); -} - -const fillTextSettings = async (page, settingName, settingsTabUrl, value) => { - await page.goto(settingsTabUrl); - let field = await page.locator(`input[name="${settingName}"]`); - await field.fill(value); - await saveSettings(page); -} - -const fillNumberSettings = async (page, settingName, settingsTabUrl, value) => { - await page.goto(settingsTabUrl); - await page.locator(`input#${settingName}`).fill(''); - await page.type(`input#${settingName}`, value.toString()); - await saveSettings(page); -} - -module.exports = {loginAdmin, deactivateWPPlugin, activateWPPlugin, gotoWPPlugins, enableCheckboxSetting, disableCheckboxSetting, selectOptionSetting, fillTextSettings, fillNumberSettings}; -