Skip to content

Commit

Permalink
[TECH] Améliorer les notifications d'erreur sur la création de profil…
Browse files Browse the repository at this point in the history
… cible
  • Loading branch information
pix-service-auto-merge committed May 17, 2022
2 parents 74887ba + 8196552 commit 3d3a045
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 10 deletions.
21 changes: 17 additions & 4 deletions admin/app/controllers/authenticated/target-profiles/new.js
Expand Up @@ -7,6 +7,7 @@ import { tracked } from '@glimmer/tracking';
export default class NewController extends Controller {
@service notifications;
@service store;
@service router;

@tracked isFileInvalid = false;
@tracked isSaving = false;
Expand All @@ -16,7 +17,7 @@ export default class NewController extends Controller {
goBackToTargetProfileList() {
this.store.deleteRecord(this.model);
this.transitionToRoute('authenticated.target-profiles.list');
this.router.transitionTo('authenticated.target-profiles.list');
}
@action
Expand Down Expand Up @@ -53,11 +54,23 @@ export default class NewController extends Controller {
await this.model.save();
this.notifications.success('Le profil cible a été créé avec succès.');
this.transitionToRoute('authenticated.target-profiles.target-profile', this.model.id);
this.router.transitionTo('authenticated.target-profiles.target-profile', this.model.id);
} catch (error) {
this.notifications.error('Une erreur est survenue.');
this._handleResponseError(error);
} finally {
this.isSaving = false;
}
}
this.isSaving = false;
_handleResponseError({ errors }) {
if (!errors) {
return this.notifications.error('Une erreur est survenue.');
}
errors.forEach((error) => {
if (['404', '412', '422'].includes(error.status)) {
return this.notifications.error(error.detail);
}
return this.notifications.error('Une erreur est survenue.');
});
}
}
Expand Up @@ -14,13 +14,13 @@ module('Unit | Controller | authenticated/target-profiles/new', function (hooks)
module('#goBackToTargetProfileList', function () {
test('should delete record and go back target profile list page', async function (assert) {
controller.store.deleteRecord = sinon.stub();
controller.transitionToRoute = sinon.stub();
controller.router.transitionTo = sinon.stub();
controller.model = Symbol('targetProfile');

controller.goBackToTargetProfileList();

assert.ok(controller.store.deleteRecord.calledWith(controller.model));
assert.ok(controller.transitionToRoute.calledWith('authenticated.target-profiles.list'));
assert.ok(controller.router.transitionTo.calledWith('authenticated.target-profiles.list'));
});
});

Expand Down Expand Up @@ -122,7 +122,7 @@ module('Unit | Controller | authenticated/target-profiles/new', function (hooks)
save: sinon.stub(),
};

controller.transitionToRoute = sinon.stub();
controller.router.transitionTo = sinon.stub();

controller.notifications = {
success: sinon.stub(),
Expand All @@ -142,11 +142,11 @@ module('Unit | Controller | authenticated/target-profiles/new', function (hooks)
assert.ok(controller.model.save.called);
assert.ok(controller.notifications.success.calledWith('Le profil cible a été créé avec succès.'));
assert.ok(
controller.transitionToRoute.calledWith('authenticated.target-profiles.target-profile', controller.model.id)
controller.router.transitionTo.calledWith('authenticated.target-profiles.target-profile', controller.model.id)
);
});

test('it should display notification Error when model cannot be saved', async function (assert) {
test('it should display error notification when model cannot be saved', async function (assert) {
controller.model = {
save: sinon.stub(),
};
Expand All @@ -169,5 +169,31 @@ module('Unit | Controller | authenticated/target-profiles/new', function (hooks)
assert.ok(controller.model.save.called);
assert.ok(controller.notifications.error.calledWith('Une erreur est survenue.'));
});

test('it should display detailed error notification when model cannot be saved', async function (assert) {
controller.model = {
save: sinon.stub(),
};

controller.notifications = {
error: sinon.stub(),
};

const event = {
preventDefault: sinon.stub(),
};

controller.model.save.rejects({
errors: [{ status: '404', detail: 'Organisation non trouvée' }],
});

// when
await controller.createTargetProfile(event);

// then
assert.ok(event.preventDefault.called);
assert.ok(controller.model.save.called);
assert.ok(controller.notifications.error.calledWith('Organisation non trouvée'));
});
});
});
2 changes: 2 additions & 0 deletions api/db/pgsql-errors.js
@@ -1,9 +1,11 @@
const PGSQL_DUPLICATE_DATABASE_ERROR = '42P04';
const PGSQL_NON_EXISTENT_DATABASE_ERROR = '3D000';
const PGSQL_UNIQUE_CONSTRAINT_VIOLATION_ERROR = '23505';
const PGSQL_FOREIGN_KEY_VIOLATION_ERROR = '23503';

module.exports = {
PGSQL_DUPLICATE_DATABASE_ERROR,
PGSQL_NON_EXISTENT_DATABASE_ERROR,
PGSQL_UNIQUE_CONSTRAINT_VIOLATION_ERROR,
PGSQL_FOREIGN_KEY_VIOLATION_ERROR,
};
Expand Up @@ -11,9 +11,11 @@ const {
NotFoundError,
ObjectValidationError,
InvalidSkillSetError,
OrganizationNotFoundError,
} = require('../../domain/errors');
const DomainTransaction = require('../../infrastructure/DomainTransaction');
const TargetProfile = require('../../domain/models/TargetProfile');
const { PGSQL_FOREIGN_KEY_VIOLATION_ERROR } = require('../../../db/pgsql-errors');

module.exports = {
async create(targetProfileData) {
Expand Down Expand Up @@ -46,6 +48,10 @@ module.exports = {
} catch (e) {
await trx.rollback();

if (e.code === PGSQL_FOREIGN_KEY_VIOLATION_ERROR) {
throw new OrganizationNotFoundError();
}

throw new TargetProfileCannotBeCreated();
}
},
Expand Down
Expand Up @@ -5,7 +5,12 @@ const TargetProfileForCreation = require('../../../../lib/domain/models/TargetPr
const Skill = require('../../../../lib/domain/models/Skill');
const targetProfileRepository = require('../../../../lib/infrastructure/repositories/target-profile-repository');
const skillDatasource = require('../../../../lib/infrastructure/datasources/learning-content/skill-datasource');
const { NotFoundError, ObjectValidationError, InvalidSkillSetError } = require('../../../../lib/domain/errors');
const {
NotFoundError,
ObjectValidationError,
InvalidSkillSetError,
OrganizationNotFoundError,
} = require('../../../../lib/domain/errors');

describe('Integration | Repository | Target-profile', function () {
describe('#create', function () {
Expand Down Expand Up @@ -68,6 +73,22 @@ describe('Integration | Repository | Target-profile', function () {
// then
expect(skillsId).to.exactlyContain(['skills1', 'skills2']);
});

describe("when organization doesn't exist", function () {
it('should throw an OrganizationNotFoundError', async function () {
const targetProfileForCreation = new TargetProfileForCreation({
name: 'myFirstTargetProfile',
skillIds: ['skills1', 'skills2', 'skills2'],
ownerOrganizationId: -1,
});

// when
const error = await catchErr(targetProfileRepository.create)(targetProfileForCreation);

// then
expect(error).to.be.instanceOf(OrganizationNotFoundError);
});
});
});

describe('#get', function () {
Expand Down

0 comments on commit 3d3a045

Please sign in to comment.