Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playwright test changes #29

Merged
merged 12 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
RVVUP_HYVA_CHECKOUT_VERSION=dev-main
RVVUP_API_KEY=replace.this.jwt
# Access to Magento Repository: https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/prerequisites/authentication-keys
MAGENTO_REPO_PUBLIC_KEY=replacethis
MAGENTO_REPO_PRIVATE_KEY=replacethis
MAGENTO_VERSION=2
# Use the private key matching one of the public keys on gitlab.hyva.io
HYVA_SSH_PRIVATE_KEY="Private key goes here"
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ node_modules/
test-results/
playwright-report/
hyva/
.idea/
.idea/

.env
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ARG MAGENTO_VERSION=2
FROM docker.io/bitnami/magento:${MAGENTO_VERSION}
COPY ./docker/scripts /rvvup/scripts
RUN apt-get update && apt-get install -y \
unzip \
git \
vim \
curl \
&& rm -rf /var/lib/apt/lists/*

RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt-get install -y nodejs

ENTRYPOINT ["/rvvup/scripts/entrypoint.sh"]
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,36 @@ After that, run setup:upgrade to install the plugin:
```bash
bin/magento setup:upgrade
```
## Dockerized Setup of Test Store

## Testing
If you would like to have a quick local installation of the plugin on a magento store (for testing), you can follow these steps:

This plugin comes with Playwright tests to ensure its functionality. To run the tests, use the following command:
- Copy .env.sample to .env and update the values as needed.
- Run the following command to start the docker containers:
```
docker-compose up -d --build
```
## End to End Testing
This plugin comes with Playwright tests to ensure it's functionality.

### Get Started (install dependencies):
```bash
npm i
npx playwright install
```

### (Recommended), Running the E2E tests against a dockerized store installation

This will spin up a docker container with magento with hyva + rvvup plugin installed and run the test against this
container.
```bash
./run-e2e-tests.sh
```

### If you have an existing store, to run the tests, use the following command:

```bash
npm ci # Install the required dependencies
npx playwright test --ui
ENV TEST_BASE_URL=https://magento.test npx playwright test --ui # change your base url to point to the right domain
```

**Please note:** There are tests included for credit card for both the inline and the modal versions. It depends on the configuration of the payment method which test will succeed.
13 changes: 13 additions & 0 deletions Test/End-2-End/Components/Cart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {expect} from "@playwright/test";

export default class Cart {
constructor(page) {
this.page = page;
}

async addStandardItemToCart() {
await this.page.goto('./affirm-water-bottle.html');
await this.page.getByRole('button', { name: 'Add to Cart'}).first().click();
await expect(this.page.getByText(/You added [A-Za-z0-9 ]+ to your shopping cart/i)).toBeVisible();
}
}
17 changes: 17 additions & 0 deletions Test/End-2-End/Components/PaypalPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

export default class PaypalPopup {
constructor(popup) {
this.popup = popup;
}

async acceptPayment() {
await this.popup.getByPlaceholder('Email').fill('[email protected]');
if(await this.popup.getByRole('button', { name: 'Next' }).isVisible()) {
await this.popup.getByRole('button', {name: 'Next'}).click();
}
await this.popup.getByPlaceholder('Password').fill('h5Hc/b8M');
await this.popup.getByRole('button', { name: 'Log In' }).click();

await this.popup.getByTestId('submit-button-initial').click();
}
}
9 changes: 3 additions & 6 deletions Test/End-2-End/Pages/VisitCheckoutPayment.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import {expect} from "@playwright/test";
import Cart from "../Components/Cart";

export default class VisitCheckoutPayment {
constructor(page) {
this.page = page;
}

async visit() {
await this.page.goto('/');
await new Cart(this.page).addStandardItemToCart();

await this.page.getByRole('button', { name: 'Add to Cart Aim Analog Watch' }).click();

await expect(this.page.getByRole('button', { name: 'Toggle minicart, You have 1 product in your cart.'})).toBeVisible();

await this.page.goto('/checkout');
await this.page.goto('./checkout');

await this.page.getByLabel('Email address', { exact: true }).fill('[email protected]');
await this.page.getByLabel('First name').fill('John');
Expand Down
36 changes: 10 additions & 26 deletions Test/End-2-End/card-inline.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ test('Can place an order using the inline credit card', async ({ page }) => {

await page.getByLabel('Pay by Card').click();

await page.waitForRequest(
request => request.url().includes('magewire/post/livewire/message/checkout.payment.method.rvvup.card-processor') && request.method() === 'POST'
);

await visitCheckoutPayment.loadersShouldBeHidden();

// Credit card form
Expand All @@ -21,9 +17,16 @@ test('Can place an order using the inline credit card', async ({ page }) => {

await visitCheckoutPayment.loadersShouldBeHidden();

// OTP form
await page.frameLocator('#Cardinal-CCA-IFrame').getByPlaceholder('Enter Code Here').fill('1234');
await page.frameLocator('#Cardinal-CCA-IFrame').getByPlaceholder('Enter Code Here').press('Enter');
// OTP form (3DS) does not always show.
const frame = page.frameLocator('#Cardinal-CCA-IFrame');
try {
const element = frame.getByPlaceholder('Enter Code Here');
await element.waitFor({ state: 'visible', timeout: 10000 });
await element.fill('1234');
await element.press('Enter');
} catch (error) {
console.log('3DS form not found, so skipping it.');
}

await page.waitForURL("**/checkout/onepage/success/");

Expand All @@ -46,22 +49,3 @@ test('The validation prevents placing an order with invalid card details', async

await expect(page.frameLocator('iframe[name="st-expiration-date-iframe"]').getByText('Field is required')).toBeVisible();
});

test('Can switch between payment methods', async ({ page }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();

// Switch to card
await page.getByLabel('Pay by Card').click();
await visitCheckoutPayment.loadersShouldBeHidden();
await expect(page.locator('#rvvup-card-form')).toBeVisible();

// Switch to Check / Money order
await page.getByLabel('Check / Money order').click();
await visitCheckoutPayment.loadersShouldBeHidden();

// Switch back to card
await page.getByLabel('Pay by Card').click();
await visitCheckoutPayment.loadersShouldBeHidden();
await expect(page.locator('#rvvup-card-form')).toBeVisible();
});
3 changes: 2 additions & 1 deletion Test/End-2-End/card-modal.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { test, expect } from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";

test('Can place an order using the credit card modal', async ({ page, browser }) => {
// This test is dependent on test store configuration, if they are using modal model. Rvvup supports inline by default.s
test.skip('Can place an order using the credit card modal', async ({ page, browser }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();

Expand Down
9 changes: 3 additions & 6 deletions Test/End-2-End/clearpay.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test, expect } from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";
import Cart from "./Components/Cart";

// This test is quite far, but the Clearpay modal is quite a bit flakey. It sometimes works, sometimes doesn't.
test.skip('Can place an order', async ({ page, browser }) => {
Expand Down Expand Up @@ -45,7 +46,7 @@ test.skip('Can place an order', async ({ page, browser }) => {
});

test('Renders the Clearpay on the product page', async ({ page }) => {
await page.goto('/aim-analog-watch.html');
await page.goto('./joust-duffle-bag.html');

await expect(page.locator('.afterpay-modal-overlay')).toBeHidden();

Expand All @@ -56,11 +57,7 @@ test('Renders the Clearpay on the product page', async ({ page }) => {
});

test('Renders the Clearpay widget in the checkout', async ({ page }) => {
await page.goto('/');

await page.getByRole('button', { name: 'Add to Cart Aim Analog Watch' }).click();

await expect(page.getByRole('button', { name: 'Toggle minicart, You have 1 product in your cart.'})).toBeVisible();
await new Cart(page).addStandardItemToCart();

await page.goto('/checkout/cart');

Expand Down
34 changes: 34 additions & 0 deletions Test/End-2-End/different_shipping_and_billing_address.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { test, expect } from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";

test('Can place an order using different billing and shipping address', async ({ page, browser }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();
await page.getByLabel('My billing and shipping address are the same').setChecked(false);

await page.getByLabel('First name').fill('Liam');
await page.getByLabel('Last name').fill('Fox');
await page.getByLabel('Street address').fill('123 Small St');
await page.getByLabel('Form Field').fill('2nd Line');
await page.getByLabel('City').fill('Derby');
await page.getByLabel('Country').selectOption('United Kingdom');
await page.getByLabel('ZIP').fill('SW1B 1BB');
await page.getByLabel('Phone number').fill('+447599999999');

await page.getByLabel('Pay by Bank').click();

await page.getByRole('button', { name: 'Place order' }).click();

// Credit card form
const frame = page.frameLocator('iframe.rvvup-modal');
await frame.getByLabel('Mock Bank').click();
await frame.getByRole('button', { name: 'Log in on this device' }).click();

await page.waitForURL("**/checkout/onepage/success/");

await expect(page.getByRole('heading', { name: 'Thank you for your purchase!' })).toBeVisible();

const warningMessage = await page.$eval('.message.warning', el => el.textContent);
expect(warningMessage).toContain('Your payment is being processed and is pending confirmation. You will receive an email confirmation when the payment is confirmed.');
});

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { test, expect } from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";

test('Can place an order using Yapily', async ({ page, browser }) => {
test('Can place an order using pay by bank', async ({ page, browser }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();

Expand Down
43 changes: 15 additions & 28 deletions Test/End-2-End/paypal.spec.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import { test, expect } from '@playwright/test';
import {expect, test} from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";
import PaypalPopup from "./Components/PaypalPopup";

test('Can place an order using PayPal', async ({ page, browser }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();

await page.getByLabel('PayPal').click();
await page.getByLabel('PayPal', { exact: true }).click();

await expect(page.locator('#rvvup-paypal-button-container')).toBeVisible();
await page.waitForTimeout(2000);

page.on('popup', async popup => {
await popup.waitForLoadState();

await popup.getByPlaceholder('Email or mobile number').fill('[email protected]');
await popup.getByPlaceholder('Password').fill('h5Hc/b8M');

await popup.getByRole('button', { name: 'Log In' }).click();
await popup.getByRole('button', { name: 'Complete Purchase' }).click();
});

const paypalFrame = page.frameLocator('#rvvup-paypal-button-container iframe:first-of-type')
const popupPromise = page.waitForEvent('popup');
const paypalFrame = page.frameLocator('#rvvup-paypal-button-container iframe').first();
await paypalFrame.getByRole('link', { name: 'PayPal' }).click();

await new PaypalPopup(await popupPromise).acceptPayment();

await expect(page.locator('#payment-method-view-rvvup_PAYPAL'))
.not.toContainText('You are currently paying with PayPal. If you want to cancel this process');
await expect(page.frameLocator('#rvvup-modal iframe').getByText("Payment being processed")).toBeVisible();

await page.waitForURL("**/checkout/onepage/success/");

Expand All @@ -33,30 +29,20 @@ test('Can place an order using PayPal', async ({ page, browser }) => {
test('Can place an order from the product page using PayPal', async ({ page }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);

await page.goto('/aim-analog-watch.html');

page.on('popup', async popup => {
await popup.waitForLoadState();

await popup.getByPlaceholder('Email or mobile number').fill('[email protected]');
await popup.getByRole('button', { name: 'Next' }).click();

await popup.getByPlaceholder('Password').fill('h5Hc/b8M');
await popup.getByRole('button', { name: 'Log In' }).click();

await popup.getByRole('button', { name: 'Continue to review order' }).click();
});
await page.goto('./joust-duffle-bag.html');

const paypalFrame = page.frameLocator('.rvvup-paypal-express-button-container iframe:first-of-type')
const popupPromise = page.waitForEvent('popup');
const paypalFrame = page.frameLocator('.rvvup-paypal-express-button-container iframe').first();
await paypalFrame.getByRole('link', { name: 'PayPal' }).click();
await new PaypalPopup(await popupPromise).acceptPayment();

await page.waitForURL("**/checkout/");

await page.getByLabel('Phone number').fill('+447500000000');

await page.getByLabel('Fixed').click();

visitCheckoutPayment.loadersShouldBeHidden();
await visitCheckoutPayment.loadersShouldBeHidden();

await page.getByRole('button', { name: 'Proceed to review & payments' }).click();

Expand All @@ -69,6 +55,7 @@ test('Can place an order from the product page using PayPal', async ({ page }) =
await expect(children.length).toBe(1);

await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.frameLocator('#rvvup-modal iframe').getByText("Payment being processed")).toBeVisible();
await page.waitForURL("**/checkout/onepage/success/");
await expect(page.getByRole('heading', { name: 'Thank you for your purchase!' })).toBeVisible();
});
25 changes: 25 additions & 0 deletions Test/End-2-End/switch_payment_methods.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { test, expect } from '@playwright/test';
import VisitCheckoutPayment from "./Pages/VisitCheckoutPayment";

test('Can switch between payment methods', async ({ page }) => {
const visitCheckoutPayment = new VisitCheckoutPayment(page);
await visitCheckoutPayment.visit();

// Switch to card
await page.getByLabel('Pay by Card').click();
await visitCheckoutPayment.loadersShouldBeHidden();
await expect(page.locator('#rvvup-paypal-button-container')).toBeHidden();
await expect(page.locator('#rvvup-card-form')).toBeVisible();

await page.getByLabel('PayPal', { exact: true }).click();
await visitCheckoutPayment.loadersShouldBeHidden();
await expect(page.locator('#rvvup-card-form')).toBeHidden();
await expect(page.locator('#rvvup-paypal-button-container')).toBeVisible();


// Switch back to card
await page.getByLabel('Pay by Card').click();
await visitCheckoutPayment.loadersShouldBeHidden();
await expect(page.locator('#rvvup-paypal-button-container')).toBeHidden();
await expect(page.locator('#rvvup-card-form')).toBeVisible();
});
Loading