test: rendre la suppression inexécutable plutôt que détectée
Trois trouvailles adverses survivaient à leur premier correctif. Elles avaient la même faiblesse : ce qui prouve le code n'exerçait pas le code. L'adaptateur n'était pas testé dans son comportement — six méthodes sur sept pouvaient être vidées avec la suite verte. Une doublure de polyfill en mémoire les exerce désormais toutes : elle RÉPOND au lieu de rendre des constantes, et elle EXÉCUTE le SPARQL, avec un analyseur qui n'accepte qu'un INSERT DATA ancré de triplets littéraux. Les six vidages ont été vérifiés rouges, entre 2 et 10 échecs chacun. Et la garde anti-suppression change de nature. Elle n'instrumentait que deux méthodes, et cinq contournements passaient — dont un littéral coupé placé dans readDeposits, qui est le chemin de la prochaine fonctionnalité. Maintenant le moteur REFUSE la requête : « expected the keyword INSERT, found DELETE ». La suppression n'est plus détectée, elle est inexécutable — ce qui ne se contourne pas par une écriture plus habile. Une nouvelle méthode est couverte par construction, sans liste à tenir : le test lit Object.keys du port. Vérifié — une huitième méthode sans pilote fait rougir. Le README disait qu'une entrée ne change jamais après sa création, alors qu'une valeur plus petite l'écrase. Remplacé par ce qui est vrai — un objet déjà indexé n'est jamais relu — avec le cas reproduit. Et « ne fait que grandir » dit désormais que la suppression n'a JAMAIS été construite, pas qu'elle a été retirée : celui qui en aura besoin doit le lire, pas le déduire d'une fonction manquante. Enfin la forme d'écriture s'aligne sur celle du polyfill — l'écriture ancrée sans clause GRAPH, le document nommé une seule fois comme ancre. buildInsertTriple ne prend plus de graphe, donc elle ne peut plus dériver.
This commit is contained in:
+20
-9
@@ -59,15 +59,26 @@ export function escapeIri(value: string): string {
|
||||
return out;
|
||||
}
|
||||
|
||||
/** One triple, added to `graph`. The only statement this package ever writes. */
|
||||
export function buildInsertTriple(
|
||||
graph: string,
|
||||
subject: string,
|
||||
predicate: string,
|
||||
value: string,
|
||||
): string {
|
||||
/**
|
||||
* One triple, for the ANCHORED default graph. The only statement this package
|
||||
* ever writes.
|
||||
*
|
||||
* No `GRAPH <…>` wrapper, and the document is not a parameter at all: it is named
|
||||
* once, as `docs.sparqlUpdate`'s anchor, which already scopes the write to that
|
||||
* repo's default graph. Naming it twice would be two chances to disagree.
|
||||
*
|
||||
* This is the polyfill's own shape, and the alignment is deliberate: it calls the
|
||||
* no-GRAPH form "the CANONICAL, always-safe shape and the one the anchored
|
||||
* default-graph read queries" (`src/surface/inbox.ts`). The anchored
|
||||
* `GRAPH <plainNuri>` form this package wrote until now ALSO round-trips — the
|
||||
* polyfill's own e2e harness verified it resolves to the same repo graph, with no
|
||||
* phantom graph — so this is not a bug being fixed. It is two layers writing the
|
||||
* same kind of data the same way, instead of leaving someone to work out later
|
||||
* whether the difference meant something.
|
||||
*/
|
||||
export function buildInsertTriple(subject: string, predicate: string, value: string): string {
|
||||
return (
|
||||
`INSERT DATA { GRAPH <${escapeIri(graph)}> ` +
|
||||
`{ <${escapeIri(subject)}> <${escapeIri(predicate)}> "${escapeLiteral(value)}" } }`
|
||||
`INSERT DATA { <${escapeIri(subject)}> <${escapeIri(predicate)}> ` +
|
||||
`"${escapeLiteral(value)}" }`
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user