Expand drawing widths and quarantine live-feed test

This commit is contained in:
Chris Amow 2026-08-13 03:54:28 -05:00
parent 22a638cf73
commit 0e2d5fa2cb
5 changed files with 28 additions and 8 deletions

View file

@ -69,7 +69,7 @@ class LineCreate(BaseModel):
note: str = "" note: str = ""
hidden: bool = False hidden: bool = False
color: str = Field("#65b7cf", pattern=r"^#[0-9a-fA-F]{6}$") color: str = Field("#65b7cf", pattern=r"^#[0-9a-fA-F]{6}$")
line_width: int = Field(2, ge=1, le=4) line_width: int = Field(2, ge=1, le=9)
cutoff_t: int | None = None cutoff_t: int | None = None
armed: bool = True armed: bool = True
@ -86,7 +86,7 @@ class PriceAlertCreate(BaseModel):
note: str = "" note: str = ""
tf: Timeframe = Timeframe.D1 tf: Timeframe = Timeframe.D1
color: str = Field("#e0a34a", pattern=r"^#[0-9a-fA-F]{6}$") color: str = Field("#e0a34a", pattern=r"^#[0-9a-fA-F]{6}$")
line_width: int = Field(2, ge=1, le=4) line_width: int = Field(2, ge=1, le=9)
class LinePatch(BaseModel): class LinePatch(BaseModel):
@ -94,7 +94,7 @@ class LinePatch(BaseModel):
note: str | None = None note: str | None = None
hidden: bool | None = None hidden: bool | None = None
color: str | None = Field(None, pattern=r"^#[0-9a-fA-F]{6}$") color: str | None = Field(None, pattern=r"^#[0-9a-fA-F]{6}$")
line_width: int | None = Field(None, ge=1, le=4) line_width: int | None = Field(None, ge=1, le=9)
anchor_t: int | None = None anchor_t: int | None = None
anchor_p: float | None = None anchor_p: float | None = None
slope: float | None = None slope: float | None = None

View file

@ -753,7 +753,7 @@ re-run is indistinguishable from a fix.
### 2026-08-11 — flaky browser cases quarantined ### 2026-08-11 — flaky browser cases quarantined
The four cases named above are skipped rather than allowed to make the full The cases named above are skipped rather than allowed to make the full
suite nondeterministic. The symbol failure was reproduced: an older persisted, suite nondeterministic. The symbol failure was reproduced: an older persisted,
off-screen symbol occupied the same edge position and intercepted the click off-screen symbol occupied the same edge position and intercepted the click
intended for the symbol created by the test. That test is unsound while it intended for the symbol created by the test. That test is unsound while it
@ -763,6 +763,13 @@ before a multi-step gesture, so they need stable fixture data or stronger
gesture-local targeting. The diagnostic capture case needs deterministic gesture-local targeting. The diagnostic capture case needs deterministic
display-media and upload-completion boundaries. display-media and upload-completion boundaries.
The live-edge viewport case joined the quarantine after the same pattern was
observed directly: its helper reads candle data and the visible range in
separate chart API calls while the live feed can update between them. It then
requires exact timestamp equality, so a legitimate new bar makes the assertion
compare two different instants. It needs one stable snapshot or a tolerance
that still catches the original ten-hour regression before it is sound.
These are explicit `node:test` skips with reasons, not deleted coverage. Re-enable These are explicit `node:test` skips with reasons, not deleted coverage. Re-enable
each case only after its stated external dependency is removed and repeated full each case only after its stated external dependency is removed and repeated full
suite runs remain green. suite runs remain green.

View file

@ -66,7 +66,7 @@
<label>Label<input v-model.trim="drawName" placeholder="optional" aria-label="Trendline label"></label> <label>Label<input v-model.trim="drawName" placeholder="optional" aria-label="Trendline label"></label>
<div class="row"> <div class="row">
<label>Colour<input type="color" v-model="drawColor" aria-label="Trendline colour"></label> <label>Colour<input type="color" v-model="drawColor" aria-label="Trendline colour"></label>
<label>Width<select v-model.number="drawWidth" aria-label="Trendline width"><option v-for="width in [1,2,3,4]" :value="width">{{ width }}px</option></select></label> <label>Width<select v-model.number="drawWidth" aria-label="Trendline width"><option v-for="width in 9" :value="width">{{ width }}px</option></select></label>
</div> </div>
<div class="row"> <div class="row">
<!-- Side is inferred from the extreme you snap to, so it only has <!-- Side is inferred from the extreme you snap to, so it only has
@ -86,7 +86,7 @@
<label>Label<input v-model.trim="alertNote" placeholder="optional" aria-label="Level label"></label> <label>Label<input v-model.trim="alertNote" placeholder="optional" aria-label="Level label"></label>
<div class="row"> <div class="row">
<label>Colour<input type="color" v-model="levelColor" aria-label="Level colour"></label> <label>Colour<input type="color" v-model="levelColor" aria-label="Level colour"></label>
<label>Width<select v-model.number="levelWidth" aria-label="Level width"><option v-for="width in [1,2,3,4]" :value="width">{{ width }}px</option></select></label> <label>Width<select v-model.number="levelWidth" aria-label="Level width"><option v-for="width in 9" :value="width">{{ width }}px</option></select></label>
</div> </div>
<form class="row price-row" @submit.prevent="addPriceAlert"> <form class="row price-row" @submit.prevent="addPriceAlert">
<label>Price<input type="number" step="0.25" v-model.number="alertPrice" :placeholder="price == null ? '0.00' : price.toFixed(2)" aria-label="Level price"></label> <label>Price<input type="number" step="0.25" v-model.number="alertPrice" :placeholder="price == null ? '0.00' : price.toFixed(2)" aria-label="Level price"></label>
@ -223,7 +223,7 @@
</details> </details>
<select :value="item.line.line_width || 2" aria-label="Drawing width" <select :value="item.line.line_width || 2" aria-label="Drawing width"
@change="updateLineStyle(item.line, {line_width: Number($event.target.value)})"> @change="updateLineStyle(item.line, {line_width: Number($event.target.value)})">
<option v-for="width in [1,2,3,4]" :value="width">{{ width }}</option> <option v-for="width in 9" :value="width">{{ width }}</option>
</select> </select>
</div> </div>
<div class="drawing-controls" @click.stop v-else> <div class="drawing-controls" @click.stop v-else>

View file

@ -139,7 +139,10 @@ test('diagnostic capture uploads a PNG and adds its capability ID to Events',
} }
}); });
test('the viewport opens on the live edge, not in the past', { timeout: 180000 }, async () => { test('the viewport opens on the live edge, not in the past', {
timeout: 180000,
skip: 'quarantined: chart data and viewport are sampled separately while the live feed advances',
}, async () => {
await withChart(async page => { await withChart(async page => {
const state = await chartState(page); const state = await chartState(page);
assert.ok(state.bars > 0, 'the chart loaded no bars at all'); assert.ok(state.bars > 0, 'the chart loaded no bars at all');

View file

@ -10,6 +10,9 @@ test('editing a drawing name with Backspace or Delete cannot delete the drawing'
const label = `e2e rename ${Date.now()}`; const label = `e2e rename ${Date.now()}`;
const box = await chartBox(page); const box = await chartBox(page);
await armTool(page, 'Trendline'); await armTool(page, 'Trendline');
assert.deepEqual(await page.locator('select[aria-label="Trendline width"] option').allTextContents(),
['1px', '2px', '3px', '4px', '5px', '6px', '7px', '8px', '9px']);
await page.selectOption('select[aria-label="Trendline width"]', '9');
await page.fill('input[aria-label="Trendline label"]', label); await page.fill('input[aria-label="Trendline label"]', label);
const first = at(box, 0.42, 0.55); const first = at(box, 0.42, 0.55);
const second = at(box, 0.62, 0.40); const second = at(box, 0.62, 0.40);
@ -31,11 +34,16 @@ test('editing a drawing name with Backspace or Delete cannot delete the drawing'
}, label); }, label);
assert.ok(created, 'the trendline was not created'); assert.ok(created, 'the trendline was not created');
assert.ok((await drawingIds(page)).includes(created), 'the trendline was not persisted'); assert.ok((await drawingIds(page)).includes(created), 'the trendline was not persisted');
assert.equal(await page.evaluate(id =>
window.__chart.levels.find(level => level.id === id)?.line_width, created), 9,
'the 9px trendline width was not persisted');
await page.fill('input[aria-label="Filter drawings by text"]', label); await page.fill('input[aria-label="Filter drawings by text"]', label);
const input = page.locator('input[aria-label="Drawing name"]'); const input = page.locator('input[aria-label="Drawing name"]');
assert.equal(await input.count(), 1, 'the unique drawing filter did not isolate the test line'); assert.equal(await input.count(), 1, 'the unique drawing filter did not isolate the test line');
const row = page.locator('.trendline-row'); const row = page.locator('.trendline-row');
assert.deepEqual(await row.locator('select[aria-label="Drawing width"] option').allTextContents(),
['1', '2', '3', '4', '5', '6', '7', '8', '9']);
const rowBox = await row.boundingBox(); const rowBox = await row.boundingBox();
assert.ok(rowBox.height <= 48, `drawing row is still ${rowBox.height}px tall`); assert.ok(rowBox.height <= 48, `drawing row is still ${rowBox.height}px tall`);
assert.equal(await row.locator('.drawing-state .fa-bell').count(), 1, assert.equal(await row.locator('.drawing-state .fa-bell').count(), 1,
@ -91,6 +99,8 @@ test('a price level selects and focuses in both directions', { timeout: 180000 }
const label = `e2e level focus ${Date.now()}`; const label = `e2e level focus ${Date.now()}`;
const price = await page.evaluate(() => window.__chart.bars.at(-1).c); const price = await page.evaluate(() => window.__chart.bars.at(-1).c);
await armTool(page, 'Price level'); await armTool(page, 'Price level');
assert.deepEqual(await page.locator('select[aria-label="Level width"] option').allTextContents(),
['1px', '2px', '3px', '4px', '5px', '6px', '7px', '8px', '9px']);
await page.fill('input[aria-label="Level label"]', label); await page.fill('input[aria-label="Level label"]', label);
await page.fill('input[aria-label="Level price"]', String(price)); await page.fill('input[aria-label="Level price"]', String(price));
await page.locator('.price-row button[type="submit"]').click(); await page.locator('.price-row button[type="submit"]').click();