From 5d4ff6614f863a5ddcd0c70716a6dffd92c2c033 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 20 Oct 2022 15:26:01 +0100 Subject: [PATCH 01/13] Snapshotting canonical style property examples --- docs/examples/styles/grid.py | 2 - docs/examples/styles/links.py | 3 - .../__snapshots__/test_snapshots.ambr | 4442 +++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 34 + 4 files changed, 4476 insertions(+), 5 deletions(-) diff --git a/docs/examples/styles/grid.py b/docs/examples/styles/grid.py index 338af444c..1901d1862 100644 --- a/docs/examples/styles/grid.py +++ b/docs/examples/styles/grid.py @@ -14,5 +14,3 @@ class GridApp(App): app = GridApp(css_path="grid.css") -if __name__ == "__main__": - app.run() diff --git a/docs/examples/styles/links.py b/docs/examples/styles/links.py index cf45563cc..ddd472974 100644 --- a/docs/examples/styles/links.py +++ b/docs/examples/styles/links.py @@ -13,6 +13,3 @@ class LinksApp(App): app = LinksApp(css_path="links.css") - -if __name__ == "__main__": - app.run() diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index e5ffd0b4e..5151d8b27 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -1,3 +1,189 @@ +# name: test_buttons_render + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ButtonsApp + + + + + + + + + + + Standard ButtonsDisabled Buttons + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +  Default  Default  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +  Primary!  Primary!  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +  Success!  Success!  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +  Warning!  Warning!  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +  Error!  Error!  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + ''' +# --- # name: test_checkboxes ''' @@ -158,6 +344,4103 @@ ''' # --- +# name: test_css_property_snapshot[docs/examples/styles/align.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AlignApp + + + + + + + + + + + + + + + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + + Vertical alignment with Textual + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + + Take note, browsers. + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/background.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BackgroundApp + + + + + + + + + + + + + Widget 1 + + + + + + + + Widget 2 + + + + + + + + Widget 3 + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/border.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BorderApp + + + + + + + + + + + ┌────────────────────────────────────────────────────────────────────────────┐ + + My border is solid red + + └────────────────────────────────────────────────────────────────────────────┘ + + ┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓ + + My border is dashed green + + ┗╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┛ + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + My border is tall blue + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/box_sizing.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BoxSizingApp + + + + + + + + + + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + I'm using border-box! + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + I'm using content-box! + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/color.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ColorApp + + + + + + + + + + + + + I'm red! + + + + + + + + I'm rgb(0, 255, 0)! + + + + + + + + I'm hsl(240, 100%, 50%)! + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/content_align.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ContentAlignApp + + + + + + + + + + + With content-align you can... + + + + + + + + + + ...Easily align content... + + + + + + + + + + + ...Horizontally and vertically! + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/display.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DisplayApp + + + + + + + + + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃Widget 1 + + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃Widget 3 + + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + + + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/grid.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GridApp + + + + + + + + + + + Grid cell 1Grid cell 2 + + row-span: 3; + column-span: 2; + + + Grid cell 3 + + + + + + Grid cell 4 + + + + + + Grid cell 5Grid cell 6Grid cell 7 + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/height.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HeightApp + + + + + + + + + + Widget + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/layout.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LayoutApp + + + + + + + + + + + Layout + + Is + + Vertical + + + LayoutIsHorizontal + + + + + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/links.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LinksApp + + + + + + + + + + Here is a link which you can click! + + Here is a link which you can click! + + + + + + + + + + + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/margin.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MarginApp + + + + + + + + + + + + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me. + And when it has gone past, I will turn the inner eye to see  + its path. + Where the fear has gone there will be nothing. Only I will  + remain. + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/offset.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OffsetApp + + + + + + + + + + + + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + Paul (offset 8 2) + + + Chani (offset 0 5)▐ + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + + + Duncan (offset▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + 10) + + + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/opacity.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OpacityApp + + + + + + + + + + + + + + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + opacity: 25% + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + opacity: 50% + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + opacity: 75% + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + opacity: 100% + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/outline.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OutlineApp + + + + + + + + + + + + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ear is the mind-killer. + ear is the little-death that brings total obliteration. +  will face my fear. +  will permit it to pass over me and through me. + nd when it has gone past, I will turn the inner eye to see its + ath. + here the fear has gone there will be nothing. Only I will  + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/overflow.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OverflowApp + + + + + + + + + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + I must not fear.I must not fear. + Fear is the mind-killer.Fear is the mind-killer. + Fear is the little-death that Fear is the little-death that  + brings total obliteration.brings total obliteration. + I will face my fear.I will face my fear. + I will permit it to pass over meI will permit it to pass over me  + and through me.and through me. + And when it has gone past, I And when it has gone past, I will  + will turn the inner eye to see turn the inner eye to see its  + its path.▁▁path. + Where the fear has gone there Where the fear has gone there will + will be nothing. Only I will be nothing. Only I will remain. + remain.▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁I must not fear. + I must not fear.Fear is the mind-killer. + Fear is the mind-killer.Fear is the little-death that  + Fear is the little-death that brings total obliteration. + brings total obliteration.I will face my fear. + I will face my fear.I will permit it to pass over me  + I will permit it to pass over meand through me. + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/padding.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PaddingApp + + + + + + + + + + + + + + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me. + And when it has gone past, I will turn the inner eye to see its  + path. + Where the fear has gone there will be nothing. Only I will  + remain. + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/scrollbar_gutter.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ScrollbarGutterApp + + + + + + + + + + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me. + And when it has gone past, I will turn the inner eye to see its path. + Where the fear has gone there will be nothing. Only I will remain. + + + + + + + + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/scrollbar_size.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ScrollbarApp + + + + + + + + + + + + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me. + And when it has gone past, I will turn the inner eye to see its path. + Where the fear has gone there will be nothing. Only I will remain. + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me.▂▂▂▂ + And when it has gone past, I will turn the inner eye to see its path. + Where the fear has gone there will be nothing. Only I will remain. + I must not fear. + Fear is the mind-killer. + Fear is the little-death that brings total obliteration. + I will face my fear. + I will permit it to pass over me and through me. + And when it has gone past, I will turn the inner eye to see its path. + Where the fear has gone there will be nothing. Only I will remain. + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/scrollbars.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ScrollbarApp + + + + + + + + + + + + I must not fear.I must not fear. + Fear is the mind-killer.Fear is the mind-killer. + Fear is the little-death that Fear is the little-death that  + brings total obliteration.brings total obliteration. + I will face my fear.I will face my fear. + I will permit it to pass over I will permit it to pass over  + me and through me.▇▇me and through me.▇▇ + And when it has gone past, I And when it has gone past, I  + will turn the inner eye to seewill turn the inner eye to see + its path.its path. + Where the fear has gone there Where the fear has gone there  + will be nothing. Only I will will be nothing. Only I will  + remain.remain. + I must not fear.I must not fear. + Fear is the mind-killer.Fear is the mind-killer. + Fear is the little-death that Fear is the little-death that  + brings total obliteration.brings total obliteration. + I will face my fear.I will face my fear. + I will permit it to pass over I will permit it to pass over  + me and through me.me and through me. + And when it has gone past, I And when it has gone past, I  + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/text_align.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TextAlign + + + + + + + + + + + Left aligned + I must not fear. Fear is the mind-killer. Fear is the little-death that brings + total obliteration. I will face my fear. I will permit it to pass over me and  + through me.                                                                    + + + Center aligned + I must not fear. Fear is the mind-killer. Fear is the little-death that brings + total obliteration. I will face my fear. I will permit it to pass over me and  +                                  through me.                                   + + + Right aligned + I must not fear. Fear is the mind-killer. Fear is the little-death that brings +  total obliteration. I will face my fear. I will permit it to pass over me and +                                                                    through me. + + + Justified + I must not fear. Fear is the mind-killer. Fear is the little-death that brings + total obliteration. I will face my fear. I will permit it to pass over me  and + through me. + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/text_opacity.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TextOpacityApp + + + + + + + + + + + + + +                                text-opacity: 25%                                 + + + + +                                text-opacity: 50%                                 + + + + +                                text-opacity: 75%                                 + + + + +                                text-opacity: 100%                                + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/text_style.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TextStyleApp + + + + + + + + + + I must not fear.I must not fear.I must not fear. + Fear is the mind-killer.Fear is the mind-killer.Fear is the mind-killer. + Fear is the little-death Fear is the little-death Fear is the little-death  + that brings total that brings total that brings total  + obliteration.obliteration.obliteration. + I will face my fear.I will face my fear.I will face my fear. + I will permit it to pass I will permit it to pass I will permit it to pass  + over me and through me.over me and through me.over me and through me. + And when it has gone past,And when it has gone past, And when it has gone past,  + I will turn the inner eye I will turn the inner eye I will turn the inner eye  + to see its path.to see its path.to see its path. + Where the fear has gone Where the fear has gone Where the fear has gone  + there will be nothing. there will be nothing. Onlythere will be nothing. Only + Only I will remain.I will remain.I will remain. + + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/tint.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TintApp + + + + + + + + + + + tint: green 0%; + + + tint: green 10%; + + + tint: green 20%; + + + tint: green 30%; + + + tint: green 40%; + + + tint: green 50%; + ▄▄ + + tint: green 60%; + + + tint: green 70%; + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/visibility.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VisibilityApp + + + + + + + + + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃Widget 1 + + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + + + + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃Widget 3 + + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + + + + + + + + + + + + + ''' +# --- +# name: test_css_property_snapshot[docs/examples/styles/width.py] + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WidthApp + + + + + + + + + + Widget + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' +# --- # name: test_dock_layout_sidebar ''' @@ -939,6 +5222,165 @@ ''' # --- +# name: test_input_and_focus + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Darren                                                                     + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Burns + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + + + + + + + ''' +# --- # name: test_layers ''' diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 72249c3ed..adb8743d3 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -1,3 +1,10 @@ +from pathlib import Path + +import pytest + + +# --- Layout related stuff --- + def test_grid_layout_basic(snap_compare): assert snap_compare("docs/examples/guide/layout/grid_layout1.py") @@ -26,7 +33,34 @@ def test_dock_layout_sidebar(snap_compare): assert snap_compare("docs/examples/guide/layout/dock_layout2_sidebar.py") +# --- Interacting with widgets --- + def test_checkboxes(snap_compare): """Tests checkboxes but also acts a regression test for using width: auto in a Horizontal layout context.""" assert snap_compare("docs/examples/widgets/checkbox.py") + + +def test_input_and_focus(snap_compare): + first_field = ["tab"] + list("Darren") # Focus first input, write "Darren" + second_field = ["tab"] + list("Burns") # Tab focus to second input, write "Burns" + assert snap_compare("docs/examples/widgets/input.py", press=first_field + second_field) + + +def test_buttons_render(snap_compare): + # Testing button rendering. We press tab to focus the first button too. + assert snap_compare("docs/examples/widgets/button.py", press=["tab"]) + + +# --- CSS properties --- +# We have a canonical example for each CSS property that is shown in their docs. +# If any of these change, something has likely broken, so snapshot each of them. + +PATHS = [ + str(path) for path in Path("docs/examples/styles").iterdir() if path.suffix == ".py" +] + + +@pytest.mark.parametrize("path", PATHS) +def test_css_property_snapshot(path, snap_compare): + assert snap_compare(path) From e35291da3370df4bf44c59120a508b8eb8192895 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Thu, 20 Oct 2022 15:27:10 +0100 Subject: [PATCH 02/13] Fix snapshots --- .../__snapshots__/test_snapshots.ambr | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 5151d8b27..e43445bf5 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -2249,134 +2249,134 @@ font-weight: 700; } - .terminal-3115616900-matrix { + .terminal-2080475776-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3115616900-title { + .terminal-2080475776-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3115616900-r1 { fill: #000000 } - .terminal-3115616900-r2 { fill: #c5c8c6 } - .terminal-3115616900-r3 { fill: #ff0000 } - .terminal-3115616900-r4 { fill: #0000ff } - .terminal-3115616900-r5 { fill: #008000 } + .terminal-2080475776-r1 { fill: #000000 } + .terminal-2080475776-r2 { fill: #c5c8c6 } + .terminal-2080475776-r3 { fill: #ff0000 } + .terminal-2080475776-r4 { fill: #0000ff } + .terminal-2080475776-r5 { fill: #008000 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OffsetApp + OffsetApp - - - - - - ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ - - - ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ - Paul (offset 8 2) - - - Chani (offset 0 5)▐ - ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀ - ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ - - - Duncan (offset▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ - 10) - - - - ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ - - - + + + + + + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + + + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ + Paul (offset 8 2) + + + Chani (offset 0 5)▐ + ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + + + Duncan (offset ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + 10) + + + + ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ + + + From c6418e5e202e8c30bbc19cf82e1d153547c5fbc0 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 12:14:52 +0100 Subject: [PATCH 03/13] Snapshot testing data table, checkbox interactions --- .../widgets/{table.py => data_table.py} | 0 docs/widgets/data_table.md | 6 +- .../__snapshots__/test_snapshots.ambr | 277 ++++++++++++++---- tests/snapshot_tests/test_snapshots.py | 25 +- 4 files changed, 243 insertions(+), 65 deletions(-) rename docs/examples/widgets/{table.py => data_table.py} (100%) diff --git a/docs/examples/widgets/table.py b/docs/examples/widgets/data_table.py similarity index 100% rename from docs/examples/widgets/table.py rename to docs/examples/widgets/data_table.py diff --git a/docs/widgets/data_table.md b/docs/widgets/data_table.md index ce7f25bf5..7d5558a95 100644 --- a/docs/widgets/data_table.md +++ b/docs/widgets/data_table.md @@ -11,13 +11,13 @@ The example below populates a table with CSV data. === "Output" - ```{.textual path="docs/examples/widgets/table.py"} + ```{.textual path="docs/examples/widgets/data_table.py"} ``` -=== "table.py" +=== "data_table.py" ```python - --8<-- "docs/examples/widgets/table.py" + --8<-- "docs/examples/widgets/data_table.py" ``` diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index e43445bf5..e4bc44f84 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -207,136 +207,136 @@ font-weight: 700; } - .terminal-900458690-matrix { + .terminal-1548740802-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-900458690-title { + .terminal-1548740802-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-900458690-r1 { fill: #e1e1e1 } - .terminal-900458690-r2 { fill: #c5c8c6 } - .terminal-900458690-r3 { fill: #e1e1e1;font-weight: bold } - .terminal-900458690-r4 { fill: #1e1e1e } - .terminal-900458690-r5 { fill: #e2e3e3 } - .terminal-900458690-r6 { fill: #0178d4 } - .terminal-900458690-r7 { fill: #e3e8e8 } + .terminal-1548740802-r1 { fill: #e1e1e1 } + .terminal-1548740802-r2 { fill: #c5c8c6 } + .terminal-1548740802-r3 { fill: #e1e1e1;font-weight: bold } + .terminal-1548740802-r4 { fill: #1e1e1e } + .terminal-1548740802-r5 { fill: #0178d4 } + .terminal-1548740802-r6 { fill: #e2e3e3 } + .terminal-1548740802-r7 { fill: #e3e8e8 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - CheckboxApp + CheckboxApp - - - - - - - - Example checkboxes - - - ▔▔▔▔▔▔▔▔ - off:      - ▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔ - on:       - ▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔ - focused:  - ▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔ - custom:   - ▁▁▁▁▁▁▁▁ - - - - + + + + + + + + Example checkboxes + + + ▔▔▔▔▔▔▔▔ + off:      + ▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔ + on:       + ▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔ + focused:  + ▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔ + custom:   + ▁▁▁▁▁▁▁▁ + + + + @@ -4441,6 +4441,163 @@ ''' # --- +# name: test_datatable_render + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TableApp + + + + + + + + + +  lane  swimmer               country        time   +  4     Joseph Schooling      Singapore      50.39  +  2     Michael Phelps        United States  51.14  +  5     Chad le Clos          South Africa   51.14  +  6     László Cseh           Hungary        51.14  +  3     Li Zhuhao             China          51.26  +  8     Mehdy Metella         France         51.58  +  7     Tom Shields           United States  51.73  +  1     Aleksandr Sadovnikov  Russia         51.84  + + + + + + + + + + + + + + + + + + + + ''' +# --- # name: test_dock_layout_sidebar ''' diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index adb8743d3..c4af6167c 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -33,12 +33,27 @@ def test_dock_layout_sidebar(snap_compare): assert snap_compare("docs/examples/guide/layout/dock_layout2_sidebar.py") -# --- Interacting with widgets --- +# --- Widgets - rendering and basic interactions --- + +# before snapshot test: +# src/textual/widgets/_checkbox.py 47 47 0% 1-126 +# before testing presses in snapshot test: +# src/textual/widgets/_checkbox.py 47 11 77% 83-88, 110, 113, 118, 124-126 +# after testing presses in snapshot test: +# src/textual/widgets/_checkbox.py 47 2 96% 87, 110 def test_checkboxes(snap_compare): """Tests checkboxes but also acts a regression test for using width: auto in a Horizontal layout context.""" - assert snap_compare("docs/examples/widgets/checkbox.py") + press = [ + "shift+tab", + "enter", # toggle off + "shift+tab", + "wait:20", + "enter", # toggle on + "wait:20", + ] + assert snap_compare("docs/examples/widgets/checkbox.py", press=press) def test_input_and_focus(snap_compare): @@ -52,6 +67,12 @@ def test_buttons_render(snap_compare): assert snap_compare("docs/examples/widgets/button.py", press=["tab"]) +# src/textual/widgets/_data_table.py 312 312 0% +# src/textual/widgets/_data_table.py 312 85 73% +def test_datatable_render(snap_compare): + assert snap_compare("docs/examples/widgets/data_table.py") + + # --- CSS properties --- # We have a canonical example for each CSS property that is shown in their docs. # If any of these change, something has likely broken, so snapshot each of them. From 67c3b83f806ecfc1c26362b66a8ab8ef97ea586d Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 12:18:35 +0100 Subject: [PATCH 04/13] Remove animation from checkbox snapshot test --- docs/examples/widgets/checkbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/examples/widgets/checkbox.py b/docs/examples/widgets/checkbox.py index ff2b27196..400f2ae25 100644 --- a/docs/examples/widgets/checkbox.py +++ b/docs/examples/widgets/checkbox.py @@ -7,7 +7,9 @@ class CheckboxApp(App): def compose(self) -> ComposeResult: yield Static("[b]Example checkboxes\n", classes="label") yield Horizontal( - Static("off: ", classes="label"), Checkbox(), classes="container" + Static("off: ", classes="label"), + Checkbox(animate=False), + classes="container", ) yield Horizontal( Static("on: ", classes="label"), From f09e5f7d9f1eb31df20b550e9826b87dd1f6c8d0 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 12:39:33 +0100 Subject: [PATCH 05/13] Snapshot testing footer --- docs/examples/widgets/footer.py | 11 +- .../__snapshots__/test_snapshots.ambr | 272 ++++++++++++++---- tests/snapshot_tests/test_snapshots.py | 10 +- 3 files changed, 234 insertions(+), 59 deletions(-) diff --git a/docs/examples/widgets/footer.py b/docs/examples/widgets/footer.py index 47d9c9aa6..85406b4e9 100644 --- a/docs/examples/widgets/footer.py +++ b/docs/examples/widgets/footer.py @@ -4,7 +4,16 @@ from textual.widgets import Footer class FooterApp(App): - BINDINGS = [Binding(key="q", action="quit", description="Quit the app")] + BINDINGS = [ + Binding(key="q", action="quit", description="Quit the app"), + Binding( + key="question_mark", + action="help", + description="Show help screen", + key_display="?", + ), + Binding(key="j", action="down", description="Scroll down", show=False), + ] def compose(self) -> ComposeResult: yield Footer() diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index e4bc44f84..1c5ed27e0 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -4464,133 +4464,134 @@ font-weight: 700; } - .terminal-2487729631-matrix { + .terminal-133545376-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2487729631-title { + .terminal-133545376-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2487729631-r1 { fill: #dde6ed;font-weight: bold } - .terminal-2487729631-r2 { fill: #e1e1e1 } - .terminal-2487729631-r3 { fill: #c5c8c6 } - .terminal-2487729631-r4 { fill: #211505 } + .terminal-133545376-r1 { fill: #dde6ed;font-weight: bold } + .terminal-133545376-r2 { fill: #e1e1e1 } + .terminal-133545376-r3 { fill: #c5c8c6 } + .terminal-133545376-r4 { fill: #e7e5e2 } + .terminal-133545376-r5 { fill: #211505 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - TableApp + TableApp - - - -  lane  swimmer               country        time   -  4     Joseph Schooling      Singapore      50.39  -  2     Michael Phelps        United States  51.14  -  5     Chad le Clos          South Africa   51.14  -  6     László Cseh           Hungary        51.14  -  3     Li Zhuhao             China          51.26  -  8     Mehdy Metella         France         51.58  -  7     Tom Shields           United States  51.73  -  1     Aleksandr Sadovnikov  Russia         51.84  - - - - - - - - - - - - - - + + + +  lane  swimmer               country        time   +  4     Joseph Schooling      Singapore      50.39  +  2     Michael Phelps        United States  51.14  +  5     Chad le Clos          South Africa   51.14  +  6     László Cseh           Hungary        51.14  +  3     Li Zhuhao             China          51.26  +  8     Mehdy Metella         France         51.58  +  7     Tom Shields           United States  51.73  +  1     Aleksandr Sadovnikov  Russia         51.84  + + + + + + + + + + + + + + @@ -4755,6 +4756,163 @@ ''' # --- +# name: test_footer_render + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FooterApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  Q  Quit the app  ?  Show help screen  + + + + + ''' +# --- # name: test_grid_layout_basic ''' diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index c4af6167c..fb66234f1 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -34,6 +34,9 @@ def test_dock_layout_sidebar(snap_compare): # --- Widgets - rendering and basic interactions --- +# Each widget should have a canonical example that is display in the docs. +# When adding a new widget, ideally we should also create a snapshot test +# from these examples which test rendering and simple interactions with it. # before snapshot test: # src/textual/widgets/_checkbox.py 47 47 0% 1-126 @@ -70,7 +73,12 @@ def test_buttons_render(snap_compare): # src/textual/widgets/_data_table.py 312 312 0% # src/textual/widgets/_data_table.py 312 85 73% def test_datatable_render(snap_compare): - assert snap_compare("docs/examples/widgets/data_table.py") + press = ["tab", "down", "down", "right", "up", "left"] + assert snap_compare("docs/examples/widgets/data_table.py", press=press) + + +def test_footer_render(snap_compare): + assert snap_compare("docs/examples/widgets/footer.py") # --- CSS properties --- From 9632e76159bbc032f10acd81c01069bc9cdd878d Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 12:42:32 +0100 Subject: [PATCH 06/13] Snapshotting Header widgets --- .../__snapshots__/test_snapshots.ambr | 156 ++++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 3 + 2 files changed, 159 insertions(+) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 1c5ed27e0..92eb75fc1 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -5381,6 +5381,162 @@ ''' # --- +# name: test_header_render + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HeaderApp + + + + + + + + + + HeaderApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''' +# --- # name: test_horizontal_layout ''' diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index fb66234f1..fb4913227 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -81,6 +81,9 @@ def test_footer_render(snap_compare): assert snap_compare("docs/examples/widgets/footer.py") +def test_header_render(snap_compare): + assert snap_compare("docs/examples/widgets/header.py") + # --- CSS properties --- # We have a canonical example for each CSS property that is shown in their docs. # If any of these change, something has likely broken, so snapshot each of them. From 041bb350140f77f327fb747c4471bc093076070e Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 14:51:40 +0100 Subject: [PATCH 07/13] Remove comments, simplify test --- docs/examples/widgets/data_table.py | 3 ++- tests/snapshot_tests/conftest.py | 1 + tests/snapshot_tests/test_snapshots.py | 28 ++++++++++++++------------ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/examples/widgets/data_table.py b/docs/examples/widgets/data_table.py index 87b2c0ce8..f2671dd48 100644 --- a/docs/examples/widgets/data_table.py +++ b/docs/examples/widgets/data_table.py @@ -2,7 +2,7 @@ import csv import io from textual.app import App, ComposeResult -from textual.widgets import DataTable +from textual.widgets import DataTable, Header CSV = """lane,swimmer,country,time 4,Joseph Schooling,Singapore,50.39 @@ -17,6 +17,7 @@ CSV = """lane,swimmer,country,time class TableApp(App): def compose(self) -> ComposeResult: + yield Header() yield DataTable() def on_mount(self) -> None: diff --git a/tests/snapshot_tests/conftest.py b/tests/snapshot_tests/conftest.py index 79b5584b1..0a0f0d55c 100644 --- a/tests/snapshot_tests/conftest.py +++ b/tests/snapshot_tests/conftest.py @@ -59,6 +59,7 @@ def snap_compare( """ node = request.node app = import_app(app_path) + compare.app = app actual_screenshot = take_svg_screenshot( app=app, press=press, diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index fb4913227..71b02371e 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -2,8 +2,9 @@ from pathlib import Path import pytest - # --- Layout related stuff --- +from textual.widgets import Input + def test_grid_layout_basic(snap_compare): assert snap_compare("docs/examples/guide/layout/grid_layout1.py") @@ -38,13 +39,6 @@ def test_dock_layout_sidebar(snap_compare): # When adding a new widget, ideally we should also create a snapshot test # from these examples which test rendering and simple interactions with it. -# before snapshot test: -# src/textual/widgets/_checkbox.py 47 47 0% 1-126 -# before testing presses in snapshot test: -# src/textual/widgets/_checkbox.py 47 11 77% 83-88, 110, 113, 118, 124-126 -# after testing presses in snapshot test: -# src/textual/widgets/_checkbox.py 47 2 96% 87, 110 - def test_checkboxes(snap_compare): """Tests checkboxes but also acts a regression test for using width: auto in a Horizontal layout context.""" @@ -60,9 +54,18 @@ def test_checkboxes(snap_compare): def test_input_and_focus(snap_compare): - first_field = ["tab"] + list("Darren") # Focus first input, write "Darren" - second_field = ["tab"] + list("Burns") # Tab focus to second input, write "Burns" - assert snap_compare("docs/examples/widgets/input.py", press=first_field + second_field) + press = [ + "tab", + *list("Darren"), # Focus first input, write "Darren" + "tab", + *list("Burns"), # Tab focus to second input, write "Burns" + ] + assert snap_compare("docs/examples/widgets/input.py", press=press) + + # Assert that the state of the Input is what we'd expect + input: Input = snap_compare.app.query_one(Input) + assert input.value == "Darren" + assert input.cursor_position == 6 def test_buttons_render(snap_compare): @@ -70,8 +73,6 @@ def test_buttons_render(snap_compare): assert snap_compare("docs/examples/widgets/button.py", press=["tab"]) -# src/textual/widgets/_data_table.py 312 312 0% -# src/textual/widgets/_data_table.py 312 85 73% def test_datatable_render(snap_compare): press = ["tab", "down", "down", "right", "up", "left"] assert snap_compare("docs/examples/widgets/data_table.py", press=press) @@ -84,6 +85,7 @@ def test_footer_render(snap_compare): def test_header_render(snap_compare): assert snap_compare("docs/examples/widgets/header.py") + # --- CSS properties --- # We have a canonical example for each CSS property that is shown in their docs. # If any of these change, something has likely broken, so snapshot each of them. From d02e6e94b0e1ab92f900631aa0667be8955b103f Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 15:16:47 +0100 Subject: [PATCH 08/13] Fix data-table snapshot --- docs/examples/widgets/data_table.py | 3 +-- tests/snapshot_tests/test_snapshots.py | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/examples/widgets/data_table.py b/docs/examples/widgets/data_table.py index f2671dd48..87b2c0ce8 100644 --- a/docs/examples/widgets/data_table.py +++ b/docs/examples/widgets/data_table.py @@ -2,7 +2,7 @@ import csv import io from textual.app import App, ComposeResult -from textual.widgets import DataTable, Header +from textual.widgets import DataTable CSV = """lane,swimmer,country,time 4,Joseph Schooling,Singapore,50.39 @@ -17,7 +17,6 @@ CSV = """lane,swimmer,country,time class TableApp(App): def compose(self) -> ComposeResult: - yield Header() yield DataTable() def on_mount(self) -> None: diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 71b02371e..5831e0b78 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -2,10 +2,12 @@ from pathlib import Path import pytest -# --- Layout related stuff --- +from textual.app import App from textual.widgets import Input +# --- Layout related stuff --- + def test_grid_layout_basic(snap_compare): assert snap_compare("docs/examples/guide/layout/grid_layout1.py") @@ -63,7 +65,8 @@ def test_input_and_focus(snap_compare): assert snap_compare("docs/examples/widgets/input.py", press=press) # Assert that the state of the Input is what we'd expect - input: Input = snap_compare.app.query_one(Input) + app: App = snap_compare.app + input: Input = app.query_one(Input) assert input.value == "Darren" assert input.cursor_position == 6 From 5adbba7674bbc97d6501ba2271d940998b6013a9 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Mon, 24 Oct 2022 16:11:59 +0100 Subject: [PATCH 09/13] Increase sleep between key-presses --- src/textual/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index c044f6155..03e728ac9 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -605,7 +605,7 @@ class App(Generic[ReturnType], DOMNode): assert press driver = app._driver assert driver is not None - await asyncio.sleep(0.01) + await asyncio.sleep(0.02) for key in press: if key == "_": print("(pause 50ms)") @@ -632,7 +632,7 @@ class App(Generic[ReturnType], DOMNode): print(f"press {key!r} (char={char!r})") key_event = events.Key(self, key, char) driver.send_event(key_event) - await asyncio.sleep(0.01) + await asyncio.sleep(0.02) await app._animator.wait_for_idle() From 617f0acb99e2ebd654b75e42b6f9e0848b023175 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Oct 2022 10:57:54 +0100 Subject: [PATCH 10/13] Additional sleep after tabbing to guard vs races --- src/textual/app.py | 6 ++++++ tests/snapshot_tests/test_snapshots.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index 03e728ac9..43f1bd56c 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -632,6 +632,12 @@ class App(Generic[ReturnType], DOMNode): print(f"press {key!r} (char={char!r})") key_event = events.Key(self, key, char) driver.send_event(key_event) + # TODO: A bit of a fudge - extra sleep after tabbing to help guard against race + # condition between widget-level key handling and app/screen level handling. + # More information here: https://github.com/Textualize/textual/issues/1009 + # This conditional sleep can be removed after that issue is closed. + if key == "tab": + await asyncio.sleep(0.05) await asyncio.sleep(0.02) await app._animator.wait_for_idle() diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 5831e0b78..d68bb5c21 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -58,9 +58,9 @@ def test_checkboxes(snap_compare): def test_input_and_focus(snap_compare): press = [ "tab", - *list("Darren"), # Focus first input, write "Darren" + *"Darren", # Focus first input, write "Darren" "tab", - *list("Burns"), # Tab focus to second input, write "Burns" + *"Burns", # Tab focus to second input, write "Burns" ] assert snap_compare("docs/examples/widgets/input.py", press=press) From 1b194507798344000e2a8642bc91e43233cd840e Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Oct 2022 12:08:08 +0100 Subject: [PATCH 11/13] Ensure consistent path in snapshot tests --- .../__snapshots__/test_snapshots.ambr | 158 ++++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 4 +- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 92eb75fc1..e8583dec8 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -6009,6 +6009,164 @@ ''' # --- +# name: test_property_align + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AlignApp + + + + + + + + + + + + + + + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + + Vertical alignment with Textual + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + + Take note, browsers. + + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + + + + + + + + + + + + ''' +# --- # name: test_vertical_layout ''' diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index d68bb5c21..cbc12b51e 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -1,4 +1,4 @@ -from pathlib import Path +from pathlib import Path, PurePosixPath import pytest @@ -94,7 +94,7 @@ def test_header_render(snap_compare): # If any of these change, something has likely broken, so snapshot each of them. PATHS = [ - str(path) for path in Path("docs/examples/styles").iterdir() if path.suffix == ".py" + str(PurePosixPath(path)) for path in Path("docs/examples/styles").iterdir() if path.suffix == ".py" ] From 66d15d2a9e4b55ff3c4e4023195aed1077742ba8 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Oct 2022 12:11:15 +0100 Subject: [PATCH 12/13] Remove unused snapshot --- .../__snapshots__/test_snapshots.ambr | 158 ------------------ 1 file changed, 158 deletions(-) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index e8583dec8..92eb75fc1 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -6009,164 +6009,6 @@ ''' # --- -# name: test_property_align - ''' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AlignApp - - - - - - - - - - - - - - - - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - - Vertical alignment with Textual - - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - - Take note, browsers. - - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - - - - - - - - - - - - ''' -# --- # name: test_vertical_layout ''' From 6be7895ecb25772497244def17cf0e3ca9333c44 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Oct 2022 13:15:31 +0100 Subject: [PATCH 13/13] Check some more widget state --- tests/snapshot_tests/test_snapshots.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index cbc12b51e..2f04c9314 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -3,7 +3,7 @@ from pathlib import Path, PurePosixPath import pytest from textual.app import App -from textual.widgets import Input +from textual.widgets import Input, Button # --- Layout related stuff --- @@ -69,12 +69,17 @@ def test_input_and_focus(snap_compare): input: Input = app.query_one(Input) assert input.value == "Darren" assert input.cursor_position == 6 + assert input.view_position == 0 def test_buttons_render(snap_compare): # Testing button rendering. We press tab to focus the first button too. assert snap_compare("docs/examples/widgets/button.py", press=["tab"]) + app = snap_compare.app + button: Button = app.query_one(Button) + assert app.focused is button + def test_datatable_render(snap_compare): press = ["tab", "down", "down", "right", "up", "left"]