-
Notifications
You must be signed in to change notification settings - Fork 117
test: Add unit and pytest tests, coverage config, and Makefile targets #2152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
876e9ea
2ce8333
2f48f12
3bffa5e
6a83d20
d05d797
1b29800
d9c226e
71284cc
f0f04c1
9e25a40
8c0a3e6
3bc190e
939806a
5d291f3
063b120
75cc4e3
a3c1c34
5f16691
ca1f8a3
f0d49b8
f4cb254
552cd85
921c289
597a99d
5597104
e437362
ace416d
7f2f646
702eabb
2539bbd
0efd5c3
746a07a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -44,18 +44,20 @@ class MISSING_TYPE: | |||||||||
| pass | ||||||||||
|
|
||||||||||
|
|
||||||||||
| MISSING: MISSING_TYPE = MISSING_TYPE() | ||||||||||
| DEPRECATED: MISSING_TYPE = MISSING_TYPE() # A MISSING that communicates deprecation | ||||||||||
| MISSING: MISSING_TYPE = MISSING_TYPE() # pragma: no cover | ||||||||||
| DEPRECATED: MISSING_TYPE = ( | ||||||||||
| MISSING_TYPE() | ||||||||||
| ) # A MISSING that communicates deprecation # pragma: no cover | ||||||||||
|
Comment on lines
+48
to
+50
|
||||||||||
| DEPRECATED: MISSING_TYPE = ( | |
| MISSING_TYPE() | |
| ) # A MISSING that communicates deprecation # pragma: no cover | |
| DEPRECATED: MISSING_TYPE = MISSING_TYPE() # A MISSING that communicates deprecation # pragma: no cover |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The # pragma: no cover comments are redundant on both the decorator and the class definition. The exclusion pattern in pyproject.toml already excludes class .*\(TypedDict\): lines. Remove the duplicate pragma comments to reduce clutter.
| @add_example(ex_dir="./api-examples/input_file") # pragma: no cover | |
| class FileInfo(TypedDict): # pragma: no cover | |
| @add_example(ex_dir="./api-examples/input_file") | |
| class FileInfo(TypedDict): |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above - these # pragma: no cover comments are redundant given the TypedDict exclusion pattern in pyproject.toml configuration.
| class ImgData(TypedDict): # pragma: no cover | |
| class ImgData(TypedDict): |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The # pragma: no cover comment on line 191 is redundant. The exclusion pattern ^ pass$ in pyproject.toml already excludes standalone pass statements. Only the class definition line needs the pragma comment.
| pass # pragma: no cover | |
| pass |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| """Tests for accordion UI components.""" | ||
|
|
||
| from shiny.ui import ( | ||
| accordion, | ||
| accordion_panel, | ||
| ) | ||
|
|
||
|
|
||
| class TestAccordionPanel: | ||
| """Tests for accordion_panel function.""" | ||
|
|
||
| def test_basic_accordion_panel(self): | ||
| """Test creating a basic accordion panel.""" | ||
| panel = accordion_panel("Panel Title", "Panel content") | ||
| assert panel is not None | ||
| assert panel._data_value == "Panel Title" | ||
|
|
||
| def test_accordion_panel_with_value(self): | ||
| """Test accordion panel with explicit value.""" | ||
| panel = accordion_panel("Display Title", "Content", value="panel_id") | ||
| assert panel._data_value == "panel_id" | ||
|
|
||
| def test_accordion_panel_with_icon(self): | ||
| """Test accordion panel with icon.""" | ||
| from htmltools import tags | ||
|
|
||
| icon = tags.i(class_="fa fa-cog") | ||
| panel = accordion_panel("Settings", "Settings content", icon=icon) | ||
| assert panel is not None | ||
| assert panel._icon is not None | ||
|
|
||
|
|
||
| class TestAccordion: | ||
| """Tests for accordion function.""" | ||
|
|
||
| def test_basic_accordion(self): | ||
| """Test creating a basic accordion.""" | ||
| acc = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| accordion_panel("Panel 2", "Content 2"), | ||
| ) | ||
| html = str(acc) | ||
|
|
||
| assert "accordion" in html | ||
| assert "Panel 1" in html | ||
| assert "Panel 2" in html | ||
|
|
||
| def test_accordion_with_id(self): | ||
| """Test accordion with id.""" | ||
| acc = accordion(accordion_panel("Panel 1", "Content 1"), id="my_accordion") | ||
| html = str(acc) | ||
|
|
||
| assert "my_accordion" in html | ||
|
|
||
| def test_accordion_open_panels(self): | ||
| """Test accordion with specific panels open.""" | ||
| acc = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| accordion_panel("Panel 2", "Content 2"), | ||
| open="Panel 1", | ||
| ) | ||
| html = str(acc) | ||
|
|
||
| assert "Panel 1" in html | ||
|
|
||
| def test_accordion_open_all(self): | ||
| """Test accordion with all panels open.""" | ||
| acc = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| accordion_panel("Panel 2", "Content 2"), | ||
| open=True, | ||
| ) | ||
| html = str(acc) | ||
|
|
||
| assert "Panel 1" in html | ||
|
|
||
| def test_accordion_multiple(self): | ||
| """Test accordion that allows multiple panels open.""" | ||
| acc = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| accordion_panel("Panel 2", "Content 2"), | ||
| multiple=True, | ||
| ) | ||
| html = str(acc) | ||
|
|
||
| assert "accordion" in html | ||
|
|
||
| def test_accordion_width(self): | ||
| """Test accordion with explicit width.""" | ||
| acc = accordion(accordion_panel("Panel 1", "Content 1"), width="400px") | ||
| html = str(acc) | ||
|
|
||
| assert "400px" in html | ||
|
|
||
| def test_accordion_height(self): | ||
| """Test accordion with explicit height.""" | ||
| acc = accordion(accordion_panel("Panel 1", "Content 1"), height="300px") | ||
| html = str(acc) | ||
|
|
||
| assert "300px" in html |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| """Tests for shiny/ui/_accordion.py module.""" | ||
|
|
||
| from shiny.ui._accordion import AccordionPanel, accordion, accordion_panel | ||
|
|
||
|
|
||
| class TestAccordion: | ||
| """Tests for accordion function.""" | ||
|
|
||
| def test_accordion_is_callable(self): | ||
| """Test accordion is callable.""" | ||
| assert callable(accordion) | ||
|
|
||
| def test_accordion_returns_tag(self): | ||
| """Test accordion returns a Tag.""" | ||
| from htmltools import Tag | ||
|
|
||
| result = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| accordion_panel("Panel 2", "Content 2"), | ||
| ) | ||
| assert isinstance(result, Tag) | ||
|
|
||
| def test_accordion_with_id(self): | ||
| """Test accordion with id parameter.""" | ||
| from htmltools import Tag | ||
|
|
||
| result = accordion( | ||
| accordion_panel("Panel 1", "Content 1"), | ||
| id="my_accordion", | ||
| ) | ||
| assert isinstance(result, Tag) | ||
|
|
||
|
|
||
| class TestAccordionPanel: | ||
| """Tests for accordion_panel function.""" | ||
|
|
||
| def test_accordion_panel_is_callable(self): | ||
| """Test accordion_panel is callable.""" | ||
| assert callable(accordion_panel) | ||
|
|
||
| def test_accordion_panel_returns_accordion_panel(self): | ||
| """Test accordion_panel returns an AccordionPanel object.""" | ||
| result = accordion_panel("Panel Title", "Content") | ||
| assert isinstance(result, AccordionPanel) | ||
|
|
||
|
|
||
| class TestAccordionPanelClass: | ||
| """Tests for AccordionPanel class.""" | ||
|
|
||
| def test_accordion_panel_class_exists(self): | ||
| """Test AccordionPanel class exists.""" | ||
| assert AccordionPanel is not None | ||
|
|
||
|
|
||
| class TestAccordionExported: | ||
| """Tests for accordion functions export.""" | ||
|
|
||
| def test_accordion_in_ui(self): | ||
| """Test accordion is in ui module.""" | ||
| from shiny import ui | ||
|
|
||
| assert hasattr(ui, "accordion") | ||
|
|
||
| def test_accordion_panel_in_ui(self): | ||
| """Test accordion_panel is in ui module.""" | ||
| from shiny import ui | ||
|
|
||
| assert hasattr(ui, "accordion_panel") | ||
|
|
||
| def test_update_accordion_in_ui(self): | ||
| """Test update_accordion is in ui module.""" | ||
| from shiny import ui | ||
|
|
||
| assert hasattr(ui, "update_accordion") | ||
|
|
||
| def test_update_accordion_panel_in_ui(self): | ||
| """Test update_accordion_panel is in ui module.""" | ||
| from shiny import ui | ||
|
|
||
| assert hasattr(ui, "update_accordion_panel") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 30-minute timeout seems quite generous given the PR description states execution time increased to 5 minutes. Consider setting a more appropriate timeout (e.g., 10-15 minutes) to catch runaway tests earlier while still providing adequate buffer.