Skip to content

Commit

Permalink
feat: permet l'accès en lecture seul au nouvel OC
Browse files Browse the repository at this point in the history
  • Loading branch information
GregoireDucharme committed Jan 8, 2025
1 parent 95a7aa9 commit 1b67002
Show file tree
Hide file tree
Showing 20 changed files with 378 additions and 110 deletions.
211 changes: 132 additions & 79 deletions src/components/forms/SingleItemCertificationBodyForm.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
import { defineComponent, markRaw } from "vue";
import { createTestingPinia } from "@pinia/testing";
import { flushPromises, mount } from "@vue/test-utils";
Expand All @@ -12,15 +12,19 @@ import {
CERTIFICATION_BODY_DECISION,
LEVEL_AB,
LEVEL_C1,
LEVEL_C2,
LEVEL_C3,
LEVEL_CONVENTIONAL,
} from "@/referentiels/ab.js";

import record from "@/utils/__fixtures__/record-with-features.json" assert { type: "json" };
import EditForm from "@/components/forms/SingleItemCertificationBodyForm.vue";
import TableComponent from "@/components/records/Table/index.vue";
import { useOperatorStore } from "@/stores/operator";

const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false });
const recordStore = useRecordStore(pinia);
const operatorStore = useOperatorStore(pinia);
const permissions = usePermissions(pinia);
const storage = useCartoBioStorage(pinia);

Expand Down Expand Up @@ -51,97 +55,146 @@ describe("SingleItemCertificationBodyForm", () => {
document.body.outerHTML = "";
});

test("we assign a certification state", async () => {
const form = wrapper.getComponent(EditForm);

// if "Conventionnel", there is no date field
await form.find(`#conversion-${LEVEL_CONVENTIONAL}`).setValue();
expect(form.find("#engagement_date").exists()).toEqual(false);
describe("item is not readonly", async () => {
beforeAll(async () => {
operatorStore.operator = {
organismeCertificateur: {
id: 1,
},
};
});
test("we assign a certification state", async () => {
const form = wrapper.getComponent(EditForm);

// if AB, date field is not mandatory
await form.find(`#conversion-${LEVEL_AB}`).setValue();
expect(form.find("#engagement_date").attributes()).not.toHaveProperty("required");
// if "Conventionnel", there is no date field
await form.find(`#conversion-${LEVEL_CONVENTIONAL}`).setValue();
expect(form.find("#engagement_date").exists()).toEqual(false);

// date field is mandatory otherwise
await form.find(`#conversion-${LEVEL_C1}`).setValue();
expect(form.find("#engagement_date").attributes()).toHaveProperty("required", "");
});
// if AB, date field is not mandatory
await form.find(`#conversion-${LEVEL_AB}`).setValue();
expect(form.find("#engagement_date").attributes()).not.toHaveProperty("required");

test("we toggle expanded annotations", async () => {
const form = wrapper.getComponent(EditForm);
// date field is mandatory otherwise
await form.find(`#conversion-${LEVEL_C1}`).setValue();
expect(form.find("#engagement_date").attributes()).toHaveProperty("required", "");
});

// We have all the tags tags and no expand button
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(5);
expect(form.find(".fr-tags-group--annotations > .annotation--more").attributes()).toHaveProperty("hidden");
test("we toggle expanded annotations", async () => {
const form = wrapper.getComponent(EditForm);

// expect(form.find('.fr-tags-group--annotations > .annotation--more').attributes()).not.toHaveProperty('hidden')
// await form.find('.fr-tags-group--annotations > .annotation--more button').trigger('click')
// We have all the tags tags and no expand button
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(5);
expect(form.find(".fr-tags-group--annotations > .annotation--more").attributes()).toHaveProperty("hidden");

const expectedChoices = Object.keys(AnnotationTags);
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(expectedChoices.length);
});
// expect(form.find('.fr-tags-group--annotations > .annotation--more').attributes()).not.toHaveProperty('hidden')
// await form.find('.fr-tags-group--annotations > .annotation--more button').trigger('click')

test("we select three choices, and two reasons", async () => {
const form = wrapper.getComponent(EditForm);
const expectedChoices = Object.keys(AnnotationTags);
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(expectedChoices.length);
});

// We have 5 tags
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.DOWNGRADED} button`).trigger("click");
await form
.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.REDUCED_CONVERSION_PERIOD} button`)
.trigger("click");
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.RISKY} button`).trigger("click");
test("we select three choices, and two reasons", async () => {
const form = wrapper.getComponent(EditForm);

// We have 5 tags
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.DOWNGRADED} button`).trigger("click");
await form
.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.REDUCED_CONVERSION_PERIOD} button`)
.trigger("click");
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.RISKY} button`).trigger("click");

expect(form.find("#downgraded_state").element.value).toEqual(CERTIFICATION_BODY_DECISION.PENDING);
expect(form.find("#downgraded_state").element.selectedOptions[0].textContent).toEqual("En cours de traitement");

expect(form.find("#reduced_conversion_period_state").element.value).toEqual(CERTIFICATION_BODY_DECISION.PENDING);
expect(form.find("#reduced_conversion_period_state").element.selectedOptions[0].textContent).toEqual(
"En cours de traitement",
);

// we toggle and cancel the tag
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.SURVEYED} button`).trigger("click");
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.SURVEYED} button`).trigger("click");

await form.find("#reduced_conversion_period_state").setValue(CERTIFICATION_BODY_DECISION.REJECTED);
await form.find("#downgraded_state").setValue(CERTIFICATION_BODY_DECISION.ACCEPTED);

// click and assess server update
axios.__createMock.patch.mockResolvedValueOnce({ data: record });
axios.__createMock.get.mockResolvedValueOnce({ data: record });
await form.find(".fr-modal__footer button.fr-btn").trigger("click");

await flushPromises();
expect(wrapper.findComponent(EditForm).exists()).toEqual(false);
expect(axios.__createMock.patch).toHaveBeenCalled();
expect(axios.__createMock.patch.mock.lastCall).toMatchObject([
"/v2/audits/054f0d70-c3da-448f-823e-81fcf7c2bf6e/parcelles/2",
{
properties: {
annotations: [
{
code: ANNOTATIONS.DOWNGRADED,
metadata: {
[ANNOTATIONS.METADATA_STATE]: CERTIFICATION_BODY_DECISION.ACCEPTED,
},
},
{
code: ANNOTATIONS.REDUCED_CONVERSION_PERIOD,
metadata: {
[ANNOTATIONS.METADATA_STATE]: CERTIFICATION_BODY_DECISION.REJECTED,
},
},
{
code: ANNOTATIONS.RISKY,
},
],
},
},
{
headers: {
"If-Unmodified-Since": expect.any(String),
},
},
]);
});
});

expect(form.find("#downgraded_state").element.value).toEqual(CERTIFICATION_BODY_DECISION.PENDING);
expect(form.find("#downgraded_state").element.selectedOptions[0].textContent).toEqual("En cours de traitement");
describe("item is readonly", async () => {
beforeAll(async () => {
operatorStore.operator = {
organismeCertificateur: {
id: 2,
},
};
});
test("certification state are disabled", async () => {
const form = wrapper.getComponent(EditForm);

expect(form.find(`#conversion-${LEVEL_CONVENTIONAL}`).isDisabled()).toEqual(true);
expect(form.find(`#conversion-${LEVEL_C1}`).isDisabled()).toEqual(true);
expect(form.find(`#conversion-${LEVEL_C2}`).isDisabled()).toEqual(true);
expect(form.find(`#conversion-${LEVEL_C3}`).isDisabled()).toEqual(true);
expect(form.find(`#conversion-${LEVEL_AB}`).isDisabled()).toEqual(true);
});

expect(form.find("#reduced_conversion_period_state").element.value).toEqual(CERTIFICATION_BODY_DECISION.PENDING);
expect(form.find("#reduced_conversion_period_state").element.selectedOptions[0].textContent).toEqual(
"En cours de traitement",
);
test("annotations are disabled", async () => {
const form = wrapper.getComponent(EditForm);

// we toggle and cancel the tag
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.SURVEYED} button`).trigger("click");
await form.find(`.fr-tags-group--annotations > .annotation--${ANNOTATIONS.SURVEYED} button`).trigger("click");
// We have all the tags tags and no expand button
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(5);
expect(form.find(".fr-tags-group--annotations > .annotation--more").attributes()).toHaveProperty("hidden");

await form.find("#reduced_conversion_period_state").setValue(CERTIFICATION_BODY_DECISION.REJECTED);
await form.find("#downgraded_state").setValue(CERTIFICATION_BODY_DECISION.ACCEPTED);
// expect(form.find('.fr-tags-group--annotations > .annotation--more').attributes()).not.toHaveProperty('hidden')
// await form.find('.fr-tags-group--annotations > .annotation--more button').trigger('click')

// click and assess server update
axios.__createMock.patch.mockResolvedValueOnce({ data: record });
axios.__createMock.get.mockResolvedValueOnce({ data: record });
await form.find(".fr-modal__footer button.fr-btn").trigger("click");
const expectedChoices = Object.keys(AnnotationTags);
expect(form.findAll(".fr-tags-group--annotations > .annotation-choice")).toHaveLength(expectedChoices.length);

await flushPromises();
expect(wrapper.findComponent(EditForm).exists()).toEqual(false);
expect(axios.__createMock.patch).toHaveBeenCalled();
expect(axios.__createMock.patch.mock.lastCall).toMatchObject([
"/v2/audits/054f0d70-c3da-448f-823e-81fcf7c2bf6e/parcelles/2",
{
properties: {
annotations: [
{
code: ANNOTATIONS.DOWNGRADED,
metadata: {
[ANNOTATIONS.METADATA_STATE]: CERTIFICATION_BODY_DECISION.ACCEPTED,
},
},
{
code: ANNOTATIONS.REDUCED_CONVERSION_PERIOD,
metadata: {
[ANNOTATIONS.METADATA_STATE]: CERTIFICATION_BODY_DECISION.REJECTED,
},
},
{
code: ANNOTATIONS.RISKY,
},
],
},
},
{
headers: {
"If-Unmodified-Since": expect.any(String),
},
},
]);
const annotations = form.findAll(".fr-tags-group--annotations > .annotation-choice > button");
expect(annotations[0].isDisabled()).toEqual(true);
expect(annotations[1].isDisabled()).toEqual(true);
expect(annotations[2].isDisabled()).toEqual(true);
expect(annotations[3].isDisabled()).toEqual(true);
expect(annotations[4].isDisabled()).toEqual(true);
});
});
});
25 changes: 21 additions & 4 deletions src/components/forms/SingleItemCertificationBodyForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
:required="requiredName"
:class="{ 'fr-input--error': nameErrors.size }"
ref="autofocusedElement"
:disabled="readonly"
/>
<div v-for="[id, result] in nameErrors" :key="id" class="fr-hint-text fr-error-text">
{{ result.errorMessage }}.
Expand Down Expand Up @@ -41,6 +42,7 @@
:feature-id="feature.properties.id"
:cultures="patch.cultures"
@change="($cultures) => (patch.cultures = $cultures)"
:disabled-input="readonly"
/>
</AccordionSection>
</AccordionGroup>
Expand All @@ -53,7 +55,7 @@
>
<ConversionLevelSelector
:feature-id="feature.properties.id"
:readonly="!permissions.canChangeConversionLevel"
:readonly="!permissions.canChangeConversionLevel || readonly"
v-model="patch.conversion_niveau"
/>

Expand All @@ -78,9 +80,10 @@
v-if="permissions.canAddAnnotations"
v-model="patch.annotations"
:feature-id="feature.properties.id"
:readonly="readonly"
/>

<div class="fr-input-group">
<div v-if="!readonly" class="fr-input-group">
<label class="fr-label" for="auditeur_notes">Vos notes de certification (facultatif)</label>
<textarea class="fr-input" id="auditeur_notes" name="auditeur_notes" v-model="patch.auditeur_notes" />
</div>
Expand All @@ -92,7 +95,9 @@

<template #footer>
<div class="fr-input-group">
<button class="fr-btn" type="submit" form="single-feature-edit-form">Enregistrer</button>
<button class="fr-btn" type="submit" form="single-feature-edit-form">
{{ readonly ? "Fermer" : "Enregistrer" }}
</button>
</div>
</template>
</Modal>
Expand Down Expand Up @@ -130,6 +135,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
readonly: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["submit", "close"]);
Expand Down Expand Up @@ -159,6 +168,10 @@ function requiresAction(properties) {
}
const validate = () => {
if (props.readonly) {
emit("close");
return;
}
const set = featuresSet.byFeature(props.feature.id, true);
if (set.size) {
Expand All @@ -169,7 +182,7 @@ const validate = () => {
};
function handleClose() {
if (featuresSet.isDirty) {
if (featuresSet.isDirty && !props.readonly) {
showCancelModal.value = true;
} else {
emit("close");
Expand All @@ -179,6 +192,10 @@ function handleClose() {
onBeforeUnmount(() => featuresSet.setCandidate([]));
watch(patch, (properties) => {
if (props.readonly) {
return;
}
featuresSet.setCandidate([
{
id: props.feature.id,
Expand Down
5 changes: 5 additions & 0 deletions src/components/forms/fields/AnnotationsSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
type="button"
:aria-pressed="isSelected(annotationId)"
@click="toggleAnnotation(annotationId)"
:disabled="readonly"
>
{{ annotation.label }}
</button>
Expand Down Expand Up @@ -93,6 +94,10 @@ const props = defineProps({
required: true,
default: () => [],
},
readonly: {
type: Boolean,
default: false,
},
});
const isUserExpanded = ref(false);
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/fields/ConversionLevelSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const props = defineProps({
},
readonly: {
type: Boolean,
default: () => false,
default: false,
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/fields/CultureSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const props = defineProps({
},
disabledInput: {
type: Boolean,
default: () => false,
default: false,
},
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/fields/CultureTypeSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const props = defineProps({
},
disabledInput: {
type: Boolean,
default: () => false,
default: false,
},
});
Expand Down
Loading

0 comments on commit 1b67002

Please sign in to comment.