Files
mabibli/MaBibli.Tests/RafaleIsbnTests.cs
T
mathieu 42dec0dbd1 - Catalogage rapide (douchette, code-barres)
- Cataloguer en rafale — nouvel écran /ajout/rafale : on scanne une pile de livres à la suite dans une zone de texte, chaque code est traité (BnF puis OpenLibrary), les doublons connus sont passés automatiquement. La collecte marche même hors-ligne. Le compte rendu liste maintenant les livres créés, en lien vers leur fiche, et reste consultable en revenant sur l'écran même après une rafale entièrement réussie. Le catalogue reconnaît un ISBN dans sa barre de recherche (13 ou 10 chiffres, avec ou sans tirets) : scanner un livre en main ouvre directement sa fiche s'il n'y en a qu'un. Un bouton « Scanner » l'alimente, actif hors-ligne.
- Ajouter un tome à une série accepte aussi un ISBN dans le champ manuel : le catalogue est cherché d'abord (rattachement direct si un seul exemplaire), sinon la BnF prend le relais.
Séries et sagas
- Numéro de tome distinct de la position de lecture : on peut indiquer « c'est le tome 7 » même si on ne possède pas les six premiers ; l'ordre de lecture reste un réglage séparé (utile pour les préquelles).
- Tri par numéro en plus du tri par ordre de lecture quand des tomes en portent un.
- Panneau « Ajouter » regroupé et repliable sur la fiche d'une série (manuellement / en rafale / depuis le catalogue / depuis les envies), au lieu de quatre formulaires ouverts en permanence.
- Filtre catalogue « sans couverture » pour repérer les livres à illustrer.
Le catalogue groupe les tomes d'une même série sous un bloc repliable, avec un décompte plus clair (affichés / possédés / total).
- Corrections directes sur la fiche
- Effacer un prêt saisi par erreur (bouton ✕ sur chaque ligne, avec confirmation), sans passer par « rendre ».
- Corriger une couverture manquante ou cassée en cliquant dessus : le champ d'adresse s'ouvre focalisé, Entrée enregistre. Étendu aux numéros de revue dans la dernière modification.
- Les thèmes déjà utilisés dans la bibliothèque sont proposés à la frappe.
- La recherche d'un livre à rattacher montre des suggestions dès le focus, sans attendre de taper.

- Visuel : un rendu manquant après une écriture asynchrone dans le formulaire de livre, une bascule de rôle cassée, des débordements à 320 px, et le style d'un bouton-lien qui restait souligné.
2026-09-09 00:05:26 +02:00

134 lines
4.3 KiB
C#

using MaBibli.Shared.Catalogue;
namespace MaBibli.Tests;
/// <summary>
/// La file de catalogage en rafale : découpe de la saisie, et comptes du compte rendu.
/// </summary>
public class RafaleIsbnTests
{
[Fact]
public void Un_code_par_ligne()
{
Assert.Equal(
["9782070612758", "9782253004226"],
SaisieRafale.Decouper("9782070612758\n9782253004226"));
}
[Fact]
public void Les_lignes_vides_et_les_retours_windows_sont_tolerés()
{
Assert.Equal(
["1112223334445", "5554443332221"],
SaisieRafale.Decouper("1112223334445\r\n\r\n5554443332221\r\n"));
}
[Fact]
public void Les_tirets_et_espaces_de_la_douchette_disparaissent()
{
// Une douchette tape des chiffres, mais une saisie manuelle peut recopier la forme
// imprimée : la normalisation est la même que celle d'IsbnUtils.
Assert.Equal(["9782070612758"], SaisieRafale.Decouper("978-2-07-061275-8"));
}
[Fact]
public void Le_X_final_d_un_isbn10_survit()
{
Assert.Equal(["222403313X"], SaisieRafale.Decouper("222403313x"));
}
[Fact]
public void Un_code_scanne_deux_fois_n_entre_qu_une_fois()
{
// ⚠️ Rescanner par mégarde est le geste le plus banal d'une rafale. Interroger la BnF
// deux fois pour le même code ne peut rien apporter.
Assert.Equal(
["9782070612758", "9782253004226"],
SaisieRafale.Decouper("9782070612758\n9782253004226\n9782070612758"));
}
[Fact]
public void L_ordre_de_saisie_est_conserve()
{
// On repasse sur la pile dans l'ordre où on l'a scannée : c'est ce qui permet de
// retrouver le livre suivant sur la table.
Assert.Equal(["333", "111", "222"], SaisieRafale.Decouper("333\n111\n222"));
}
[Fact]
public void Une_saisie_vide_ne_donne_aucun_code()
{
Assert.Empty(SaisieRafale.Decouper(null));
Assert.Empty(SaisieRafale.Decouper(" \n\n "));
}
private static Rafale Rafale(params EtatCodeRafale[] etats) => new()
{
Codes = [.. etats.Select((e, i) => new CodeRafale { Code = $"code{i}", Etat = e })],
};
[Fact]
public void Le_pourcentage_ne_compte_que_ce_qui_est_traite()
{
var rafale = Rafale(
EtatCodeRafale.Cree, EtatCodeRafale.Passe,
EtatCodeRafale.ATraiter, EtatCodeRafale.ATraiter);
Assert.Equal(50, rafale.Pourcentage);
Assert.True(rafale.ResteATraiter);
}
[Fact]
public void Une_rafale_vide_ne_divise_pas_par_zero()
{
Assert.Equal(0, new Rafale().Pourcentage);
}
[Fact]
public void Les_residus_sont_ce_qui_attend_une_decision()
{
var rafale = Rafale(
EtatCodeRafale.Cree, EtatCodeRafale.Passe, EtatCodeRafale.AChoisir,
EtatCodeRafale.Introuvable, EtatCodeRafale.Revue, EtatCodeRafale.Echec);
// ⚠️ Ni les créés ni les passés : ils sont terminés, et les rappeler ferait croire
// qu'il reste du travail dessus.
Assert.Equal(4, rafale.Residus.Count);
Assert.All(rafale.Residus, c => Assert.False(c.Termine));
}
[Fact]
public void Les_passes_se_comptent_a_part_des_crees()
{
// ⚠️ C'est ce qui empêche de croire qu'on a ajouté cinquante livres quand on en a
// ajouté quarante-deux : posséder deux exemplaires est légitime, passer en silence non.
var rafale = Rafale(
EtatCodeRafale.Cree, EtatCodeRafale.Cree, EtatCodeRafale.Passe);
Assert.Equal(2, rafale.Crees);
Assert.Equal(1, rafale.Passes);
}
[Fact]
public void Passer_les_doublons_est_coche_par_defaut()
{
Assert.True(new Rafale().PasserLesDoublons);
}
[Fact]
public void Un_code_cree_ou_passe_est_termine_les_autres_non()
{
Assert.True(new CodeRafale { Code = "x", Etat = EtatCodeRafale.Cree }.Termine);
Assert.True(new CodeRafale { Code = "x", Etat = EtatCodeRafale.Passe }.Termine);
foreach (var etat in new[]
{
EtatCodeRafale.ATraiter, EtatCodeRafale.AChoisir,
EtatCodeRafale.Introuvable, EtatCodeRafale.Revue, EtatCodeRafale.Echec,
})
{
Assert.False(new CodeRafale { Code = "x", Etat = etat }.Termine);
}
}
}