End to end tests
This commit is contained in:
parent
c71e4b4cd0
commit
fed82d1ae8
26 changed files with 1016 additions and 37 deletions
|
|
@ -33,6 +33,7 @@ const copy = {
|
|||
redirectLoading: 'Reindirizzamento alla pagina legacy filtrata in corso…',
|
||||
processingLoading: 'Ricerca biometrica in corso su tutte le foto della gara…',
|
||||
unavailableDefault: 'FaceAI non è disponibile per questa gara.',
|
||||
noFacesFoundMessage: 'Nessun volto rilevato nella foto caricata. Puoi tornare alla gara oppure provare con un altro selfie.',
|
||||
readyMessage: 'Seleziona un selfie per avviare una ricerca limitata alla gara corrente.',
|
||||
completedMessage: 'Ricerca completata. Trovate {count} foto corrispondenti.',
|
||||
failedMessage: 'La ricerca non è stata completata. Verifica il messaggio di errore e riprova.',
|
||||
|
|
@ -45,6 +46,7 @@ const copy = {
|
|||
redirectError: 'Impossibile generare il link di ritorno.',
|
||||
chooseSelfie: 'Seleziona un selfie prima di avviare la ricerca.',
|
||||
raceDataUnavailable: 'I dati FaceAI non sono disponibili per questa gara.',
|
||||
invalidRaceData: 'I dati della gara ricevuti non sono validi. Torna alla pagina gara e riapri Face ID dalla gara corretta.',
|
||||
searchCreateError: 'Impossibile avviare la ricerca.',
|
||||
faceAiAlt: 'FaceAI',
|
||||
dropzoneDisabled: 'Il caricamento non è disponibile per questa gara.'
|
||||
|
|
@ -81,6 +83,7 @@ const copy = {
|
|||
redirectLoading: 'Redirecting to the filtered legacy page…',
|
||||
processingLoading: 'Biometric search in progress across all race photos…',
|
||||
unavailableDefault: 'FaceAI is not available for this race.',
|
||||
noFacesFoundMessage: 'No faces were detected in the uploaded image. You can return to the race page or try another selfie.',
|
||||
readyMessage: 'Select a selfie to start a search limited to the current race.',
|
||||
completedMessage: 'Search completed. Found {count} matching photos.',
|
||||
failedMessage: 'The search did not complete. Check the message and try again.',
|
||||
|
|
@ -93,6 +96,7 @@ const copy = {
|
|||
redirectError: 'Unable to build the return link.',
|
||||
chooseSelfie: 'Choose a selfie before starting the search.',
|
||||
raceDataUnavailable: 'FaceAI data is not available for this race.',
|
||||
invalidRaceData: 'The race data received for this session is invalid. Go back to the race page and reopen Face ID from the correct race.',
|
||||
searchCreateError: 'Unable to start the search.',
|
||||
faceAiAlt: 'FaceAI',
|
||||
dropzoneDisabled: 'Upload is not available for this race.'
|
||||
|
|
@ -111,6 +115,11 @@ const knownServerMessages = {
|
|||
};
|
||||
|
||||
const simulatorUrl = 'http://localhost:8080/faceai_simulator.php?raceId=101&lang=it';
|
||||
const legacyHomeUrl = 'http://localhost:8080/index.jsp';
|
||||
|
||||
function isInvalidRaceAvailability(availability) {
|
||||
return availability?.reasonCode === 'RACE_DIRECTORY_NOT_FOUND' || availability?.reasonCode === 'MISSING_RACE_STORAGE';
|
||||
}
|
||||
|
||||
export function useFaceAiHome() {
|
||||
const session = ref(null);
|
||||
|
|
@ -153,6 +162,14 @@ export function useFaceAiHome() {
|
|||
return t(fallbackKey);
|
||||
}
|
||||
|
||||
function getAvailabilityUserMessage(availability, fallbackKey = 'unavailableDefault') {
|
||||
if (isInvalidRaceAvailability(availability)) {
|
||||
return t('invalidRaceData');
|
||||
}
|
||||
|
||||
return localizeServerMessage(availability?.message, fallbackKey);
|
||||
}
|
||||
|
||||
function shouldLogFaceAiDebug() {
|
||||
return import.meta.env.DEV || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
|
||||
}
|
||||
|
|
@ -176,6 +193,24 @@ export function useFaceAiHome() {
|
|||
console.groupEnd();
|
||||
}
|
||||
|
||||
function reportInvalidRaceAvailability(availability) {
|
||||
if (!isInvalidRaceAvailability(availability)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const details = {
|
||||
raceId: session.value?.race?.id || null,
|
||||
raceName: session.value?.race?.name || null,
|
||||
lang: session.value?.lang || currentLocale.value,
|
||||
reasonCode: availability.reasonCode,
|
||||
message: availability.message,
|
||||
storage: availability.storage || null,
|
||||
raceDir: availability.raceDir || null
|
||||
};
|
||||
|
||||
console.error(`[FaceAI] Invalid race data: ${JSON.stringify(details)}`);
|
||||
}
|
||||
|
||||
const isWorking = computed(() => loading.value || isSubmitting.value || isRedirecting.value || activeSearch.value?.status === 'processing');
|
||||
const isProcessingSearch = computed(() => isSubmitting.value || activeSearch.value?.status === 'processing');
|
||||
const raceAvailability = computed(() => session.value?.availability || null);
|
||||
|
|
@ -245,13 +280,17 @@ export function useFaceAiHome() {
|
|||
const statusLabel = computed(() => {
|
||||
if (!activeSearch.value) {
|
||||
if (session.value && raceAvailability.value && !raceAvailability.value.available) {
|
||||
return localizeServerMessage(raceAvailability.value.message, 'unavailableDefault');
|
||||
return getAvailabilityUserMessage(raceAvailability.value, 'unavailableDefault');
|
||||
}
|
||||
|
||||
return t('readyMessage');
|
||||
}
|
||||
|
||||
if (activeSearch.value.status === 'completed') {
|
||||
if (activeSearch.value.completionCode === 'NO_FACES_FOUND') {
|
||||
return t('noFacesFoundMessage');
|
||||
}
|
||||
|
||||
return t('completedMessage', { count: activeSearch.value.matchCount ?? 0 });
|
||||
}
|
||||
|
||||
|
|
@ -347,13 +386,21 @@ export function useFaceAiHome() {
|
|||
const response = await fetch('/api/session', { credentials: 'include' });
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
loading.value = false;
|
||||
logFaceAiDebug('Session load failed', { status: response.status });
|
||||
logFaceAiDebug('Session load failed', { status: response.status, payload });
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
window.location.replace(payload.redirectUrl || legacyHomeUrl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
session.value = await response.json();
|
||||
loading.value = false;
|
||||
if (session.value?.availability && !session.value.availability.available && isInvalidRaceAvailability(session.value.availability)) {
|
||||
errorMessage.value = getAvailabilityUserMessage(session.value.availability, 'invalidRaceData');
|
||||
reportInvalidRaceAvailability(session.value.availability);
|
||||
}
|
||||
logFaceAiDebug('Session loaded');
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +423,14 @@ export function useFaceAiHome() {
|
|||
|
||||
if (activeSearch.value.status === 'completed') {
|
||||
isSubmitting.value = false;
|
||||
if (activeSearch.value.completionCode === 'NO_FACES_FOUND') {
|
||||
isRedirecting.value = false;
|
||||
redirectUrl.value = '';
|
||||
clearSelectedFile();
|
||||
logFaceAiDebug('Search completed without detectable faces', { searchId });
|
||||
return;
|
||||
}
|
||||
|
||||
const redirectResponse = await fetch(`/api/searches/${searchId}/redirect`, { credentials: 'include' });
|
||||
const payload = await redirectResponse.json();
|
||||
if (!redirectResponse.ok) {
|
||||
|
|
@ -408,7 +463,7 @@ export function useFaceAiHome() {
|
|||
}
|
||||
|
||||
if (!session.value?.access?.faceAiAllowed || !raceAvailability.value?.available) {
|
||||
errorMessage.value = localizeServerMessage(raceAvailability.value?.message, 'raceDataUnavailable');
|
||||
errorMessage.value = getAvailabilityUserMessage(raceAvailability.value, 'raceDataUnavailable');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue