test: /runda round 2 — pin TeachingEcho kind + cat-3 prose wiring
Second Devil's-Advocate pass over the now-complete ADR-0038 closes
three minor test-coverage gaps the polish (2aab457) left behind. No
production code changes; src/app.rs only, +98 lines of tests.
* bucket_a_success_events_render_the_teaching_echo_beneath_ok and
bucket_b_multi_line_echo_renders_one_line_per_statement_beneath_ok
only checked line *text*. After the polish, every echo line is
pushed via `push_teaching_echo` and carries
`OutputKind::TeachingEcho` — the kind is what makes
`ui::render_output_line` fire the dim-prefix + advanced-lex
branch. Without a kind assertion, a future refactor that regressed
`push_teaching_echo` to emit `System` would leave the text intact
but silently break the styling. The `assert_echo_beneath_ok`
helper now pins kind == TeachingEcho on every event arm covered
by the bucket_a test, and the bucket_b test asserts the same for
each of the three multi-statement lines.
* add_column_client_side_notes_render_as_category_three_prose (new)
pins the broader-scope polish: `handle_dsl_add_column_success`'s
illuminating client_side_notes (shortid / serial auto-fill,
per `client_side.auto_fill_*` keys) now route through
`push_category_three_prose`, producing a System line with a
whole-text Hint span. The user-confirmed scope extension was
recorded in ADR-0038's Status block; this test makes the wiring
enforceable. The closely-related caveat path was already pinned
by polished_echo_carries_teaching_echo_kind_and_caveat_a_hint_span;
this completes the cat-3 prose coverage symmetrically.
Tests: 2020 passed / 0 failed / 1 ignored (pre-existing); clippy
clean (`--all-targets -D warnings`, nursery). Nothing to escalate.
This commit is contained in:
+98
@@ -3011,6 +3011,19 @@ mod tests {
|
|||||||
.expect("an echo line");
|
.expect("an echo line");
|
||||||
assert_eq!(echo_idx, ok_idx + 1, "echo sits immediately beneath [ok]: {texts:?}");
|
assert_eq!(echo_idx, ok_idx + 1, "echo sits immediately beneath [ok]: {texts:?}");
|
||||||
assert!(texts[echo_idx].contains(expected), "echo carries the SQL: {texts:?}");
|
assert!(texts[echo_idx].contains(expected), "echo carries the SQL: {texts:?}");
|
||||||
|
// ADR-0038 §4 polish: every success arm now wires the echo as
|
||||||
|
// `OutputKind::TeachingEcho` so `ui::render_output_line` fires
|
||||||
|
// the dim-prefix + advanced-lex custom branch. Pinning this
|
||||||
|
// here guards every event-arm wiring covered by this test —
|
||||||
|
// a future refactor that regressed `push_teaching_echo` to
|
||||||
|
// emit `System` would leave the text intact but break the
|
||||||
|
// styling, and would be caught here.
|
||||||
|
assert_eq!(
|
||||||
|
app.output[echo_idx].kind,
|
||||||
|
OutputKind::TeachingEcho,
|
||||||
|
"echo line carries TeachingEcho kind: {:?}",
|
||||||
|
app.output[echo_idx],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn empty_data() -> DataResult {
|
fn empty_data() -> DataResult {
|
||||||
@@ -3122,6 +3135,79 @@ mod tests {
|
|||||||
assert_echo_beneath_ok(&app, "ALTER TABLE T ALTER COLUMN c SET DATA TYPE text");
|
assert_echo_beneath_ok(&app, "ALTER TABLE T ALTER COLUMN c SET DATA TYPE text");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_column_client_side_notes_render_as_category_three_prose() {
|
||||||
|
// ADR-0038 §4 polish (broader scope): the existing illuminating
|
||||||
|
// `client_side_notes` on an `AddColumnResult` (e.g. the shortid
|
||||||
|
// / serial auto-fill messages) now route through
|
||||||
|
// `push_category_three_prose` — a System line with a whole-text
|
||||||
|
// Hint span — so every category-3 prose line renders dim
|
||||||
|
// consistently per §6, not just the new DontConvert caveat.
|
||||||
|
//
|
||||||
|
// The broader scope was user-confirmed in the polish session
|
||||||
|
// (see ADR-0038 Status); this test pins that wiring so a
|
||||||
|
// regression to plain `note_system` would be caught.
|
||||||
|
use crate::db::{AddColumnResult, ColumnDescription};
|
||||||
|
|
||||||
|
let mut app = App::new();
|
||||||
|
app.update(AppEvent::DslAddColumnSucceeded {
|
||||||
|
command: Command::AddColumn {
|
||||||
|
table: "Customers".to_string(),
|
||||||
|
column: "code".to_string(),
|
||||||
|
ty: Type::ShortId,
|
||||||
|
not_null: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
|
},
|
||||||
|
result: AddColumnResult {
|
||||||
|
description: TableDescription {
|
||||||
|
name: "Customers".to_string(),
|
||||||
|
columns: vec![ColumnDescription {
|
||||||
|
name: "code".to_string(),
|
||||||
|
user_type: Some(Type::ShortId),
|
||||||
|
sqlite_type: "TEXT".to_string(),
|
||||||
|
notnull: false,
|
||||||
|
primary_key: false,
|
||||||
|
unique: false,
|
||||||
|
default: None,
|
||||||
|
check: None,
|
||||||
|
}],
|
||||||
|
outbound_relationships: Vec::new(),
|
||||||
|
inbound_relationships: Vec::new(),
|
||||||
|
indexes: Vec::new(),
|
||||||
|
unique_constraints: Vec::new(),
|
||||||
|
check_constraints: Vec::new(),
|
||||||
|
},
|
||||||
|
// A representative illuminating note — the wording is
|
||||||
|
// the one the worker would emit via the
|
||||||
|
// `client_side.auto_fill_add_shortid` i18n key.
|
||||||
|
client_side_notes: vec![
|
||||||
|
"[client-side] 5 row(s) given auto-generated shortid values. In raw SQL this would need an explicit UPDATE to populate.".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
echo: None, // simple-mode submission, no echo
|
||||||
|
});
|
||||||
|
|
||||||
|
let note_line = app
|
||||||
|
.output
|
||||||
|
.iter()
|
||||||
|
.find(|l| l.text.starts_with("[client-side]"))
|
||||||
|
.expect("the illuminating client_side note");
|
||||||
|
assert_eq!(note_line.kind, OutputKind::System);
|
||||||
|
let runs = note_line
|
||||||
|
.styled_runs
|
||||||
|
.as_ref()
|
||||||
|
.expect("client_side note carries a styled-runs payload after the polish");
|
||||||
|
assert_eq!(runs.len(), 1);
|
||||||
|
assert_eq!(runs[0].class, OutputStyleClass::Hint);
|
||||||
|
assert_eq!(
|
||||||
|
runs[0].byte_range,
|
||||||
|
(0, note_line.text.len()),
|
||||||
|
"the dim span covers the whole prose body — same shape as the caveat",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn polished_echo_carries_teaching_echo_kind_and_caveat_a_hint_span() {
|
fn polished_echo_carries_teaching_echo_kind_and_caveat_a_hint_span() {
|
||||||
// ADR-0038 §4 styled-runs polish: the App-side wiring places
|
// ADR-0038 §4 styled-runs polish: the App-side wiring places
|
||||||
@@ -3310,6 +3396,18 @@ mod tests {
|
|||||||
texts[ok_idx + 2].contains("Executing SQL: DROP INDEX Customers_Email_Day_idx"),
|
texts[ok_idx + 2].contains("Executing SQL: DROP INDEX Customers_Email_Day_idx"),
|
||||||
"second echo line: {texts:?}",
|
"second echo line: {texts:?}",
|
||||||
);
|
);
|
||||||
|
// ADR-0038 §4 polish: every one of the multi-statement echo lines
|
||||||
|
// carries TeachingEcho — the polish styling fires per line. A
|
||||||
|
// regression that pushed the multi-line case as System would
|
||||||
|
// leave the text intact but break the per-line styling.
|
||||||
|
for (offset, label) in [(1, "first"), (2, "second"), (3, "third")] {
|
||||||
|
assert_eq!(
|
||||||
|
app.output[ok_idx + offset].kind,
|
||||||
|
OutputKind::TeachingEcho,
|
||||||
|
"{label} echo line carries TeachingEcho: {:?}",
|
||||||
|
app.output[ok_idx + offset],
|
||||||
|
);
|
||||||
|
}
|
||||||
assert!(
|
assert!(
|
||||||
texts[ok_idx + 3]
|
texts[ok_idx + 3]
|
||||||
.contains("Executing SQL: ALTER TABLE Customers DROP COLUMN Email"),
|
.contains("Executing SQL: ALTER TABLE Customers DROP COLUMN Email"),
|
||||||
|
|||||||
Reference in New Issue
Block a user