Files
termanager2/tests/js/scelta.test.mjs
Francesco Picone fda428f242 ++ scelta di territori e proclamatori con ricerca
Al posto delle tendine (Assegna, Registro, editor delle piantine) un
campo in cui si scrive e compaiono le proposte più vicine: uguale, inizia
con, contiene, errore di battitura ("forse cercavi"); parole in qualsiasi
ordine, senza badare a maiuscole e accenti. Campo vuoto: la tendina
completa. Fatto anche per il telefono (16px, voci da 44px, scelta al tocco).

- Logica pura in resources/js/scelta.js con test node (tests/js).
- Opzioni dal server: Territorio/Proclamatore::opzioneScelta(); i
  territori già assegnati si trovano ("già assegnato a …") ma non si
  scelgono. Nomi cifrati ordinati e cercati decifrati, mai in SQL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:35:56 +02:00

99 lines
4.4 KiB
JavaScript

// Prove della ricerca nei campi di scelta (resources/js/scelta.js).
// Si eseguono con: node --test tests/js/
// Gli esempi sono quelli concordati con l'utente il 19 ottobre 2026.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { proponi, normalizza, distanza } from '../../resources/js/scelta.js';
const territorio = (numero, zona = 'Montepellegrino', tipologia = 'Residenziale', motivo) => ({
valore: numero, etichetta: `N° ${numero}`, dettaglio: `${zona} (${tipologia})`,
chiavi: [numero, zona, tipologia], ...(motivo ? { motivo } : {}),
});
const proclamatore = (cognome, nome, motivo) => ({
valore: `${cognome}-${nome}`, etichetta: `${cognome} ${nome}`, chiavi: [cognome, nome], ...(motivo ? { motivo } : {}),
});
const etichette = (risultati) => risultati.map((o) => o.etichetta);
const territori = [
territorio('12', 'Zisa'), territorio('35'), territorio('135', 'Noce'), territorio('235', 'Cuba'),
territorio('350'), territorio('351'), territorio('36'),
];
const proclamatori = [
proclamatore('Bianchi', 'Rosa'), proclamatore('Grosso', 'Luca'), proclamatore('Neri', 'Nicolò'),
proclamatore('Rosselli', 'Anna'), proclamatore('Rossi', 'Mario'), proclamatore('Verdi', 'Paolo'),
];
test('esempio 1: "35" mette prima l\'uguale, poi chi inizia, poi chi contiene', () => {
assert.deepEqual(etichette(proponi(territori, '35')), ['N° 35', 'N° 350', 'N° 351', 'N° 135', 'N° 235']);
});
test('i numeri brevi non hanno tolleranza: "35" non trova il 36', () => {
assert.ok(!etichette(proponi(territori, '35')).includes('N° 36'));
});
test('esempio 1: "monte" trova i territori della zona Montepellegrino', () => {
assert.deepEqual(etichette(proponi(territori, 'monte')), ['N° 35', 'N° 350', 'N° 351', 'N° 36']);
});
test('esempio 2: "ros" mette prima il cognome, poi il nome, poi chi contiene', () => {
assert.deepEqual(etichette(proponi(proclamatori, 'ros')), ['Rosselli Anna', 'Rossi Mario', 'Bianchi Rosa', 'Grosso Luca']);
});
test('maiuscole e accenti non contano', () => {
assert.deepEqual(etichette(proponi(proclamatori, 'NICOLO')), ['Neri Nicolò']);
assert.equal(normalizza(' Nicolò '), 'nicolo');
});
test('nome e cognome in qualsiasi ordine', () => {
assert.deepEqual(etichette(proponi(proclamatori, 'mario ros')), ['Rossi Mario']);
assert.deepEqual(etichette(proponi(proclamatori, 'rossi mario')), ['Rossi Mario']);
});
test('esempio 3: "rosi" propone Rossi come "forse cercavi"', () => {
const risultati = proponi(proclamatori, 'rosi');
const rossi = risultati.find((o) => o.etichetta === 'Rossi Mario');
assert.ok(rossi, 'Rossi Mario deve essere proposto');
assert.equal(rossi.forse, true);
});
test('una corrispondenza vera viene prima di un errore di battitura', () => {
const elenco = [proclamatore('Rossi', 'Mario'), proclamatore('Rosi', 'Carla')];
const risultati = proponi(elenco, 'rosi');
assert.equal(risultati[0].etichetta, 'Rosi Carla');
assert.equal(risultati[0].forse, false);
});
test('campo vuoto: la tendina completa, senza le voci non sceglibili', () => {
const elenco = [territorio('7'), territorio('8', 'Zisa', 'Residenziale', 'già assegnato a Rossi Mario')];
assert.deepEqual(etichette(proponi(elenco, '')), ['N° 7']);
assert.deepEqual(etichette(proponi(elenco, ' ')), ['N° 7']);
});
test('cercando, le voci non sceglibili compaiono con il motivo', () => {
const elenco = [territorio('7'), territorio('8', 'Zisa', 'Residenziale', 'già assegnato a Rossi Mario')];
const [occupato] = proponi(elenco, '8');
assert.equal(occupato.etichetta, 'N° 8');
assert.equal(occupato.motivo, 'già assegnato a Rossi Mario');
});
test('le opzioni speciali restano sempre in cima', () => {
const elenco = [
{ valore: '', etichetta: '— nessun territorio —', speciale: true },
{ valore: 'nuovo', etichetta: '+ Crea un territorio nuovo', speciale: true },
territorio('35'), territorio('12', 'Zisa'),
];
assert.deepEqual(etichette(proponi(elenco, 'zisa')), ['— nessun territorio —', '+ Crea un territorio nuovo', 'N° 12']);
});
test('nessun risultato: elenco vuoto', () => {
assert.deepEqual(proponi(proclamatori, 'zzzz'), []);
});
test('distanza di modifica', () => {
assert.equal(distanza('rosi', 'rossi'), 1);
assert.equal(distanza('kitten', 'sitting', 3), 3);
assert.equal(distanza('abc', 'abcdef', 1), 2); // oltre il limite: limite + 1
});