fix(noter): en ny note taber ikke det, man skriver i den
Serveren tømmer `body` på listerækker med vilje, så en tom krop var sidens tegn på "det her er en række, hent noten hel". En nyoprettet note er også tom — og hel — så den blev sendt samme vej: editoren blev pillet af skærmen, noten hentet igen, og editoren sat op på ny. I det hul er der ingen valgt note, og save() går tavst tilbage uden en. Skrev man der, forsvandt teksten sporløst: ingen fejl, ingen toast, bare en tom note. Svaret på oprettelsen var hele noten hele tiden, så opslaget var også overflødigt. Det er samtidig grunden til, at søgeprøven var ustabil. Dens værn var en ventetid på "Gemt", og den tekst er hvilestanden — feltet siger "Gemmer" mens en gemning kører og "Gemt" ellers, altså også før den første gemning er begyndt. Prøven fik grønt med det samme og målte ingenting; i CI var maskinen langsom nok til at ramme hullet bagefter. Den venter nu på et tomt felt før den skriver, og på rækken i listen bagefter. Den nye prøve tæller opslag frem for at måle et blink: et blink ville kræve en prøve, der er hurtigere end programmet, hvilket er præcis den fejl den lukker. Efterprøvet mod den gamle kode — den fejler på `expect(fetched).toEqual([])`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
de673260a3
commit
9ed6f49589
+57
-5
@@ -4657,16 +4657,23 @@ test('en søgning i ⌘K efterlader de træffere, den fandt', async ({ page }) =
|
|||||||
// Gemt ved at forlade feltet, som resten af fladen gør det — der er ingen
|
// Gemt ved at forlade feltet, som resten af fladen gør det — der er ingen
|
||||||
// Gem-knap at huske.
|
// Gem-knap at huske.
|
||||||
//
|
//
|
||||||
// Der ventes på "Gemt", før den næste note laves. Uden det klikkes "Ny note",
|
// Der ventes på et TOMT tekstfelt, før der skrives. Uden det kan udfyldningen
|
||||||
// mens den forrige stadig er undervejs, og listen når ikke at få den med — det
|
// ramme den forrige notes felt, mens den nye er undervejs, og så bliver teksten
|
||||||
// fejlede i CI én gang ud af tre kørsler, og bestod hver gang her på maskinen.
|
// enten skrevet på den forkerte note eller tabt undervejs.
|
||||||
// En prøve, der er hurtigere end programmet, måler maskinen den kører på.
|
//
|
||||||
|
// Og der ventes IKKE på "Gemt": den tekst er hvilestanden, ikke et signal.
|
||||||
|
// Feltet siger "Gemmer" mens en gemning kører og "Gemt" ellers — altså også før
|
||||||
|
// den første gemning overhovedet er begyndt. En prøve, der venter på den, får
|
||||||
|
// grønt med det samme og måler ingenting. Det var den fejl, der gjorde den her
|
||||||
|
// prøve ustabil: rettelsen var en ventetid, der ikke kunne vente på noget.
|
||||||
|
// Rækken i listen er det rigtige tegn — den kommer først, når serveren har
|
||||||
|
// svaret.
|
||||||
for (const title of ['Fyrreskov nord', 'Fyrreskov syd', 'Egeskov']) {
|
for (const title of ['Fyrreskov nord', 'Fyrreskov syd', 'Egeskov']) {
|
||||||
await page.getByRole('button', { name: 'Ny note' }).click();
|
await page.getByRole('button', { name: 'Ny note' }).click();
|
||||||
const body = page.getByLabel('Notens tekst');
|
const body = page.getByLabel('Notens tekst');
|
||||||
|
await expect(body).toHaveText('');
|
||||||
await body.fill(`${title}\n\nnoget om den`);
|
await body.fill(`${title}\n\nnoget om den`);
|
||||||
await body.blur();
|
await body.blur();
|
||||||
await expect(page.getByText('Gemt', { exact: true })).toBeVisible();
|
|
||||||
await expect(page.locator('.list').getByText(title, { exact: true })).toBeVisible();
|
await expect(page.locator('.list').getByText(title, { exact: true })).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4696,6 +4703,51 @@ test('en søgning i ⌘K efterlader de træffere, den fandt', async ({ page }) =
|
|||||||
|
|
||||||
expect(trouble).toEqual([]);
|
expect(trouble).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* En ny note åbnes med det samme, uden at editoren forsvinder undervejs.
|
||||||
|
*
|
||||||
|
* Serveren tømmer `body` på listerækker med vilje, og siden brugte den tomme krop
|
||||||
|
* som tegn på "det her er en række, hent noten hel". En nyoprettet note er også
|
||||||
|
* tom — og hel — så den blev sendt samme vej: editoren blev pillet af skærmen,
|
||||||
|
* noten hentet igen, og editoren sat op på ny.
|
||||||
|
*
|
||||||
|
* Det hul var ikke kun et blink. Mens det stod åbent, var der ingen valgt note, og
|
||||||
|
* gemningen går tavst tilbage uden en. Skrev man i det sekund, var teksten væk —
|
||||||
|
* ingen fejl, ingen toast, bare en tom note. Det er også det, der gjorde
|
||||||
|
* søgeprøven ovenfor ustabil: i CI var maskinen langsom nok til at ramme hullet.
|
||||||
|
*
|
||||||
|
* Prøven tæller opslagene frem for at måle et blink. Et blink er en tidsting og
|
||||||
|
* ville kræve, at prøven var hurtigere end programmet — præcis den fejl, den er
|
||||||
|
* skrevet for at lukke. Et opslag, der ikke sker, er et tal.
|
||||||
|
*/
|
||||||
|
test('en ny note hentes ikke igen, når den lige er lavet', async ({ page }) => {
|
||||||
|
const trouble = watchForTrouble(page);
|
||||||
|
|
||||||
|
const fetched = [];
|
||||||
|
page.on('request', (r) => {
|
||||||
|
// Selve noten, ikke dens delinger: /notes/<id> og ikke /notes/<id>/shares.
|
||||||
|
const m = new URL(r.url()).pathname.match(/^\/api\/v1\/notes\/([0-9a-f-]+)$/);
|
||||||
|
if (r.method() === 'GET' && m) fetched.push(m[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.goto('/noter');
|
||||||
|
await page.getByRole('button', { name: 'Ny note' }).click();
|
||||||
|
|
||||||
|
// Editoren er der, og den er tom — ikke væk og på vej tilbage.
|
||||||
|
const body = page.getByLabel('Notens tekst');
|
||||||
|
await expect(body).toHaveText('');
|
||||||
|
|
||||||
|
await body.fill('Grantræ\n\nnoget om det');
|
||||||
|
await body.blur();
|
||||||
|
await expect(page.locator('.list').getByText('Grantræ', { exact: true })).toBeVisible();
|
||||||
|
|
||||||
|
// Noten blev aldrig hentet igen: svaret på oprettelsen var den hele.
|
||||||
|
expect(fetched).toEqual([]);
|
||||||
|
|
||||||
|
expect(trouble).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Et indsat billede kan ses i fuld størrelse og kopieres videre.
|
* Et indsat billede kan ses i fuld størrelse og kopieres videre.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -561,7 +561,17 @@
|
|||||||
* Derfor hentes den hele her. Rækken vises med det samme, så det ikke føles som
|
* Derfor hentes den hele her. Rækken vises med det samme, så det ikke føles som
|
||||||
* at vente; teksten kommer, når den er der.
|
* at vente; teksten kommer, når den er der.
|
||||||
*/
|
*/
|
||||||
async function open(note) {
|
/**
|
||||||
|
* `whole` siger, at noten allerede er hel, og at der ikke skal hentes.
|
||||||
|
*
|
||||||
|
* En tom krop bruges ellers som tegn på, at det her er en listerække — serveren
|
||||||
|
* tømmer `body` på dem med vilje. Men en *nyoprettet* note er også tom, og den
|
||||||
|
* er hel. Uden det her blev den lukket ud som en halv note: editoren blev pillet
|
||||||
|
* af skærmen, noten hentet igen, og editoren sat op på ny. I det hul står
|
||||||
|
* `selected` som null, og `save()` går tavst tilbage uden at gemme — så tekst
|
||||||
|
* skrevet der forsvandt sporløst.
|
||||||
|
*/
|
||||||
|
async function open(note, { whole = false } = {}) {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
if (!note) {
|
if (!note) {
|
||||||
selectedId = null;
|
selectedId = null;
|
||||||
@@ -577,9 +587,9 @@
|
|||||||
// id'et være det samme begge gange, så den anden aldrig blev vist. Man ville
|
// id'et være det samme begge gange, så den anden aldrig blev vist. Man ville
|
||||||
// sidde med en tom note, der lige havde haft en titel.
|
// sidde med en tom note, der lige havde haft en titel.
|
||||||
selectedId = note.id;
|
selectedId = note.id;
|
||||||
if (note.body) {
|
if (whole || note.body) {
|
||||||
selected = note;
|
selected = note;
|
||||||
draft = note.body;
|
draft = note.body ?? '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selected = null;
|
selected = null;
|
||||||
@@ -691,7 +701,8 @@
|
|||||||
try {
|
try {
|
||||||
const note = await api.createNote({ body: '' });
|
const note = await api.createNote({ body: '' });
|
||||||
notes = [note, ...notes];
|
notes = [note, ...notes];
|
||||||
open(note);
|
// Svaret er hele noten, så den skal ikke hentes igen — se open().
|
||||||
|
await open(note, { whole: true });
|
||||||
document.querySelector('.editor textarea')?.focus();
|
document.querySelector('.editor textarea')?.focus();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
app.toast(humanMessage(e));
|
app.toast(humanMessage(e));
|
||||||
|
|||||||
Reference in New Issue
Block a user