diff --git a/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/after-decide-complete/estimation-infra.json b/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/after-decide-complete/estimation-infra.json index a1e13789d..436c14d71 100644 --- a/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/after-decide-complete/estimation-infra.json +++ b/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/after-decide-complete/estimation-infra.json @@ -48,6 +48,9 @@ ], "stay_if": [ "need Heroku DX indefinitely" + ], + "would_flip_if": [ + "A confirmed always-on traffic pattern would raise the AWS compute estimate materially." ] }, "workshop": { diff --git a/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/retained-execution-pack/estimation-infra.json b/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/retained-execution-pack/estimation-infra.json index a1e13789d..436c14d71 100644 --- a/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/retained-execution-pack/estimation-infra.json +++ b/plugins/aws-startup-advisor/fixtures/heroku-decision-gate/retained-execution-pack/estimation-infra.json @@ -48,6 +48,9 @@ ], "stay_if": [ "need Heroku DX indefinitely" + ], + "would_flip_if": [ + "A confirmed always-on traffic pattern would raise the AWS compute estimate materially." ] }, "workshop": { diff --git a/plugins/aws-startup-advisor/fixtures/migration-report-reference.html b/plugins/aws-startup-advisor/fixtures/migration-report-reference.html index 6f6b0a3b3..aa1027f49 100644 --- a/plugins/aws-startup-advisor/fixtures/migration-report-reference.html +++ b/plugins/aws-startup-advisor/fixtures/migration-report-reference.html @@ -170,6 +170,12 @@
Any of these would change the verdict:
\n' + + +def test_would_flip_lead_in_paragraph_before_list_passes() -> None: + # A one-sentence lead-in between the heading and theSee below.
" + ) + assert html != _reference_html() + errors = _flip_errors(html) + assert errors and "0 of 2" in errors[0], errors + + +INLINE_LABEL_BLOCK = """Go, with conditions
', + 'Go, with conditions
\n' + "Confirm these before cutover.
", + ) + + +def test_one_word_condition_only_in_prose_fails() -> None: + # Conditions render as a checklist, so the scan is scoped to rendered list + # items. A one-word condition used to be satisfied by that word anywhere in + # the summary prose and could never be reported as omitted. + validator = _load() + html, estimate = _with_condition("Confirm", rendered=False) + html = _without_confirm_in_checklist(html) + rendered = validator._rendered_fragment(validator._section_html(html, "decision-summary")) + assert any("confirm" in text for kind, text in rendered.entries if kind != "li") + assert not any("confirm" in text for kind, text in rendered.entries if kind == "li") + errors = [e for e in validator.validate_report(html, estimate, None) if "condition" in e] + assert errors, "one-word condition rendered only in prose passed" + + +def test_one_word_condition_in_checklist_passes() -> None: + validator = _load() + html, estimate = _with_condition("Confirm", rendered=False) + html = _without_confirm_in_checklist(html).replace( + "Go, with conditions
', + 'Go, with conditions
', + ) + assert html != _reference_html() + errors = validator.validate_report(html, _reference_estimate(), None) + assert any("verdict-headline" in err for err in errors), errors + + +def test_metric_hero_only_in_template_fails() -> None: + validator = _load() + html = _reference_html().replace('Go, with conditions
', + 'Go, with conditions
Go, with conditions
', replacement + ) + errors = validator.validate_report(html, _reference_estimate(), None) + assert any("verdict-headline" in err for err in errors), (replacement, errors) + + +def test_metric_hero_only_in_hidden_ancestor_fails() -> None: + validator = _load() + html = _reference_html().replace('| Scenario | Monthly | ' + "
|---|---|
| Baseline | $1 |