mirror of
https://github.com/jlengrand/adyen-web.git
synced 2026-03-10 08:01:22 +00:00
Add 'redirectFromTop' config prop to allow top level redirect when Checkout loaded in an iframe (#2325)
* Add 'redirectFromTop' config prop to allow top level redirect when Checkout loaded in an iframe * Changed 'redirectFromTop' to 'redirectFromTopWhenInIframe' to make its function clearer
This commit is contained in:
5
.changeset/forty-badgers-bow.md
Normal file
5
.changeset/forty-badgers-bow.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@adyen/adyen-web': minor
|
||||
---
|
||||
|
||||
Add 'redirectFromTopWhenInIframe' config prop to allow top level redirect when Checkout loaded in an iframe
|
||||
@@ -3,6 +3,12 @@ import { h } from 'preact';
|
||||
import Redirect from './Redirect';
|
||||
import RedirectShopper from './components/RedirectShopper';
|
||||
|
||||
jest.mock('../../utils/detectInIframe', () => {
|
||||
return jest.fn().mockImplementation(() => {
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Redirect', () => {
|
||||
describe('isValid', () => {
|
||||
test('Is always valid', () => {
|
||||
@@ -19,6 +25,17 @@ describe('Redirect', () => {
|
||||
|
||||
expect(wrapper.find('form')).toHaveLength(1);
|
||||
expect(wrapper.find('form').prop('action')).toBe('http://www.adyen.com');
|
||||
expect(wrapper.find('form').prop('target')).toBe(undefined);
|
||||
setTimeout(() => expect(window.HTMLFormElement.prototype.submit).toHaveBeenCalled(), 0);
|
||||
});
|
||||
|
||||
test('Accepts a POST redirect status, setting target to _top, when the config prop tells it to', () => {
|
||||
window.HTMLFormElement.prototype.submit = jest.fn();
|
||||
|
||||
const wrapper = mount(<RedirectShopper url="http://www.adyen.com" method="POST" data={{}} redirectFromTopWhenInIframe={true} />);
|
||||
|
||||
expect(wrapper.find('form')).toHaveLength(1);
|
||||
expect(wrapper.find('form').prop('target')).toBe('_top');
|
||||
setTimeout(() => expect(window.HTMLFormElement.prototype.submit).toHaveBeenCalled(), 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Component, h } from 'preact';
|
||||
import detectInIframe from '../../../../utils/detectInIframe';
|
||||
|
||||
interface RedirectShopperProps {
|
||||
beforeRedirect: (resolve, reject, url) => Promise<void>;
|
||||
url: string;
|
||||
method: 'GET' | 'POST';
|
||||
data?: any;
|
||||
redirectFromTopWhenInIframe?: boolean;
|
||||
}
|
||||
|
||||
class RedirectShopper extends Component<RedirectShopperProps> {
|
||||
@@ -19,7 +21,12 @@ class RedirectShopper extends Component<RedirectShopperProps> {
|
||||
if (this.postForm) {
|
||||
this.postForm.submit();
|
||||
} else {
|
||||
window.location.assign(this.props.url);
|
||||
if (this.props.redirectFromTopWhenInIframe && detectInIframe()) {
|
||||
// if in an iframe and the config prop allows it - try to redirect from the top level window
|
||||
window.top.location.assign?.(this.props.url);
|
||||
} else {
|
||||
window.location.assign(this.props.url);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,6 +51,7 @@ class RedirectShopper extends Component<RedirectShopperProps> {
|
||||
ref={ref => {
|
||||
this.postForm = ref;
|
||||
}}
|
||||
{...(this.props.redirectFromTopWhenInIframe && detectInIframe() && { target: '_top' })}
|
||||
>
|
||||
{Object.keys(data).map(key => (
|
||||
<input type="hidden" name={key} key={key} value={data[key]} />
|
||||
|
||||
@@ -15,6 +15,7 @@ export const GENERIC_OPTIONS = [
|
||||
'session',
|
||||
'clientKey',
|
||||
'showPayButton',
|
||||
'redirectFromTopWhenInIframe',
|
||||
'installmentOptions',
|
||||
|
||||
// Events
|
||||
|
||||
2
packages/lib/src/utils/detectInIframe.ts
Normal file
2
packages/lib/src/utils/detectInIframe.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Returns true if the page is being run in an iframe
|
||||
export default () => window.location !== window.parent.location;
|
||||
Reference in New Issue
Block a user