Skip to content

Commit

Permalink
test: ✅ add e2e and api tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nutfdt committed Oct 31, 2024
1 parent 9e833a4 commit 929aa27
Show file tree
Hide file tree
Showing 24 changed files with 283 additions and 300 deletions.
28 changes: 0 additions & 28 deletions backend/src/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,34 +139,6 @@ async def imageupload(
logging.exception(e, extra=extras_logging)
raise HTTPException(status_code=500, detail=str(e))

@router.post("/identification-blank-gun")
async def imageblankgun(
image: UploadFile = File(...),
):
try:
img_bytes = image.file.read()
# Process image with ML models
alarm_model = is_alarm_weapon(img_bytes)
return {
"alarm_model": alarm_model,
"missing_text": False,
"low_quality": False,
}

except LowQuality:
return {
"alarm_model": None,
"low_quality": True,
"missing_text": False,
}
except MissingText:
return {
"alarm_model": None,
"low_quality": False,
"missing_text": True,
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

@router.post("/identification-feedback")
async def log_feedback(request: Request, user_id: Union[str, None] = Cookie(None)):
Expand Down
55 changes: 55 additions & 0 deletions frontend/cypress/e2e/blank-gun-detection.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
describe("Blank Gun Detection", () => {
it("should identificate real blank gun", () => {
cy.Identification();
cy.getByDataTestid("select-file").as("fileInput");
cy.intercept("POST", "/api/upload").as("upload");
cy.get("@fileInput").selectFile("./cypress/images/blank-gun.jpg", {
force: true,
});
cy.wait("@upload").then(({ response }) => {
expect(response.statusCode).to.eq(200);
});
cy.wait(1000);
cy.getByDataTestid("next-step").click();
cy.IdentificationPistoletOCR("Identification d'une arme d'alarme");
cy.wait(5000);
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie C");
});

it("should identificate firearm with missing text", () => {
cy.Identification();
cy.getByDataTestid("select-file").as("fileInput");
cy.intercept("POST", "/api/upload").as("upload");
cy.get("@fileInput").selectFile("./cypress/images/no-text.jpg", {
force: true,
});
cy.wait("@upload").then(({ response }) => {
expect(response.statusCode).to.eq(200);
});
cy.wait(1000);
cy.getByDataTestid("next-step").click();
cy.IdentificationPistoletOCR("Marquages non détectés");
cy.get('.fr-col-12 > [data-testid="next-step"]').click();
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie B");
});

it("should identificate firearm with low quality", () => {
cy.Identification();
cy.getByDataTestid("select-file").as("fileInput");
cy.intercept("POST", "/api/upload").as("upload");
cy.get("@fileInput").selectFile("./cypress/images/low-quality.jpg", {
force: true,
});
cy.wait("@upload").then(({ response }) => {
expect(response.statusCode).to.eq(200);
});
cy.wait(1000);
cy.getByDataTestid("next-step").click();
cy.IdentificationPistoletOCR("Qualité d'image insuffisante");
cy.get('.fr-col-12 > [data-testid="next-step"]').click();
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie B");
});
});
3 changes: 1 addition & 2 deletions frontend/cypress/e2e/firearm-confidence.cy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
describe("Firearm Confidence", () => {
it("should identificate firearm with high confidence", () => {
it.only("should identificate firearm with high confidence", () => {
cy.Identification();

cy.getByDataTestid("select-file").as("fileInput");
cy.intercept("POST", "/api/upload").as("upload");
cy.get("@fileInput").selectFile("./cypress/images/pistolet-semi-auto.jpg", {
Expand Down
1 change: 1 addition & 0 deletions frontend/cypress/e2e/firearm-identification.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("Firearm Identification", () => {
});
cy.getByDataTestid("next-step").click();
cy.IdentificationPistoletSemiAuto();
cy.wait(5000);
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie B");
cy.getByDataTestid("return-to-home-end").click();
Expand Down
1 change: 1 addition & 0 deletions frontend/cypress/e2e/firearm-securing.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe("Securing Firearm and Identification", () => {
cy.contains("p", "Basegun a identifié votre arme");
cy.getByDataTestid("next-step").click();
cy.IdentificationPistoletSemiAuto();
cy.wait(5000);
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie B");
cy.getByDataTestid("return-to-home-end").click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe("Typology Revolver Identification", () => {
cy.wait("@upload").then(({ response }) => {
expect(response.statusCode).to.eq(200);
});
cy.wait(1000);
cy.IdentificationRevolver();
cy.url().should("contain", "/guide-identification/resultat-final");
cy.getByDataTestid("arm-category").should("contain", "Catégorie B ou D");
Expand Down
Binary file added frontend/cypress/images/blank-gun.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/cypress/images/low-quality.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/cypress/images/no-text.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/cypress/images/pistolet-semi-auto.jpg
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 17 additions & 10 deletions frontend/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@ Cypress.Commands.add("IdentificationPistoletSemiAuto", () => {
cy.contains("Cartouches").first().click();
cy.getByDataTestid("next-step").should("not.have.attr", "disabled");
cy.getByDataTestid("next-step").click();
cy.url().should("contain", "/guide-identification/armes-alarme");
cy.getByDataTestid("instruction-armeAlarme").should("contain", "Votre arme");
cy.getByDataTestid("next-step").click();
cy.getByDataTestid("aucune-correspondance").click();
cy.getByDataTestid("next-step").click();
});

Cypress.Commands.add("IdentificationRevolver", () => {
Expand All @@ -133,11 +128,8 @@ Cypress.Commands.add("IdentificationRevolver", () => {
cy.contains("Balles").first().click();
cy.getByDataTestid("next-step").should("not.have.attr", "disabled");
cy.getByDataTestid("next-step").click();
cy.url().should("contain", "/guide-identification/armes-alarme");
cy.getByDataTestid("instruction-armeAlarme").should("contain", "Votre arme");
cy.getByDataTestid("next-step").click();
cy.getByDataTestid("aucune-correspondance").click();
cy.getByDataTestid("next-step").click();
cy.getByDataTestid("title-page").should("contain", "Marquages non détectés");
cy.get('.fr-col-12 > [data-testid="next-step"]').click();
});

Cypress.Commands.add("arrierePlatRevolver", () => {
Expand Down Expand Up @@ -251,6 +243,21 @@ Cypress.Commands.add("IdentificationShotgun", (typeOfMunition) => {
cy.getByDataTestid("next-step").click();
});

Cypress.Commands.add("IdentificationPistoletOCR", (header) => {
cy.url().should(
"contain",
"guide-identification/informations-complementaires",
);
cy.getByDataTestid("next-step").click();
cy.url().should("contain", "/guide-identification/munition-type");
cy.getByDataTestid("next-step").should("have.attr", "disabled");
cy.contains("Cartouches").first().click();
cy.getByDataTestid("next-step").should("not.have.attr", "disabled");
cy.getByDataTestid("next-step").click();
cy.url().should("contain", "/guide-identification/armes-alarme");
cy.getByDataTestid("title-page").should("contain", `${header}`);
});

Cypress.Commands.add("ExpertContactPath", () => {
cy.visit("/accueil", {
onBeforeLoad: (win) => {
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/api/api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TUTORIAL_FEEDBACK_ROUTE,
UPLOAD_PHOTO_FOR_DETECTION_ROUTE,
GET_IRCGN_NUMBERS_ROUTE,
UPLOAD_PHOTO_FOR_ALARM_GUN_DETECTION,
} from "./api-routes";

export const uploadPhotoForDetection = async (file: File) => {
Expand Down Expand Up @@ -55,3 +56,11 @@ export const getContactDetails = async (accessToken: string) => {
},
});
};

export const uploadPhotoForAlarmGunDetection = async (file: File) => {
const fd = new FormData();
fd.append("image", file, file.name);

const { data } = await axios.post(UPLOAD_PHOTO_FOR_ALARM_GUN_DETECTION, fd);
return data;
};
1 change: 1 addition & 0 deletions frontend/src/api/api-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export const IDENTIFICATION_FEEDBACK_ROUTE = "/identification-feedback";
export const IDENTIFICATION_DUMMY_ROUTE = "/identification-dummy";
export const ASK_FOR_OPINION_ROUTE = "/expert-contact";
export const GET_IRCGN_NUMBERS_ROUTE = "/contact-details";
export const UPLOAD_PHOTO_FOR_ALARM_GUN_DETECTION = "/identification-alarm-gun";
Binary file added frontend/src/assets/markings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed frontend/src/assets/missing_marking.png
Binary file not shown.
Binary file added frontend/src/assets/missing_markings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 32 additions & 32 deletions frontend/src/components.d.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
export {};

declare module "vue" {
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AskingExpert: (typeof import("./components/AskingExpert.vue"))["default"];
AuthCallback: (typeof import("./components/authentication/AuthCallback.vue"))["default"];
AuthRedirect: (typeof import("./components/authentication/AuthRedirect.vue"))["default"];
ContactExpert: (typeof import("./components/ContactExpert.vue"))["default"];
copy: (typeof import("./components/authentification/AuthRedirect copy.vue"))["default"];
DsfrAlert: (typeof import("@gouvminint/vue-dsfr"))["DsfrAlert"];
DsfrButton: (typeof import("@gouvminint/vue-dsfr"))["DsfrButton"];
DsfrCheckbox: (typeof import("@gouvminint/vue-dsfr"))["DsfrCheckbox"];
DsfrFileUpload: (typeof import("@gouvminint/vue-dsfr"))["DsfrFileUpload"];
DsfrHeader: (typeof import("@gouvminint/vue-dsfr"))["DsfrHeader"];
DsfrInput: (typeof import("@gouvminint/vue-dsfr"))["DsfrInput"];
DsfrModal: (typeof import("@gouvminint/vue-dsfr"))["DsfrModal"];
DsfrPicture: (typeof import("@gouvminint/vue-dsfr"))["DsfrPicture"];
DsfrRadioButton: (typeof import("@gouvminint/vue-dsfr"))["DsfrRadioButton"];
DsfrRadioButtonSet: (typeof import("@gouvminint/vue-dsfr"))["DsfrRadioButtonSet"];
DsfrSelect: (typeof import("@gouvminint/vue-dsfr"))["DsfrSelect"];
DsfrTag: (typeof import("@gouvminint/vue-dsfr"))["DsfrTag"];
HeaderMain: (typeof import("./components/HeaderMain.vue"))["default"];
MissingCardAlert: (typeof import("./components/MissingCardAlert.vue"))["default"];
OnboardingSwiper: (typeof import("./components/OnboardingSwiper.vue"))["default"];
PopupContact: (typeof import("./components/PopupContact.vue"))["default"];
PopupVideo: (typeof import("./components/PopupVideo.vue"))["default"];
ResultPage: (typeof import("./components/ResultPage.vue"))["default"];
RouterLink: (typeof import("vue-router"))["RouterLink"];
RouterView: (typeof import("vue-router"))["RouterView"];
SnackbarAlert: (typeof import("./components/SnackbarAlert.vue"))["default"];
StepsGuide: (typeof import("./components/StepsGuide.vue"))["default"];
User: (typeof import("./components/authentication/User.vue"))["default"];
VIcon: (typeof import("@gouvminint/vue-dsfr"))["VIcon"];
AskingExpert: typeof import('./components/AskingExpert.vue')['default']
AuthCallback: (typeof import("./components/authentication/AuthCallback.vue"))["default"]
AuthRedirect: (typeof import("./components/authentication/AuthRedirect.vue"))["default"]
ContactExpert: typeof import('./components/ContactExpert.vue')['default']
copy: (typeof import("./components/authentification/AuthRedirect copy.vue"))["default"]
DsfrAlert: typeof import('@gouvminint/vue-dsfr')['DsfrAlert']
DsfrButton: typeof import('@gouvminint/vue-dsfr')['DsfrButton']
DsfrCheckbox: typeof import('@gouvminint/vue-dsfr')['DsfrCheckbox']
DsfrFileUpload: typeof import('@gouvminint/vue-dsfr')['DsfrFileUpload']
DsfrHeader: typeof import('@gouvminint/vue-dsfr')['DsfrHeader']
DsfrInput: typeof import('@gouvminint/vue-dsfr')['DsfrInput']
DsfrModal: typeof import('@gouvminint/vue-dsfr')['DsfrModal']
DsfrPicture: typeof import('@gouvminint/vue-dsfr')['DsfrPicture']
DsfrRadioButton: typeof import('@gouvminint/vue-dsfr')['DsfrRadioButton']
DsfrRadioButtonSet: typeof import('@gouvminint/vue-dsfr')['DsfrRadioButtonSet']
DsfrSelect: typeof import('@gouvminint/vue-dsfr')['DsfrSelect']
DsfrTag: typeof import('@gouvminint/vue-dsfr')['DsfrTag']
HeaderMain: typeof import('./components/HeaderMain.vue')['default']
MissingCardAlert: typeof import('./components/MissingCardAlert.vue')['default']
OnboardingSwiper: typeof import('./components/OnboardingSwiper.vue')['default']
PopupContact: typeof import('./components/PopupContact.vue')['default']
PopupVideo: typeof import('./components/PopupVideo.vue')['default']
ResultPage: typeof import('./components/ResultPage.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SnackbarAlert: typeof import('./components/SnackbarAlert.vue')['default']
StepsGuide: typeof import('./components/StepsGuide.vue')['default']
User: (typeof import("./components/authentication/User.vue"))["default"]
VIcon: typeof import('@gouvminint/vue-dsfr')['VIcon']
}
}
10 changes: 5 additions & 5 deletions frontend/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { clearLocalStorage } from "@/utils/storage-utils.js";
import { mgr } from "@/utils/authentication";

import MissingCardPage from "@/views/MissingCardPage.vue";
import IdentificationQualityImage from "@/views/GuideIdentificationFirearm/IdentificationQualityImage.vue";
import IdentificationAlarmGun from "@/views/GuideIdentificationFirearm/IdentificationAlarmGun.vue";
import ExpertiseForm from "@/views/GuideAskingExpertise/ExpertiseForm.vue";

const HomePage = () => import("@/views/HomePage.vue");
Expand Down Expand Up @@ -136,9 +136,9 @@ const routes: RouteRecordRaw[] = [
component: IdentificationSelectAmmo,
},
{
path: "qualite-image",
name: "IdentificationQualityImage",
component: IdentificationQualityImage,
path: "armes-alarme",
name: "IdentificationAlarmGun",
component: IdentificationAlarmGun,
},
{
path: "resultat-final",
Expand Down Expand Up @@ -263,7 +263,7 @@ const routes: RouteRecordRaw[] = [
}
} catch (error) {
console.error("Erreur signin callback:", error);
next({ name: "ErrorPage" });
next({ name: "AuthRedirect" });
}
},
},
Expand Down
21 changes: 6 additions & 15 deletions frontend/src/stores/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@ export const useStore = defineStore("result", {
const gunBarrelLength = ref(null);
const img = ref(null);
const imgUrl = ref(null);
const unresizeImage = ref(null);
const securingTutorial = ref(false);

const selectedOptions = ref([]);
const selectedAmmo = ref(undefined);
const selectedAlarmGun = ref(undefined);
const alarmModel = ref(null);
const isAlarmGunMissingText = ref(null);
const isAlarmGunLowQuality = ref(null);
const isAlarmGun = ref(false);
const alarmGunException = ref(undefined);
const isDummy = computed(() => !!(selectedAmmo.value === "billes"));
const isModalTransparentAmmoOpened = ref(null);

Expand All @@ -30,15 +27,12 @@ export const useStore = defineStore("result", {
gunBarrelLength.value = null;
img.value = null;
imgUrl.value = null;
unresizeImage.value = null;
securingTutorial.value = false;

selectedOptions.value = [];
selectedAmmo.value = undefined;
selectedAlarmGun.value = undefined;
alarmModel.value = null;
isAlarmGunMissingText.value = null;
isAlarmGunLowQuality.value = null;
isAlarmGun.value = false;
alarmGunException.value = undefined;
isModalTransparentAmmoOpened.value = null;
}

Expand All @@ -50,14 +44,11 @@ export const useStore = defineStore("result", {
gunBarrelLength,
img,
imgUrl,
unresizeImage,
securingTutorial,
selectedOptions,
selectedAmmo,
selectedAlarmGun,
alarmModel,
isAlarmGunMissingText,
isAlarmGunLowQuality,
isAlarmGun,
alarmGunException,
isDummy,
isModalTransparentAmmoOpened,
$reset,
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/utils/firearms-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const TYPOLOGIES = {
const IdentificationTypologyResult = "IdentificationTypologyResult";
const IdentificationFurtherInformations = "IdentificationFurtherInformations";
const IdentificationSelectAmmo = "IdentificationSelectAmmo";
const IdentificationQualityImage = "IdentificationQualityImage";
const IdentificationAlarmGun = "IdentificationAlarmGun";
const IdentificationFinalResult = "IdentificationFinalResult";

export const identificationGuideSteps = [
Expand All @@ -48,7 +48,7 @@ export const identificationGuideStepsWithArmeAlarme = [
IdentificationTypologyResult,
IdentificationFurtherInformations,
IdentificationSelectAmmo,
IdentificationQualityImage,
IdentificationAlarmGun,
IdentificationFinalResult,
] as const;

Expand All @@ -69,7 +69,7 @@ export const identificationRoutePathsWithArmeAlarme = [
"resultat-typologie",
"informations-complementaires",
"munition-type",
"qualite-image",
"armes-alarme",
"resultat-final",
] as const;

Expand All @@ -81,7 +81,7 @@ export function isAlarmGun() {
) {
return false;
}
return store.alarmModel === "Alarm_model" ? true : undefined;
return store.isAlarmGun;
}

export const MEASURED_GUNS_TYPOLOGIES = [
Expand Down
Loading

0 comments on commit 929aa27

Please sign in to comment.