diff --git a/sdk/python/examples/controls/progress_ring/__init__.py b/sdk/python/examples/controls/progress_ring/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/examples/controls/progress_ring/determinate_and_indeterminate.py b/sdk/python/examples/controls/progress_ring/determinate_and_indeterminate.py index 025b85686e..15133cefc1 100644 --- a/sdk/python/examples/controls/progress_ring/determinate_and_indeterminate.py +++ b/sdk/python/examples/controls/progress_ring/determinate_and_indeterminate.py @@ -35,4 +35,5 @@ async def main(page: ft.Page): page.update() -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/progress_ring/gauge_with_progress.py b/sdk/python/examples/controls/progress_ring/gauge_with_progress.py index 43ff062828..d4d811b18a 100644 --- a/sdk/python/examples/controls/progress_ring/gauge_with_progress.py +++ b/sdk/python/examples/controls/progress_ring/gauge_with_progress.py @@ -14,4 +14,5 @@ def main(page: ft.Page): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/radio/__init__.py b/sdk/python/examples/controls/radio/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/examples/controls/radio/basic.py b/sdk/python/examples/controls/radio/basic.py index b37e8a57e3..3626560072 100644 --- a/sdk/python/examples/controls/radio/basic.py +++ b/sdk/python/examples/controls/radio/basic.py @@ -22,4 +22,5 @@ def handle_button_click(e: ft.Event[ft.Button]): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/radio/handling_selection_changes.py b/sdk/python/examples/controls/radio/handling_selection_changes.py index c0cfa14fff..fef5632f5c 100644 --- a/sdk/python/examples/controls/radio/handling_selection_changes.py +++ b/sdk/python/examples/controls/radio/handling_selection_changes.py @@ -22,4 +22,5 @@ def handle_selection_change(e: ft.Event[ft.RadioGroup]): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/radio/styled.py b/sdk/python/examples/controls/radio/styled.py index 40f5111117..6188ee0307 100644 --- a/sdk/python/examples/controls/radio/styled.py +++ b/sdk/python/examples/controls/radio/styled.py @@ -27,4 +27,5 @@ def main(page: ft.Page): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/range_slider/__init__.py b/sdk/python/examples/controls/range_slider/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/examples/controls/range_slider/basic.py b/sdk/python/examples/controls/range_slider/basic.py index 0920eaf5dc..0f458f4477 100644 --- a/sdk/python/examples/controls/range_slider/basic.py +++ b/sdk/python/examples/controls/range_slider/basic.py @@ -21,11 +21,12 @@ def main(page: ft.Page): inactive_color=ft.Colors.GREEN_300, active_color=ft.Colors.GREEN_700, overlay_color=ft.Colors.GREEN_100, - label="{value}%", + label="{value}", ), ], ) ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/range_slider/handling_change_events.py b/sdk/python/examples/controls/range_slider/handling_change_events.py index 395bea7e0c..7e0ce549c3 100644 --- a/sdk/python/examples/controls/range_slider/handling_change_events.py +++ b/sdk/python/examples/controls/range_slider/handling_change_events.py @@ -26,14 +26,15 @@ def handle_slider_change_end(e: ft.Event[ft.RangeSlider]): ), ft.Container(height=30), ft.RangeSlider( - divisions=50, + divisions=100, min=0, - max=50, + max=100, start_value=10, end_value=20, on_change_start=handle_slider_change_start, on_change=handle_slider_change, on_change_end=handle_slider_change_end, + label="{value}%", ), message := ft.Text(), ], @@ -41,4 +42,5 @@ def handle_slider_change_end(e: ft.Event[ft.RangeSlider]): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/reorderable_list_view/__init__.py b/sdk/python/examples/controls/reorderable_list_view/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/examples/controls/reorderable_list_view/horizontal_and_vertical.py b/sdk/python/examples/controls/reorderable_list_view/horizontal_and_vertical.py index 4db4e56097..a24d35269c 100644 --- a/sdk/python/examples/controls/reorderable_list_view/horizontal_and_vertical.py +++ b/sdk/python/examples/controls/reorderable_list_view/horizontal_and_vertical.py @@ -46,4 +46,5 @@ def get_color(i): ) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/responsive_row/__init__.py b/sdk/python/examples/controls/responsive_row/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/python/examples/controls/responsive_row/basic.py b/sdk/python/examples/controls/responsive_row/basic.py index d91cbaddaa..099d098c73 100644 --- a/sdk/python/examples/controls/responsive_row/basic.py +++ b/sdk/python/examples/controls/responsive_row/basic.py @@ -5,6 +5,7 @@ def main(page: ft.Page): def handle_page_resize(e: ft.PageResizeEvent): pw.value = f"{page.width} px" pw.update() + page.update() page.on_resize = handle_page_resize @@ -75,7 +76,7 @@ def handle_page_resize(e: ft.PageResizeEvent): ), pw, ) - handle_page_resize(None) -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/examples/controls/responsive_row/custom_breakpoint.py b/sdk/python/examples/controls/responsive_row/custom_breakpoint.py index bab9f64b5f..4be2c3fd56 100644 --- a/sdk/python/examples/controls/responsive_row/custom_breakpoint.py +++ b/sdk/python/examples/controls/responsive_row/custom_breakpoint.py @@ -99,4 +99,5 @@ def update_status(_=None): update_status() -ft.run(main) +if __name__ == "__main__": + ft.run(main) diff --git a/sdk/python/packages/flet/docs/controls/progressring.md b/sdk/python/packages/flet/docs/controls/progressring.md index 31f771ced5..f07d8624e7 100644 --- a/sdk/python/packages/flet/docs/controls/progressring.md +++ b/sdk/python/packages/flet/docs/controls/progressring.md @@ -1,10 +1,11 @@ --- class_name: flet.ProgressRing examples: ../../examples/controls/progress_ring -example_images: ../examples/controls/progress_ring/media +example_images: ../test-images/examples/material/golden/macos/progress_ring +example_media: ../examples/controls/progress_ring/media --- -{{ class_summary(class_name) }} +{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Fixed progress ring") }} ## Examples @@ -16,7 +17,7 @@ example_images: ../examples/controls/progress_ring/media --8<-- "{{ examples }}/determinate_and_indeterminate.py" ``` -{{ image(example_images + "/determinate_and_indeterminate.gif", alt="determinate-and-indeterminate", width="80%") }} +{{ image(example_media + "/determinate_and_indeterminate.gif", alt="determinate-and-indeterminate", width="80%") }} ### Gauge with progress @@ -25,4 +26,6 @@ example_images: ../examples/controls/progress_ring/media --8<-- "{{ examples }}/gauge_with_progress.py" ``` +{{ image(example_images + "/gauge_with_progress.png", alt="determinate-and-indeterminate", width="80%") }} + {{ class_members(class_name) }} diff --git a/sdk/python/packages/flet/docs/controls/radio.md b/sdk/python/packages/flet/docs/controls/radio.md index 308c2a1c16..9fe9b75fca 100644 --- a/sdk/python/packages/flet/docs/controls/radio.md +++ b/sdk/python/packages/flet/docs/controls/radio.md @@ -1,10 +1,10 @@ --- class_name: flet.Radio examples: ../../examples/controls/radio -example_images: ../examples/controls/radio/media +example_images: ../test-images/examples/material/golden/macos/radio --- -{{ class_summary(class_name) }} +{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Simple radio buttons") }} ## Examples @@ -16,7 +16,7 @@ example_images: ../examples/controls/radio/media --8<-- "{{ examples }}/basic.py" ``` -{{ image(example_images + "/basic.gif", alt="basic", width="80%") }} +{{ image(example_images + "/basic.png", alt="basic", width="80%") }} @@ -26,7 +26,7 @@ example_images: ../examples/controls/radio/media --8<-- "{{ examples }}/handling_selection_changes.py" ``` -{{ image(example_images + "/handling_selection_changes.gif", alt="handling-selection-changes", width="80%") }} +{{ image(example_images + "/handling_selection_changes.png", alt="handling-selection-changes", width="80%") }} ### Styled radio buttons diff --git a/sdk/python/packages/flet/docs/controls/rangeslider.md b/sdk/python/packages/flet/docs/controls/rangeslider.md index 49545f657e..64f4115a4f 100644 --- a/sdk/python/packages/flet/docs/controls/rangeslider.md +++ b/sdk/python/packages/flet/docs/controls/rangeslider.md @@ -1,10 +1,10 @@ --- class_name: flet.RangeSlider examples: ../../examples/controls/range_slider -example_images: ../examples/controls/range_slider/media +example_images: ../test-images/examples/material/golden/macos/range_slider --- -{{ class_summary(class_name) }} +{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Range Slider") }} ## Examples @@ -25,4 +25,6 @@ example_images: ../examples/controls/range_slider/media --8<-- "{{ examples }}/handling_change_events.py" ``` +{{ image(example_images + "/handling_events.gif", alt="handling_events", width="80%") }} + {{ class_members(class_name) }} diff --git a/sdk/python/packages/flet/docs/controls/reorderablelistview.md b/sdk/python/packages/flet/docs/controls/reorderablelistview.md index ac29465870..ead463218d 100644 --- a/sdk/python/packages/flet/docs/controls/reorderablelistview.md +++ b/sdk/python/packages/flet/docs/controls/reorderablelistview.md @@ -1,10 +1,10 @@ --- class_name: flet.ReorderableListView examples: ../../examples/controls/reorderable_list_view -example_images: ../examples/controls/reorderable_list_view/media +example_images: ../test-images/examples/material/golden/macos/reorderable_list_view --- -{{ class_summary(class_name) }} +{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Reorderable list view") }} ## Examples @@ -16,7 +16,7 @@ example_images: ../examples/controls/reorderable_list_view/media --8<-- "{{ examples }}/horizontal_and_vertical.py" ``` -{{ image(example_images + "/horizontal_and_vertical.gif", alt="horizontal-and-vertical", width="80%") }} +{{ image(example_images + "/horizontal_and_vertical.png", alt="horizontal-and-vertical", width="80%") }} ### Custom drag handle diff --git a/sdk/python/packages/flet/docs/controls/responsiverow.md b/sdk/python/packages/flet/docs/controls/responsiverow.md index e321ca2455..7333ead42e 100644 --- a/sdk/python/packages/flet/docs/controls/responsiverow.md +++ b/sdk/python/packages/flet/docs/controls/responsiverow.md @@ -1,10 +1,10 @@ --- class_name: flet.ResponsiveRow examples: ../../examples/controls/responsive_row -example_images: ../examples/controls/responsive_row/media +example_images: ../test-images/examples/core/golden/macos/responsive_row --- -{{ class_summary(class_name) }} +{{ class_summary(class_name, example_images + "/image_for_docs.png", image_caption="Responsive row") }} ## Examples @@ -16,7 +16,7 @@ example_images: ../examples/controls/responsive_row/media --8<-- "{{ examples }}/basic.py" ``` -{{ image(example_images + "/basic.gif", alt="basic", width="80%") }} +{{ image(example_images + "/responsive_row_basic.gif", alt="basic", width="80%") }} ### Custom breakpoints @@ -25,5 +25,6 @@ example_images: ../examples/controls/responsive_row/media --8<-- "{{ examples }}/custom_breakpoint.py" ``` +{{ image(example_images + "/responsive_row_custom_breakpoint.gif", alt="basic", width="80%") }} {{ class_members(class_name) }} diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/image_for_docs.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/image_for_docs.png new file mode 100644 index 0000000000..ce4eb87ca9 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/image_for_docs.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive1.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive1.png new file mode 100644 index 0000000000..8bc2acde2a Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive1.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive2.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive2.png new file mode 100644 index 0000000000..92acabaddb Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive2.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive3.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive3.png new file mode 100644 index 0000000000..25b01f0ed6 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive3.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_1.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_1.png new file mode 100644 index 0000000000..5c99b0554f Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_1.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_2.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_2.png new file mode 100644 index 0000000000..85a23adb95 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_2.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_3.png b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_3.png new file mode 100644 index 0000000000..253a98ef62 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_custom_3.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_basic.gif b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_basic.gif new file mode 100644 index 0000000000..c646d73614 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_basic.gif differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_custom_breakpoint.gif b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_custom_breakpoint.gif new file mode 100644 index 0000000000..7fa14bd5fd Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/core/golden/macos/responsive_row/responsive_row_custom_breakpoint.gif differ diff --git a/sdk/python/packages/flet/integration_tests/examples/core/test_responsive_row.py b/sdk/python/packages/flet/integration_tests/examples/core/test_responsive_row.py new file mode 100644 index 0000000000..94ba0365f7 --- /dev/null +++ b/sdk/python/packages/flet/integration_tests/examples/core/test_responsive_row.py @@ -0,0 +1,123 @@ +import pytest + +import flet as ft +import flet.testing as ftt + +from examples.controls.responsive_row import basic, custom_breakpoint + + +@pytest.mark.asyncio(loop_scope="function") +async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + await flet_app_function.assert_control_screenshot( + request.node.name, + ft.ResponsiveRow( + controls=[ + ft.Button( + f"Button {i}", + color=ft.Colors.BLUE_GREY_300, + col={ + ft.ResponsiveRowBreakpoint.XS: 12, + ft.ResponsiveRowBreakpoint.MD: 6, + ft.ResponsiveRowBreakpoint.LG: 3, + }, + ) + for i in range(1, 6) + ], + ), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": basic.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_basic(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.resize_page(1000, 500) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive1", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio, + delay=ft.Duration(seconds=1), + ), + ) + flet_app_function.resize_page(800, 500) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive2", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio, + delay=ft.Duration(seconds=1), + ), + ) + flet_app_function.resize_page(200, 500) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive3", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio, + delay=ft.Duration(seconds=1), + ), + ) + flet_app_function.create_gif( + ["responsive1", "responsive2", "responsive3"], + "responsive_row_basic", + duration=1600, + disposal=ftt.DisposalMode.BACKGROUND, + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": custom_breakpoint.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_custom_breakpoint(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.resize_page(1000, 800) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive_custom_1", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + flet_app_function.resize_page(650, 800) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive_custom_2", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + flet_app_function.resize_page(200, 800) + flet_app_function.page.update() + for _ in range(5): + await flet_app_function.tester.pump(100) + flet_app_function.assert_screenshot( + "responsive_custom_3", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + flet_app_function.create_gif( + ["responsive_custom_1", "responsive_custom_2", "responsive_custom_3"], + "responsive_row_custom_breakpoint", + duration=1600, + disposal=ftt.DisposalMode.BACKGROUND, + ) diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/gauge_with_progress.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/gauge_with_progress.png new file mode 100644 index 0000000000..af3ce7eadc Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/gauge_with_progress.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/image_for_docs.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/image_for_docs.png new file mode 100644 index 0000000000..c38f40bd1d Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/progress_ring/image_for_docs.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/basic.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/basic.png new file mode 100644 index 0000000000..879af88158 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/basic.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/handling_selection_changes.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/handling_selection_changes.png new file mode 100644 index 0000000000..df9305e913 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/handling_selection_changes.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/image_for_docs.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/image_for_docs.png new file mode 100644 index 0000000000..71f8e0dbab Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/radio/image_for_docs.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic.gif b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic.gif new file mode 100644 index 0000000000..1e1a481757 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic.gif differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic1.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic1.png new file mode 100644 index 0000000000..20bdfd9be9 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic1.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic2.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic2.png new file mode 100644 index 0000000000..755d805b87 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic2.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic3.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic3.png new file mode 100644 index 0000000000..e34a553bce Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/basic3.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events.gif b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events.gif new file mode 100644 index 0000000000..0f4f516575 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events.gif differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events1.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events1.png new file mode 100644 index 0000000000..a8ee8c021a Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events1.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events2.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events2.png new file mode 100644 index 0000000000..b60e37f2d8 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events2.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events3.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events3.png new file mode 100644 index 0000000000..853e937fe6 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/handling_events3.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/image_for_docs.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/image_for_docs.png new file mode 100644 index 0000000000..b83f588c2e Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/range_slider/image_for_docs.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/horizontal_and_vertical.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/horizontal_and_vertical.png new file mode 100644 index 0000000000..0560505706 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/horizontal_and_vertical.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/image_for_docs.png b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/image_for_docs.png new file mode 100644 index 0000000000..8aa8c97c90 Binary files /dev/null and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/reorderable_list_view/image_for_docs.png differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/time_picker/hour_formats.gif b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/time_picker/hour_formats.gif index 1e7061dda0..8b0ec47f59 100644 Binary files a/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/time_picker/hour_formats.gif and b/sdk/python/packages/flet/integration_tests/examples/material/golden/macos/time_picker/hour_formats.gif differ diff --git a/sdk/python/packages/flet/integration_tests/examples/material/test_progress_ring.py b/sdk/python/packages/flet/integration_tests/examples/material/test_progress_ring.py new file mode 100644 index 0000000000..61197df02e --- /dev/null +++ b/sdk/python/packages/flet/integration_tests/examples/material/test_progress_ring.py @@ -0,0 +1,50 @@ +import pytest + +import flet as ft +import flet.testing as ftt + +from examples.controls.progress_ring import ( + gauge_with_progress, + determinate_and_indeterminate, +) + + +@pytest.mark.asyncio(loop_scope="function") +async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + await flet_app_function.assert_control_screenshot( + request.node.name, + ft.ProgressRing(value=0.4, padding=ft.Padding.all(10)), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": gauge_with_progress.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_gauge_with_progress(flet_app_function: ftt.FletTestApp): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + flet_app_function.assert_screenshot( + "gauge_with_progress", + await flet_app_function.take_page_controls_screenshot(), + ) + + +@pytest.mark.skip(reason="Test runs asynchronously") +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": determinate_and_indeterminate.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_determinate_and_indeterminate(flet_app_function: ftt.FletTestApp): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + flet_app_function.page.enable_screenshots = True + flet_app_function.page.update() + + flet_app_function.assert_screenshot( + "determinate_and_indeterminate", + await flet_app_function.page.take_screenshot(delay=ft.Duration(seconds=15)), + ) diff --git a/sdk/python/packages/flet/integration_tests/examples/material/test_radio.py b/sdk/python/packages/flet/integration_tests/examples/material/test_radio.py new file mode 100644 index 0000000000..e2e97f9794 --- /dev/null +++ b/sdk/python/packages/flet/integration_tests/examples/material/test_radio.py @@ -0,0 +1,65 @@ +import pytest + +import flet as ft +import flet.testing as ftt + +from examples.controls.radio import basic, handling_selection_changes + + +@pytest.mark.asyncio(loop_scope="function") +async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + await flet_app_function.assert_control_screenshot( + request.node.name, + ft.RadioGroup( + content=ft.Row( + controls=[ft.Radio(label=f"{i}") for i in range(1, 4)], + alignment=ft.MainAxisAlignment.CENTER, + expand=True, + ), + expand=True, + ), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": basic.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_basic(flet_app_function: ftt.FletTestApp): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + flet_app_function.page.enable_screenshots = True + flet_app_function.page.update() + red = await flet_app_function.tester.find_by_text("Red") + await flet_app_function.tester.tap(red) + await flet_app_function.tester.pump_and_settle() + submit = await flet_app_function.tester.find_by_text("Submit") + await flet_app_function.tester.tap(submit) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "basic", + await flet_app_function.take_page_controls_screenshot(), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": handling_selection_changes.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_handling_selection_changes(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + flet_app_function.page.update() + blue = await flet_app_function.tester.find_by_text("Blue") + await flet_app_function.tester.tap(blue) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "handling_selection_changes", + await flet_app_function.take_page_controls_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) diff --git a/sdk/python/packages/flet/integration_tests/examples/material/test_range_slider.py b/sdk/python/packages/flet/integration_tests/examples/material/test_range_slider.py new file mode 100644 index 0000000000..58cfeb4ee8 --- /dev/null +++ b/sdk/python/packages/flet/integration_tests/examples/material/test_range_slider.py @@ -0,0 +1,103 @@ +import pytest + +import flet as ft +import flet.testing as ftt + +from examples.controls.range_slider import basic, handling_change_events + + +@pytest.mark.asyncio(loop_scope="function") +async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + await flet_app_function.assert_control_screenshot( + request.node.name, + ft.RangeSlider( + min=0, + max=10, + start_value=2, + divisions=10, + end_value=7, + ), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": basic.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_basic(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.resize_page(800, 200) + flet_app_function.page.update() + await flet_app_function.tester.tap_at(ft.Offset(200, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "basic1", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + await flet_app_function.tester.tap_at(ft.Offset(700, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "basic2", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + await flet_app_function.tester.tap_at(ft.Offset(400, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "basic3", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + flet_app_function.create_gif( + ["basic1", "basic2", "basic3"], + "basic", + duration=1600, + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": handling_change_events.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_handling_change_events(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.resize_page(800, 200) + flet_app_function.page.update() + await flet_app_function.tester.tap_at(ft.Offset(200, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "handling_events1", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + await flet_app_function.tester.tap_at(ft.Offset(700, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "handling_events2", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + await flet_app_function.tester.tap_at(ft.Offset(400, 100)) + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "handling_events3", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) + flet_app_function.create_gif( + ["handling_events1", "handling_events2", "handling_events3"], + "handling_events", + duration=1600, + ) diff --git a/sdk/python/packages/flet/integration_tests/examples/material/test_reorderable_list_view.py b/sdk/python/packages/flet/integration_tests/examples/material/test_reorderable_list_view.py new file mode 100644 index 0000000000..1aac808fd6 --- /dev/null +++ b/sdk/python/packages/flet/integration_tests/examples/material/test_reorderable_list_view.py @@ -0,0 +1,43 @@ +import pytest + +import flet as ft +import flet.testing as ftt + +from examples.controls.reorderable_list_view import horizontal_and_vertical + + +@pytest.mark.asyncio(loop_scope="function") +async def test_image_for_docs(flet_app_function: ftt.FletTestApp, request): + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + await flet_app_function.assert_control_screenshot( + request.node.name, + ft.ReorderableListView( + controls=[ + ft.ListTile( + title=ft.Text(f"Item {i}"), + bgcolor=ft.Colors.BLUE_GREY_300, + ) + for i in range(1, 6) + ], + show_default_drag_handles=True, + ), + ) + + +@pytest.mark.parametrize( + "flet_app_function", + [{"flet_app_main": horizontal_and_vertical.main}], + indirect=True, +) +@pytest.mark.asyncio(loop_scope="function") +async def test_horizontal_and_vertical(flet_app_function: ftt.FletTestApp): + flet_app_function.page.enable_screenshots = True + flet_app_function.page.theme_mode = ft.ThemeMode.LIGHT + flet_app_function.page.update() + await flet_app_function.tester.pump_and_settle() + flet_app_function.assert_screenshot( + "horizontal_and_vertical", + await flet_app_function.page.take_screenshot( + pixel_ratio=flet_app_function.screenshots_pixel_ratio + ), + ) diff --git a/sdk/python/packages/flet/integration_tests/examples/material/test_time_picker.py b/sdk/python/packages/flet/integration_tests/examples/material/test_time_picker.py index de7cae659d..d4c2bee0f2 100644 --- a/sdk/python/packages/flet/integration_tests/examples/material/test_time_picker.py +++ b/sdk/python/packages/flet/integration_tests/examples/material/test_time_picker.py @@ -80,7 +80,7 @@ async def _snap(): ) async def _settle(): - await flet_app_function.tester.pump_and_settle() + await flet_app_function.tester.pump_and_settle(ft.Duration(milliseconds=500)) async def _open_picker(): await flet_app_function.tester.tap( diff --git a/sdk/python/packages/flet/src/flet/controls/core/responsive_row.py b/sdk/python/packages/flet/src/flet/controls/core/responsive_row.py index 8cb7c8e46f..185822c91d 100644 --- a/sdk/python/packages/flet/src/flet/controls/core/responsive_row.py +++ b/sdk/python/packages/flet/src/flet/controls/core/responsive_row.py @@ -26,6 +26,24 @@ class ResponsiveRow(LayoutControl, AdaptiveControl): Similar to `expand` property, every control has [`col`][flet.Control.] property which allows specifying how many columns a control should span. + + ```python + ft.ResponsiveRow( + controls=[ + ft.Button( + f"Button {i}", + color=ft.Colors.BLUE_GREY_300, + col={ + ft.ResponsiveRowBreakpoint.XS: 12, + ft.ResponsiveRowBreakpoint.MD: 6, + ft.ResponsiveRowBreakpoint.LG: 3, + }, + ) + for i in range(1, 6) + ], + ) + ``` + """ controls: list[Control] = field(default_factory=list) diff --git a/sdk/python/packages/flet/src/flet/controls/material/progress_ring.py b/sdk/python/packages/flet/src/flet/controls/material/progress_ring.py index 14c5c02c62..0a09aeba24 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/progress_ring.py +++ b/sdk/python/packages/flet/src/flet/controls/material/progress_ring.py @@ -16,6 +16,11 @@ class ProgressRing(LayoutControl): application is busy. A control that shows progress along a circle. + + ```python + ft.ProgressRing(value=0.4, padding=ft.Padding.all(10)) + ``` + """ value: Optional[Number] = None diff --git a/sdk/python/packages/flet/src/flet/controls/material/radio.py b/sdk/python/packages/flet/src/flet/controls/material/radio.py index 6c2166521c..bf3174fb65 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/radio.py +++ b/sdk/python/packages/flet/src/flet/controls/material/radio.py @@ -21,6 +21,16 @@ class Radio(LayoutControl, AdaptiveControl): """ Radio buttons let people select a single option from two or more choices. + + ```python + ft.RadioGroup( + content=ft.Row( + controls=[ft.Radio(label=f"{i}") for i in range(1, 4)], + alignment=ft.MainAxisAlignment.CENTER, + ) + ) + ``` + """ label: str = "" diff --git a/sdk/python/packages/flet/src/flet/controls/material/range_slider.py b/sdk/python/packages/flet/src/flet/controls/material/range_slider.py index 8fc90a5b15..4b736da59e 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/range_slider.py +++ b/sdk/python/packages/flet/src/flet/controls/material/range_slider.py @@ -20,6 +20,17 @@ class RangeSlider(LayoutControl): A range slider can be used to select from either a continuous or a discrete set of values. The default is to use a continuous range of values from min to max. + + ```python + ft.RangeSlider( + min=0, + max=10, + start_value=2, + divisions=10, + end_value=7, + ) + ``` + """ start_value: Number diff --git a/sdk/python/packages/flet/src/flet/controls/material/reorderable_list_view.py b/sdk/python/packages/flet/src/flet/controls/material/reorderable_list_view.py index 664eea22fb..9863faa500 100644 --- a/sdk/python/packages/flet/src/flet/controls/material/reorderable_list_view.py +++ b/sdk/python/packages/flet/src/flet/controls/material/reorderable_list_view.py @@ -40,6 +40,19 @@ class ReorderableListView(ListView): automatically created drag handle (see [`show_default_drag_handles`][(c).]). To customize the draggable area, use the [`ReorderableDragHandle`][flet.] to define your own drag handle or region. + + ```python + ft.ReorderableListView( + controls=[ + ft.ListTile( + title=ft.Text(f"Item {i}"), + bgcolor=ft.Colors.BLUE_GREY_300, + ) + for i in range(1, 6) + ], + ) + ``` + """ controls: list[Control] = field(default_factory=list) diff --git a/sdk/python/packages/flet/src/flet/testing/__init__.py b/sdk/python/packages/flet/src/flet/testing/__init__.py index fa6a212e4c..d885a09cd4 100644 --- a/sdk/python/packages/flet/src/flet/testing/__init__.py +++ b/sdk/python/packages/flet/src/flet/testing/__init__.py @@ -1,5 +1,6 @@ from flet.testing.finder import Finder from flet.testing.flet_test_app import FletTestApp +from flet.testing.flet_test_app import DisposalMode from flet.testing.tester import Tester -__all__ = ["Finder", "FletTestApp", "Tester"] +__all__ = ["Finder", "FletTestApp", "DisposalMode", "Tester"] diff --git a/sdk/python/packages/flet/src/flet/testing/flet_test_app.py b/sdk/python/packages/flet/src/flet/testing/flet_test_app.py index b20e9c7744..ac8293b7a5 100644 --- a/sdk/python/packages/flet/src/flet/testing/flet_test_app.py +++ b/sdk/python/packages/flet/src/flet/testing/flet_test_app.py @@ -7,6 +7,7 @@ from io import BytesIO from pathlib import Path from typing import Any, Optional +from enum import Enum import numpy as np from PIL import Image @@ -21,6 +22,32 @@ __all__ = ["FletTestApp"] +class DisposalMode(Enum): + """ + Indicates the way in which a frame is treated after being displayed. + """ + + DEFAULT = 0 + """ + No disposal method specified + """ + + NONE = 1 + """ + Do not dispose + """ + + BACKGROUND = 2 + """ + Restore to background color. + """ + + PREVIOUS = 3 + """ + Restore to previous content. + """ + + class FletTestApp: """ Flet app test controller coordinates running a Python-based @@ -425,6 +452,7 @@ def create_gif( *, duration: int = 1000, loop: int = 0, + disposal: DisposalMode = DisposalMode.DEFAULT, ) -> Path: """Create an animated GIF from a sequence of image files. @@ -489,6 +517,7 @@ def create_gif( duration=duration, loop=loop, optimize=True, + disposal=disposal.value, ) finally: for frame in frames: