Skip to content

Commit

Permalink
[FEATURE] Lancement et hauteur automatiques d'embed (PIX-13211)
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge committed Jul 8, 2024
2 parents 4b9972e + c998b81 commit f8741a5
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 28 deletions.
24 changes: 13 additions & 11 deletions mon-pix/app/components/challenge-embed-simulator.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@
></iframe>
</div>

<div class="embed__reboot">
<button
type="button"
class="link link--grey embed-reboot__content"
aria-label={{t "pages.challenge.embed-simulator.actions.reset-label"}}
{{on "click" this.rebootSimulator}}
>
<FaIcon @icon="rotate-right" class="embed-reboot-content__icon" />
{{t "pages.challenge.embed-simulator.actions.reset"}}
</button>
</div>
{{#if this.isSimulatorRebootable}}
<div class="embed__reboot">
<button
type="button"
class="link link--grey embed-reboot__content"
aria-label={{t "pages.challenge.embed-simulator.actions.reset-label"}}
{{on "click" this.rebootSimulator}}
>
<FaIcon @icon="rotate-right" class="embed-reboot-content__icon" />
{{t "pages.challenge.embed-simulator.actions.reset"}}
</button>
</div>
{{/if}}
</div>
</div>
89 changes: 75 additions & 14 deletions mon-pix/app/components/challenge-embed-simulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@ export default class ChallengeEmbedSimulator extends Component {
@tracked
isSimulatorLaunched = false;

@tracked
isSimulatorRebootable = true;

@tracked
embedHeight;

_embedMessageListener;

constructor(owner, args) {
super(owner, args);
this.embedHeight = args.embedDocument?.height;
}

get embedDocumentHeightStyle() {
if (this.args.embedDocument) {
return htmlSafe(`height: ${this.args.embedDocument.height}px`);
if (this.embedHeight) {
return htmlSafe(`height: ${this.embedHeight}px`);
}
return '';
}
Expand All @@ -33,25 +46,36 @@ export default class ChallengeEmbedSimulator extends Component {
};

iframe.addEventListener('load', loadListener);

thisComponent._embedMessageListener = ({ origin, data }) => {
if (!isEmbedAllowedOrigin(origin)) return;
if (isReadyMessage(data) && thisComponent.isSimulatorLaunched) {
iframe.contentWindow.postMessage('launch', '*');
iframe.focus();
}
if (isHeightMessage(data)) {
thisComponent.embedHeight = data.height + 20;
}
if (isAutoLaunchMessage(data)) {
thisComponent.launchSimulator();
thisComponent.isSimulatorRebootable = false;
}
};

window.addEventListener('message', thisComponent._embedMessageListener);
}

@action
launchSimulator(event) {
const iframe = this._getIframe(event);
launchSimulator() {
const iframe = this.iframe;
iframe.contentWindow.postMessage('launch', '*');
iframe.focus();
this.isSimulatorLaunched = true;
window.addEventListener('message', (e) => {
if (!isEmbedAllowedOrigin(e.origin)) return;
if (typeof e.data !== 'object' || e.data.from !== 'pix' || e.data.type !== 'ready') return;
iframe.contentWindow.postMessage('launch', '*');
iframe.focus();
});
}

@action
rebootSimulator(event) {
const iframe = this._getIframe(event);
rebootSimulator() {
const iframe = this.iframe;
const tmpSrc = iframe.src;

const loadListener = () => {
Expand All @@ -71,7 +95,44 @@ export default class ChallengeEmbedSimulator extends Component {
iframe.src = 'about:blank';
}

_getIframe(event) {
return event.currentTarget.parentElement.parentElement.querySelector('.embed__iframe');
willDestroy() {
super.willDestroy();
window.removeEventListener('message', this._embedMessageListener);
}

get iframe() {
return document.querySelector('.embed__iframe');
}
}

/**
* Checks if event is a "ready" message.
* @param {unknown} data
* @returns {boolean}
*/
function isReadyMessage(data) {
return isMessageType(data, 'ready');
}

/**
* Checks if event is a "height" message.
* @param {unknown} data
* @returns {data is { height: number }}
*/
function isHeightMessage(data) {
return isMessageType(data, 'height');
}

/**
* Checks if event is a "auto-launch" message.
* @param {unknown} data
* @returns {boolean}
*/
function isAutoLaunchMessage(data) {
return isMessageType(data, 'auto-launch');
}

function isMessageType(data, type) {
if (typeof data !== 'object' || data === null) return false;
return data.from === 'pix' && data.type === type;
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ module('Integration | Component | Challenge Embed Simulator', function (hooks) {
});

module('Embed simulator', function (hooks) {
let screen;

hooks.beforeEach(async function () {
// given
this.set('embedDocument', {
Expand All @@ -82,9 +84,7 @@ module('Integration | Component | Challenge Embed Simulator', function (hooks) {
});

// when
await render(hbs`<ChallengeEmbedSimulator @embedDocument={{this.embedDocument}} />`);

// then
screen = await render(hbs`<ChallengeEmbedSimulator @embedDocument={{this.embedDocument}} />`);
});

test('should have an height that is the one defined in the referential', function (assert) {
Expand All @@ -98,5 +98,34 @@ module('Integration | Component | Challenge Embed Simulator', function (hooks) {
test('should define a src attribute on the iframe element that is the one defined in the referential for field "Embed URL"', function (assert) {
assert.strictEqual(find('.embed__iframe').src, 'http://embed-simulator.url/');
});

module('when embed sends its height', function () {
test('should listen for embed height and resize iframe container', async function (assert) {
const event = new MessageEvent('message', {
data: { from: 'pix', type: 'height', height: 480 },
origin: 'https://epreuves.pix.fr',
});
window.dispatchEvent(event);

await new Promise((resolve) => setTimeout(resolve, 0));

assert.strictEqual(find('.embed__iframe').style.cssText, 'height: 500px;');
});
});

module('when embed auto launches', function () {
test('should not display launch button and reboot button', async function (assert) {
const event = new MessageEvent('message', {
data: { from: 'pix', type: 'auto-launch' },
origin: 'https://epreuves.pix.fr',
});
window.dispatchEvent(event);

await new Promise((resolve) => setTimeout(resolve, 0));

assert.dom(screen.queryByText(this.intl.t('pages.challenge.embed-simulator.actions.launch'))).doesNotExist();
assert.dom(screen.queryByText(this.intl.t('pages.challenge.embed-simulator.actions.reset'))).doesNotExist();
});
});
});
});

0 comments on commit f8741a5

Please sign in to comment.