-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BUGFIX] Utiliser la locale sur la demande de reset de password (PIX-…
- Loading branch information
Showing
8 changed files
with
225 additions
and
37 deletions.
There are no files selected for viewing
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
15 changes: 15 additions & 0 deletions
15
mon-pix/app/services/request-manager-handlers/app-info-handler.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,15 @@ | ||
import ENV from 'mon-pix/config/environment'; | ||
|
||
/** | ||
* Request manager handler adding application info in request headers. | ||
* See: https://github.com/emberjs/data/blob/main/guides/requests/examples/1-auth.md | ||
*/ | ||
export default class AppInfoHandler { | ||
request(context, next) { | ||
const headers = new Headers(context.request.headers); | ||
|
||
headers.append('X-App-Version', ENV.APP.APP_VERSION); | ||
|
||
return next(Object.assign({}, context.request, { headers })); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
mon-pix/app/services/request-manager-handlers/auth-handler.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,20 @@ | ||
import { inject as service } from '@ember/service'; | ||
|
||
/** | ||
* Request manager handler adding authentication credentials in the request. | ||
* See: https://github.com/emberjs/data/blob/main/guides/requests/examples/1-auth.md | ||
*/ | ||
export default class AuthHandler { | ||
@service session; | ||
|
||
request(context, next) { | ||
const headers = new Headers(context.request.headers); | ||
|
||
const { isAuthenticated, data } = this.session; | ||
if (isAuthenticated) { | ||
headers.append('Authorization', `Bearer ${data.authenticated.access_token}`); | ||
} | ||
|
||
return next(Object.assign({}, context.request, { headers })); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
mon-pix/app/services/request-manager-handlers/json-handler.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,14 @@ | ||
/** | ||
* Request manager handler to manage JSON request. | ||
* See: https://github.com/emberjs/data/blob/main/guides/requests/examples/1-auth.md | ||
*/ | ||
export default class JsonHandler { | ||
request(context, next) { | ||
const headers = new Headers(context.request.headers); | ||
|
||
headers.append('Accept', 'application/json'); | ||
headers.append('Content-Type', 'application/json'); | ||
|
||
return next(Object.assign({}, context.request, { headers })); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
mon-pix/app/services/request-manager-handlers/locale-handler.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,25 @@ | ||
import { inject as service } from '@ember/service'; | ||
|
||
const FRENCH_FRANCE_LOCALE = 'fr-fr'; | ||
|
||
/** | ||
* Request manager handler adding user locale in request header. | ||
* See: https://github.com/emberjs/data/blob/main/guides/requests/examples/1-auth.md | ||
*/ | ||
export default class LocaleHandler { | ||
@service currentDomain; | ||
@service intl; | ||
|
||
request(context, next) { | ||
const headers = new Headers(context.request.headers); | ||
|
||
headers.append('Accept-Language', this._locale); | ||
|
||
return next(Object.assign({}, context.request, { headers })); | ||
} | ||
|
||
get _locale() { | ||
if (this.currentDomain.isFranceDomain) return FRENCH_FRANCE_LOCALE; | ||
return this.intl.primaryLocale; | ||
} | ||
} |
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,32 @@ | ||
import { getOwner, setOwner } from '@ember/application'; | ||
import RequestManager from '@ember-data/request'; | ||
import Fetch from '@ember-data/request/fetch'; | ||
|
||
import AppInfoHandler from './request-manager-handlers/app-info-handler.js'; | ||
import AuthHandler from './request-manager-handlers/auth-handler.js'; | ||
import JsonHandler from './request-manager-handlers/json-handler.js'; | ||
import LocaleHandler from './request-manager-handlers/locale-handler.js'; | ||
|
||
/** | ||
* Request manager preconfigured for authenticated or not HTTP requests. | ||
* see: https://api.emberjs.com/ember-data/release/modules/@ember-data%2Frequest | ||
*/ | ||
export default class RequestManagerService extends RequestManager { | ||
constructor(createArgs) { | ||
super(createArgs); | ||
|
||
const authHandler = new AuthHandler(); | ||
setOwner(authHandler, getOwner(this)); | ||
|
||
const localHandler = new LocaleHandler(); | ||
setOwner(localHandler, getOwner(this)); | ||
|
||
const appInfoHandler = new AppInfoHandler(); | ||
setOwner(appInfoHandler, getOwner(this)); | ||
|
||
const jsonHandler = new JsonHandler(); | ||
setOwner(jsonHandler, getOwner(this)); | ||
|
||
this.use([authHandler, localHandler, appInfoHandler, jsonHandler, Fetch]); | ||
} | ||
} |
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 |
---|---|---|
|
@@ -21,6 +21,13 @@ const I18N_KEYS = { | |
module('Integration | Component | Authentication | PasswordResetDemand | password-reset-demand-form', function (hooks) { | ||
setupIntlRenderingTest(hooks); | ||
|
||
let requestManagerService; | ||
|
||
hooks.beforeEach(function () { | ||
requestManagerService = this.owner.lookup('service:requestManager'); | ||
sinon.stub(requestManagerService, 'request'); | ||
}); | ||
|
||
test('it displays all elements of component successfully', async function (assert) { | ||
// given | ||
const screen = await render(<template><PasswordResetDemandForm /></template>); | ||
|
@@ -78,11 +85,7 @@ module('Integration | Component | Authentication | PasswordResetDemand | passwor | |
module('when the password-reset-demand is successful', function () { | ||
test('it displays a "password reset demand received" info (without any error message)', async function (assert) { | ||
// given | ||
window.fetch.resolves( | ||
fetchMock({ | ||
status: 201, | ||
}), | ||
); | ||
requestManagerService.request.resolves({ response: { ok: true, status: 201 } }); | ||
|
||
const email = '[email protected]'; | ||
const locale = ENGLISH_INTERNATIONAL_LOCALE; | ||
|
@@ -127,14 +130,7 @@ module('Integration | Component | Authentication | PasswordResetDemand | passwor | |
module('when there is no corresponding user account', function () { | ||
test('it displays a "password reset demand received" info (without any error message to avoid email enumeration)', async function (assert) { | ||
// given | ||
window.fetch.resolves( | ||
fetchMock({ | ||
status: 404, | ||
body: { | ||
errors: [{ title: 'Not Found' }], | ||
}, | ||
}), | ||
); | ||
requestManagerService.request.rejects({ status: 404 }); | ||
|
||
const email = '[email protected]'; | ||
const screen = await render(<template><PasswordResetDemandForm /></template>); | ||
|
@@ -157,11 +153,7 @@ module('Integration | Component | Authentication | PasswordResetDemand | passwor | |
module('when there is an unknown error', function () { | ||
test('it displays an "unknown error" error message', async function (assert) { | ||
// given | ||
window.fetch.resolves( | ||
fetchMock({ | ||
status: 500, | ||
}), | ||
); | ||
requestManagerService.request.rejects({ status: 500 }); | ||
|
||
const email = '[email protected]'; | ||
const screen = await render(<template><PasswordResetDemandForm /></template>); | ||
|
@@ -195,12 +187,3 @@ module('Integration | Component | Authentication | PasswordResetDemand | passwor | |
}); | ||
}); | ||
}); | ||
|
||
function fetchMock({ body, status }) { | ||
return new window.Response(JSON.stringify(body), { | ||
status, | ||
headers: { | ||
'Content-type': 'application/json', | ||
}, | ||
}); | ||
} |
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,101 @@ | ||
import { setupTest } from 'ember-qunit'; | ||
import { module, test } from 'qunit'; | ||
import sinon from 'sinon'; | ||
|
||
module('Unit | Service | request-manager', function (hooks) { | ||
setupTest(hooks); | ||
let requestManagerService; | ||
let sessionService; | ||
let currentDomainService; | ||
let intlService; | ||
|
||
hooks.beforeEach(function () { | ||
sinon.stub(window, 'fetch'); | ||
|
||
requestManagerService = this.owner.lookup('service:requestManager'); | ||
|
||
sessionService = this.owner.lookup('service:session'); | ||
sinon.stub(sessionService, 'isAuthenticated').value(false); | ||
sinon.stub(sessionService, 'data').value(null); | ||
|
||
currentDomainService = this.owner.lookup('service:currentDomain'); | ||
sinon.stub(currentDomainService, 'isFranceDomain').value(false); | ||
|
||
intlService = this.owner.lookup('service:intl'); | ||
sinon.stub(intlService, 'primaryLocale').value('fr'); | ||
}); | ||
|
||
hooks.afterEach(function () { | ||
sinon.restore(); | ||
}); | ||
|
||
module('request()', function () { | ||
test('it requests successfully with default headers', async function (assert) { | ||
// given | ||
window.fetch.resolves(responseMock({ status: 200, data: { foo: 'bar' } })); | ||
|
||
// when | ||
const result = await requestManagerService.request({ url: '/test', method: 'GET' }); | ||
|
||
// then | ||
assert.strictEqual(result.response.status, 200); | ||
assert.deepEqual(result.content, { foo: 'bar' }); | ||
|
||
const [url, { headers }] = window.fetch.getCall(0).args; | ||
assert.strictEqual(url, '/test'); | ||
assert.strictEqual(headers.get('Accept-Language'), 'fr'); | ||
assert.strictEqual(headers.get('X-App-Version'), 'development'); | ||
assert.strictEqual(headers.get('Accept'), 'application/json'); | ||
assert.strictEqual(headers.get('Content-Type'), 'application/json'); | ||
}); | ||
|
||
module('when user is authenticated', function () { | ||
test('it sets the Authorization header with the access token', async function (assert) { | ||
// given | ||
window.fetch.resolves(responseMock({ status: 200, data: { foo: 'bar' } })); | ||
sinon.stub(sessionService, 'isAuthenticated').value(true); | ||
sinon.stub(sessionService, 'data').value({ authenticated: { access_token: 'baz' } }); | ||
|
||
// when | ||
await requestManagerService.request({ url: '/test', method: 'GET' }); | ||
|
||
// then | ||
const [url, { headers }] = window.fetch.getCall(0).args; | ||
assert.strictEqual(url, '/test'); | ||
assert.strictEqual(headers.get('Authorization'), 'Bearer baz'); | ||
}); | ||
}); | ||
|
||
module('when it is on France domain', function () { | ||
test('it sets the header Accept-Language to fr-fr', async function (assert) { | ||
// given | ||
window.fetch.resolves(responseMock({ status: 200, data: { foo: 'bar' } })); | ||
sinon.stub(currentDomainService, 'isFranceDomain').value(true); | ||
|
||
// when | ||
await requestManagerService.request({ url: '/test', method: 'GET' }); | ||
|
||
// then | ||
const [url, { headers }] = window.fetch.getCall(0).args; | ||
assert.strictEqual(url, '/test'); | ||
assert.strictEqual(headers.get('Accept-Language'), 'fr-fr'); | ||
}); | ||
}); | ||
|
||
module('when an error occured on HTTP call', function () { | ||
test('it throws an exception with error details', async function (assert) { | ||
// given | ||
window.fetch.resolves(responseMock({ status: 400, data: { error: 'KO' } })); | ||
|
||
// when | ||
assert.rejects(requestManagerService.request({ url: '/test', method: 'GET' }), function (err) { | ||
return err.status === 400 && err.content.error === 'KO'; | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
function responseMock({ status, data }) { | ||
return new window.Response(JSON.stringify(data), { status }); | ||
} |