Skip to content

Commit

Permalink
[TECH] Améliorer la gestion d'erreurs lors du téléchargement des résu…
Browse files Browse the repository at this point in the history
…ltats de session sur Pix App (PIX-15587).

 #10743
  • Loading branch information
pix-service-auto-merge authored Dec 6, 2024
2 parents e697a80 + 6360d61 commit 0b25a5a
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 53 deletions.
4 changes: 4 additions & 0 deletions api/src/shared/application/error-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,10 @@ function _mapToHttpError(error) {
return new HttpErrors.BadRequestError(error.message, 'SENDING_EMAIL_TO_INVALID_EMAIL_ADDRESS', error.meta);
}

if (error instanceof DomainErrors.InvalidSessionResultTokenError) {
return new HttpErrors.BadRequestError(error.message, error.code);
}

return new HttpErrors.BaseHttpError(error.message);
}

Expand Down
7 changes: 5 additions & 2 deletions api/src/shared/domain/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,11 @@ class InvalidResultRecipientTokenError extends DomainError {
}

class InvalidSessionResultTokenError extends DomainError {
constructor(message = 'Le token de récupération des résultats de la session de certification est invalide.') {
super(message);
constructor(
message = 'The token used to retrieve the results of the certification session is invalid.',
code = 'INVALID_SESSION_RESULT_TOKEN',
) {
super(message, code);
}
}

Expand Down
11 changes: 11 additions & 0 deletions api/tests/shared/integration/application/error-manager_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ describe('Integration | API | Controller Error', function () {
);
expect(responseCode(response)).to.equal('SESSION_WITHOUT_STARTED_CERTIFICATION');
});

it('responds Bad Request when a InvalidSessionResultTokenError error occurs', async function () {
routeHandler.throws(new DomainErrors.InvalidSessionResultTokenError());
const response = await server.requestObject(request);

expect(response.statusCode).to.equal(BAD_REQUEST_ERROR);
expect(responseDetail(response)).to.equal(
'The token used to retrieve the results of the certification session is invalid.',
);
expect(responseCode(response)).to.equal('INVALID_SESSION_RESULT_TOKEN');
});
});

context('403 Forbidden', function () {
Expand Down
17 changes: 11 additions & 6 deletions mon-pix/app/components/download-session-results.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import ENV from 'mon-pix/config/environment';
import PixWindow from 'mon-pix/utils/pix-window';

export default class DownloadSessionResults extends Component {
@tracked showErrorMessage = false;
@tracked errorMessage = null;
@service fileSaver;
@service intl;

@action
async downloadSessionResults(event) {
event.preventDefault();
this.showErrorMessage = false;
this.errorMessage = null;

try {
const token = decodeURIComponent(PixWindow.getLocationHash().slice(1));
Expand All @@ -28,8 +29,12 @@ export default class DownloadSessionResults extends Component {
body: { token },
},
});
} catch {
this.showErrorMessage = true;
} catch (error) {
if (error.code === 'INVALID_SESSION_RESULT_TOKEN') {
this.errorMessage = this.intl.t('pages.download-session-results.errors.invalid-token');
} else {
this.errorMessage = this.intl.t('common.error');
}
}
}

Expand All @@ -46,9 +51,9 @@ export default class DownloadSessionResults extends Component {
{{t "pages.download-session-results.button.label"}}
</PixButton>

{{#if this.showErrorMessage}}
{{#if this.errorMessage}}
<PixMessage @type="error" class="form__error">
{{t "pages.download-session-results.errors.expiration"}}
{{this.errorMessage}}
</PixMessage>
{{/if}}
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
<p class="attestation__error-message">{{this.attestationDownloadErrorMessage}}</p>
{{/if}}
</div>
<hr />
<div class="verification-code">
<h2 class="verification-code__title">
{{t "pages.certificate.verification-code.title"}}
Expand Down
4 changes: 2 additions & 2 deletions mon-pix/app/components/user-certifications-detail-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export default class UserCertificationsDetailHeader extends Component {
const token = this.session.data.authenticated.access_token;
try {
await this.fileSaver.save({ url, token });
} catch (error) {
this.attestationDownloadErrorMessage = error.message;
} catch (_) {
this.attestationDownloadErrorMessage = this.intl.t('common.error');
}
}
}
2 changes: 1 addition & 1 deletion mon-pix/app/services/file-saver.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default class FileSaver extends Service {

if (!response.ok) {
const payload = await response.json();
throw new Error(payload?.errors[0]?.detail);
throw payload?.errors[0];
}

if (response.headers && response.headers.get('Content-Disposition')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,34 +72,31 @@
}

.attestation-and-verification-code {
padding: 16px 20px;
max-width: 100%;
padding: var(--pix-spacing-4x) var(--pix-spacing-6x);
background-color: var(--pix-neutral-20);
border-radius: 8px;

@include device-is('desktop') {
max-width: calc(var(--pix-spacing-12x) * 6);
}

.attestation {
margin: auto;
font-size: 0.875rem;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: var(--pix-spacing-6x);
text-align: center;

button {
max-width: 250px;
padding: 14px 20px;
}

&__error-message {
max-width: 250px;
margin-top: 15px;
@extend %pix-body-s;

margin-top: var(--pix-spacing-4x);
color: var(--pix-error-500);
}
}

hr {
margin: 24px 0;
border: 1px solid var(--pix-neutral-20);
}

.verification-code {
max-width: 250px;
margin: auto;
color: var(--pix-neutral-900);
letter-spacing: 0;
Expand Down Expand Up @@ -157,10 +154,5 @@
@include device-is('desktop') {
flex-grow: 0;
margin-left: auto;

.verification-code,
.attestation {
margin: 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ module('Integration | Component | download-session-results', function (hooks) {
assert.dom(screen.getByRole('button', { name: t('pages.download-session-results.button.label') })).exists();
});

test('should display the expiration error message', async function (assert) {
test('should display the invalid token error message', async function (assert) {
// given
fileSaver.save.rejects();
fileSaver.save.rejects({ status: '400', code: 'INVALID_SESSION_RESULT_TOKEN' });

// when
const screen = await render(hbs`<DownloadSessionResults />`);
const downloadButton = screen.getByRole('button', { name: t('pages.download-session-results.button.label') });
await click(downloadButton);

// then
assert.dom(screen.getByText(t('pages.download-session-results.errors.expiration'))).exists();
assert.dom(screen.getByText(t('pages.download-session-results.errors.invalid-token'))).exists();
});

test('should trigger the download', async function (assert) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ module('Integration | Component | user certifications detail header', function (
});

module('when there is an error during the download of the attestation', function () {
test('should show the error message', async function (assert) {
test('should show the common error message', async function (assert) {
// given
const fileSaverSaveStub = sinon.stub();

Expand Down Expand Up @@ -366,7 +366,7 @@ module('Integration | Component | user certifications detail header', function (
await click(screen.getByRole('button', { name: 'Télécharger mon attestation' }));

// then
assert.ok(screen.getByText('an error message'));
assert.ok(screen.getByText('Une erreur est survenue. Veuillez recommencer ou contacter le support.'));
});
});
});
25 changes: 12 additions & 13 deletions mon-pix/tests/unit/services/file-saver-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,24 @@ module('Unit | Service | file-saver', function (hooks) {
});

module('when the response is an error', function () {
test('should throw an error with the response error detail as message', async function (assert) {
test('should throw', async function (assert) {
// given
jsonStub.resolves({ errors: [{ detail: 'the error message' }] });
const response = { ok: false, json: jsonStub };
fetchStub = sinon.stub().resolves(response);

// when
try {
await fileSaver.save({
url,
fileName: defaultFileName,
token,
fetcher: fetchStub,
downloadFileForIEBrowser: downloadFileForIEBrowserStub,
downloadFileForModernBrowsers: downloadFileForModernBrowsersStub,
});
} catch (error) {
assert.strictEqual(error.message, 'the error message');
}
const promise = fileSaver.save({
url,
fileName: defaultFileName,
token,
fetcher: fetchStub,
downloadFileForIEBrowser: downloadFileForIEBrowserStub,
downloadFileForModernBrowsers: downloadFileForModernBrowsersStub,
});

// then
assert.rejects(promise);
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@
"label": "Download results"
},
"errors": {
"expiration": "The session results download link has expired."
"invalid-token": "The session results download link is invalid."
},
"title": "Download session results"
},
Expand Down
2 changes: 1 addition & 1 deletion mon-pix/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,7 @@
"label": "Télécharger les résultats"
},
"errors": {
"expiration": "Le lien de téléchargement des résultats de session a expiré."
"invalid-token": "Le lien de téléchargement des résultats de session est invalide."
},
"title": "Télécharger les résultats de session"
},
Expand Down

0 comments on commit 0b25a5a

Please sign in to comment.