-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix/v6 fixing sr panel regression for open invoices (#2611)
* Fixing srPanel regression for OpenInvoices (and adding e2e tests) * Improved comments on SRPanel error utils * Riverty e2e test passes * Also cherry-picked allowing forward slashes in address fields * Ensure that post code related SRPanel errors include the field label * Decoupling delivery address and billing address specifications, for SRPanel, in OpenInvoice.tsx * Added e2e test for incorrectly filled postal code * Added unit tests for OpenInvoice field mapping util * Removed unused import * When assessing error look for expected props, unique to an SFError c.f. instanceOf ValidationRuleResult. It's semantically more correct and plays better with unit tests * Added unit test for sortErrorsByLayout function in Errors/utils
- Loading branch information
Showing
18 changed files
with
596 additions
and
41 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
packages/e2e-playwright/app/src/pages/OpenInvoices/OpenInvoices.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<!DOCTYPE html> | ||
<html class="no-js" lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta http-equiv="x-ua-compatible" content="ie=edge" /> | ||
<title>Adyen Web | Open Invoices</title> | ||
<meta name="description" content="" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> | ||
</head> | ||
|
||
<body> | ||
<main> | ||
<div class="merchant-checkout__form"> | ||
<div id="openInvoicesContainer"> | ||
<div id="rivertyContainer"></div> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<script type="text/javascript"> | ||
window.htmlPages = <%= JSON.stringify(htmlWebpackPlugin.htmlPages) || '' %>; | ||
</script> | ||
</body> | ||
</html> |
28 changes: 28 additions & 0 deletions
28
packages/e2e-playwright/app/src/pages/OpenInvoices/OpenInvoices.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { AdyenCheckout, Riverty } from '@adyen/adyen-web'; | ||
import '@adyen/adyen-web/styles/adyen.css'; | ||
import { getPaymentMethods } from '../../services'; | ||
import { amount, shopperLocale, countryCode } from '../../services/commonConfig'; | ||
import { handleSubmit, handleAdditionalDetails, handleError } from '../../handlers'; | ||
import '../../style.scss'; | ||
|
||
const initCheckout = async () => { | ||
const paymentMethodsResponse = await getPaymentMethods({ amount, shopperLocale }); | ||
|
||
window.checkout = await AdyenCheckout({ | ||
amount, | ||
countryCode, | ||
clientKey: process.env.__CLIENT_KEY__, | ||
paymentMethodsResponse, | ||
locale: shopperLocale, | ||
environment: 'test', | ||
onSubmit: handleSubmit, | ||
onAdditionalDetails: handleAdditionalDetails, | ||
onError: handleError, | ||
showPayButton: true, | ||
...window.mainConfiguration | ||
}); | ||
|
||
window.riverty = new Riverty(checkout, window.rivertyConfig).mount('#rivertyContainer'); | ||
}; | ||
|
||
initCheckout(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Locator, Page } from '@playwright/test'; | ||
|
||
class OpenInvoices { | ||
readonly page: Page; | ||
|
||
readonly rootElement: Locator; | ||
readonly rootElementSelector: string; | ||
|
||
readonly riverty: Locator; | ||
readonly rivertyDeliveryAddressCheckbox: Locator; | ||
|
||
constructor(page: Page, rootElementSelector = '#openInvoicesContainer') { | ||
this.page = page; | ||
|
||
this.rootElement = page.locator(rootElementSelector); | ||
this.rootElementSelector = rootElementSelector; | ||
|
||
this.riverty = this.rootElement.locator('#rivertyContainer'); | ||
|
||
this.rivertyDeliveryAddressCheckbox = this.riverty | ||
.locator('.adyen-checkout__checkbox') | ||
.filter({ hasText: 'Specify a separate delivery address' }); | ||
} | ||
|
||
async isComponentVisible() { | ||
await this.rootElement.waitFor({ state: 'visible' }); | ||
} | ||
} | ||
|
||
export { OpenInvoices }; |
40 changes: 40 additions & 0 deletions
40
packages/e2e-playwright/pages/openInvoices/openInvoices.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { test as base, expect, Page } from '@playwright/test'; | ||
import { OpenInvoicesPage } from './openInvoices.page'; | ||
type Fixture = { | ||
openInvoicesPage: OpenInvoicesPage; | ||
openInvoicesPage_riverty: OpenInvoicesPage; | ||
}; | ||
|
||
const test = base.extend<Fixture>({ | ||
openInvoicesPage: async ({ page }, use) => { | ||
await useOpenInvoicesPage(page, use); | ||
}, | ||
|
||
openInvoicesPage_riverty: async ({ page }, use) => { | ||
const mainConfig = JSON.stringify({ | ||
srConfig: { | ||
showPanel: true | ||
} | ||
}); | ||
await page.addInitScript({ | ||
content: `window.mainConfiguration = ${mainConfig}` | ||
}); | ||
|
||
const rivertyConfig = JSON.stringify({ | ||
countryCode: 'DE' | ||
}); | ||
await page.addInitScript({ | ||
content: `window.rivertyConfig = ${rivertyConfig}` | ||
}); | ||
|
||
await useOpenInvoicesPage(page, use); | ||
} | ||
}); | ||
|
||
const useOpenInvoicesPage = async (page: Page, use: any, PageType = OpenInvoicesPage) => { | ||
const openInvoicesPage = new PageType(page); | ||
await openInvoicesPage.goto(); | ||
await use(openInvoicesPage); | ||
}; | ||
|
||
export { test, expect }; |
25 changes: 25 additions & 0 deletions
25
packages/e2e-playwright/pages/openInvoices/openInvoices.page.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Locator, Page } from '@playwright/test'; | ||
import { OpenInvoices } from '../../models/openInvoices'; | ||
|
||
class OpenInvoicesPage { | ||
readonly page: Page; | ||
|
||
readonly openInvoices: OpenInvoices; | ||
readonly payButton: Locator; | ||
|
||
constructor(page: Page) { | ||
this.page = page; | ||
this.openInvoices = new OpenInvoices(page); | ||
this.payButton = page.getByRole('button', { name: /Confirm/i }); | ||
} | ||
|
||
async goto(url?: string) { | ||
await this.page.goto('http://localhost:3024/openinvoices'); | ||
} | ||
|
||
async pay() { | ||
await this.payButton.click(); | ||
} | ||
} | ||
|
||
export { OpenInvoicesPage }; |
113 changes: 113 additions & 0 deletions
113
packages/e2e-playwright/tests/openInvoices/riverty.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { test, expect } from '../../pages/openInvoices/openInvoices.fixture'; | ||
|
||
import LANG from '../../../lib/src/language/locales/en-US.json'; | ||
import { USER_TYPE_DELAY } from '../utils/constants'; | ||
|
||
const REQUIRED_FIELD = LANG['field.error.required'].replace('%{label}', ''); | ||
|
||
const BILLING_ADDRESS = LANG['billingAddress']; | ||
const DELIVERY_ADDRESS = LANG['deliveryAddress']; | ||
|
||
const EMPTY_POST_CODE = `${REQUIRED_FIELD}${BILLING_ADDRESS} ${LANG['postalCode']}`; | ||
const INVALID_FORMAT_EXPECTS = LANG['invalid.format.expects'].replace(/%{label}|%{format}/g, ''); | ||
const INVALID_POST_CODE = `${BILLING_ADDRESS} ${LANG['postalCode']}${INVALID_FORMAT_EXPECTS}99999`; | ||
|
||
const expectedSRPanelTexts = [ | ||
`${LANG['firstName.invalid']}`, | ||
`${LANG['lastName.invalid']}`, | ||
`${REQUIRED_FIELD}${LANG['dateOfBirth']}`, | ||
`${REQUIRED_FIELD}${LANG['shopperEmail']}`, | ||
`${REQUIRED_FIELD}${LANG['telephoneNumber']}`, | ||
`${REQUIRED_FIELD}${BILLING_ADDRESS} ${LANG['street']}`, | ||
`${REQUIRED_FIELD}${BILLING_ADDRESS} ${LANG['houseNumberOrName']}`, | ||
EMPTY_POST_CODE, | ||
`${REQUIRED_FIELD}${BILLING_ADDRESS} ${LANG['city']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['deliveryAddress.firstName']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['deliveryAddress.lastName']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['street']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['houseNumberOrName']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['postalCode']}`, | ||
`${REQUIRED_FIELD}${DELIVERY_ADDRESS} ${LANG['city']}`, | ||
`${LANG['consent.checkbox.invalid']}` | ||
]; | ||
|
||
test.describe('Test Riverty Component', () => { | ||
test('#1 Test how Riverty component handles SRPanel messages', async ({ openInvoicesPage_riverty }) => { | ||
const { openInvoices, page } = openInvoicesPage_riverty; | ||
|
||
await openInvoices.isComponentVisible(); | ||
|
||
await openInvoices.rivertyDeliveryAddressCheckbox.click(); | ||
|
||
await openInvoicesPage_riverty.pay(); | ||
|
||
// Need to wait so that the expected elements can be found by locator.allInnerTexts | ||
await page.waitForTimeout(100); | ||
|
||
// Inspect SRPanel errors: all expected errors, in the expected order | ||
await page | ||
.locator('.adyen-checkout-sr-panel__msg') | ||
.allInnerTexts() | ||
.then(retrievedSRPanelTexts => { | ||
// check we have srPanel errors | ||
expect(retrievedSRPanelTexts.length).toBeGreaterThan(0); | ||
|
||
// check individual messages | ||
retrievedSRPanelTexts.forEach((retrievedText, index) => { | ||
// KEEP - handy for debugging test | ||
// console.log('\n### riverty.spec:::: retrievedText', retrievedText); | ||
// console.log('### riverty.spec:::: expectedTexts', expectedSRPanelTexts[index]); | ||
|
||
expect(retrievedText).toContain(expectedSRPanelTexts[index]); | ||
}); | ||
}); | ||
|
||
// KEEP - handy for debugging test | ||
// await expect(page.getByText('Enter your first name-sr', { exact: true })).toBeVisible(); | ||
}); | ||
|
||
test('#2 Test how Riverty component handles SRPanel messages, specifically a postal code with an invalid format', async ({ | ||
openInvoicesPage_riverty | ||
}) => { | ||
const { openInvoices, page } = openInvoicesPage_riverty; | ||
|
||
await openInvoices.isComponentVisible(); | ||
|
||
await openInvoices.rivertyDeliveryAddressCheckbox.click(); | ||
|
||
expectedSRPanelTexts.splice(7, 1, INVALID_POST_CODE); | ||
|
||
await openInvoices.riverty | ||
.getByRole('group', { name: 'Billing address' }) | ||
.getByLabel('Postal code') | ||
// .locator('.adyen-checkout__field--postalCode .adyen-checkout__input--postalCode') | ||
.type('3', { delay: USER_TYPE_DELAY }); | ||
|
||
await openInvoicesPage_riverty.pay(); // first click need to trigger blur event on postCode field | ||
await openInvoicesPage_riverty.pay(); // second click to trigger validation | ||
|
||
// Need to wait so that the expected elements can be found by locator.allInnerTexts | ||
await page.waitForTimeout(100); | ||
|
||
// Inspect SRPanel errors: all expected errors, in the expected order | ||
await page | ||
.locator('.adyen-checkout-sr-panel__msg') | ||
.allInnerTexts() | ||
.then(retrievedSRPanelTexts => { | ||
// check we have srPanel errors | ||
expect(retrievedSRPanelTexts.length).toBeGreaterThan(0); | ||
|
||
// check individual messages | ||
retrievedSRPanelTexts.forEach((retrievedText, index) => { | ||
// KEEP - handy for debugging test | ||
// console.log('\n### riverty.spec:::: retrievedText', retrievedText); | ||
// console.log('### riverty.spec:::: expectedTexts', expectedSRPanelTexts[index]); | ||
|
||
expect(retrievedText).toContain(expectedSRPanelTexts[index]); | ||
}); | ||
}); | ||
|
||
// Restore array to start state | ||
expectedSRPanelTexts.splice(7, 1, EMPTY_POST_CODE); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.