Skip to content

Commit

Permalink
Add unit tests for Container (#265)
Browse files Browse the repository at this point in the history
Co-authored-by: petar-qb <[email protected]>
Co-authored-by: Antony Milne <[email protected]>
  • Loading branch information
3 people authored Jan 25, 2024
1 parent 2b6247c commit 25a9ce4
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
A new scriv changelog fragment.
Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨
- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Removed
- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Added
- A bullet item for the Added category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Changed
- A bullet item for the Changed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Deprecated
- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Fixed
- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
<!--
### Security
- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))
-->
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,40 @@ def managers_one_page_four_controls_three_figures_filter_interaction(request, da
id="test_page",
title="My first dashboard",
components=[
vm.Graph(
id="scatter_chart",
figure=px.scatter(px.data.gapminder(), x="lifeExp", y="gdpPercap", custom_data=["continent"]),
actions=[
vm.Action(id="filter_interaction_action", function=filter_interaction(targets=["scatter_chart_2"]))
],
),
vm.Graph(
id="scatter_chart_2",
figure=px.scatter(px.data.gapminder(), x="lifeExp", y="gdpPercap", custom_data=["continent"]),
actions=[vm.Action(id="custom_action", function=custom_action_example())],
),
vm.Table(
id="vizro_table",
figure=dash_data_table_with_id,
actions=[
vm.Action(
id="table_filter_interaction_action",
function=filter_interaction(targets=["scatter_chart", "scatter_chart_2"]),
)
vm.Container(
title="test_container_1",
components=[
vm.Graph(
id="scatter_chart",
figure=px.scatter(px.data.gapminder(), x="lifeExp", y="gdpPercap", custom_data=["continent"]),
actions=[
vm.Action(
id="filter_interaction_action", function=filter_interaction(targets=["scatter_chart_2"])
)
],
),
vm.Container(
title="test_container_2",
components=[
vm.Graph(
id="scatter_chart_2",
figure=px.scatter(
px.data.gapminder(), x="lifeExp", y="gdpPercap", custom_data=["continent"]
),
actions=[vm.Action(id="custom_action", function=custom_action_example())],
),
vm.Table(
id="vizro_table",
figure=dash_data_table_with_id,
actions=[
vm.Action(
id="table_filter_interaction_action",
function=filter_interaction(targets=["scatter_chart", "scatter_chart_2"]),
)
],
),
],
),
],
),
vm.Button(
Expand Down
57 changes: 57 additions & 0 deletions vizro-core/tests/unit/vizro/models/_components/test_container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Unit tests for vizro.models.Container."""
import dash_bootstrap_components as dbc
import pytest
from asserts import STRIP_ALL, assert_component_equal
from dash import html

try:
from pydantic.v1 import ValidationError
except ImportError: # pragma: no cov
from pydantic import ValidationError

import vizro.models as vm


class TestContainerInstantiation:
"""Tests model instantiation and the validators run at that time."""

def test_create_container_mandatory_only(self):
container = vm.Container(title="Title", components=[vm.Button(), vm.Button()])
assert isinstance(container.components[0], vm.Button) and isinstance(container.components[1], vm.Button)
assert container.layout.grid == [[0], [1]]
assert container.title == "Title"

def test_create_container_mandatory_and_optional(self):
container = vm.Container(
title="Title",
components=[vm.Button(), vm.Button()],
id="my-id",
layout=vm.Layout(grid=[[0, 1]]),
)
assert isinstance(container.components[0], vm.Button) and isinstance(container.components[1], vm.Button)
assert container.layout.grid == [[0, 1]]
assert container.title == "Title"
assert container.id == "my-id"

def test_mandatory_title_missing(self):
with pytest.raises(ValidationError, match="field required"):
vm.Container(components=[vm.Button()])

def test_mandatory_components_missing(self):
with pytest.raises(ValidationError, match="field required"):
vm.Container(title="Title")


class TestContainerBuildMethod:
def test_container_build(self):
result = vm.Container(
id="container", title="Title", components=[vm.Button()], layout=vm.Layout(id="layout_id", grid=[[0]])
).build()
assert_component_equal(
result, html.Div(className="page-component-container", id="container"), keys_to_strip={"children"}
)
assert_component_equal(result.children, [html.H3(), html.Div()], keys_to_strip=STRIP_ALL)
# We still want to test the exact H3 produced in Container.build:
assert_component_equal(result.children[0], html.H3("Title"))
# And also that a button has been inserted in the right place:
assert_component_equal(result["layout_id_0"].children.children, dbc.Button(), keys_to_strip=STRIP_ALL)
6 changes: 6 additions & 0 deletions vizro-core/tests/unit/vizro/models/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

import vizro.models as vm
from vizro.models.types import capture


Expand All @@ -10,3 +11,8 @@ def _identity_action_function(arg=None):
return arg

return _identity_action_function


@pytest.fixture(params=[vm.Container, vm.Page])
def model_with_layout(request):
return request.param
47 changes: 39 additions & 8 deletions vizro-core/tests/unit/vizro/models/test_layout.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import numpy as np
import pytest

try:
from pydantic.v1 import ValidationError
except ImportError: # pragma: no cov
from pydantic import ValidationError

import numpy as np
from asserts import assert_component_equal
from dash import html

import vizro.models as vm
from vizro.models._layout import GAP_DEFAULT, MIN_DEFAULT, ColRowGridLines, _get_unique_grid_component_ids

Expand Down Expand Up @@ -147,10 +150,38 @@ def test_working_grid(self, grid):
assert False, f"{grid} raised a value error {ve}."


@pytest.mark.parametrize("grid", [[[0, -1], [1, 2]], [[0, -1, 1, 2]], [[-1, -1, -1], [0, 1, 2]]])
def test_get_unique_grid_component_ids(grid):
result = _get_unique_grid_component_ids(grid)
expected = np.array([0, 1, 2])

assert isinstance(result, np.ndarray)
assert (result == expected).all()
class TestSharedLayoutHelpers:
@pytest.mark.parametrize("grid", [[[0, -1], [1, 2]], [[0, -1, 1, 2]], [[-1, -1, -1], [0, 1, 2]]])
def test_get_unique_grid_component_ids(self, grid):
result = _get_unique_grid_component_ids(grid)
expected = np.array([0, 1, 2])

np.testing.assert_array_equal(result, expected)

def test_set_layout_valid(self, model_with_layout):
model_with_layout(title="Title", components=[vm.Button(), vm.Button()], layout=vm.Layout(grid=[[0, 1]]))

def test_set_layout_invalid(self, model_with_layout):
with pytest.raises(ValidationError, match="Number of page and grid components need to be the same."):
model_with_layout(title="Title", components=[vm.Button()], layout=vm.Layout(grid=[[0, 1]]))


class TestLayoutBuild:
def test_layout_build(self):
result = vm.Layout(grid=[[0, 1], [0, 2]], id="layout_id").build()
expected = html.Div(
[
html.Div(id="layout_id_0", style={"gridColumn": "1/2", "gridRow": "1/3"}),
html.Div(id="layout_id_1", style={"gridColumn": "2/3", "gridRow": "1/2"}),
html.Div(id="layout_id_2", style={"gridColumn": "2/3", "gridRow": "2/3"}),
],
style={
"gridRowGap": "12px",
"gridColumnGap": "12px",
"gridTemplateColumns": f"repeat(2," f"minmax({'0px'}, 1fr))",
"gridTemplateRows": f"repeat(2," f"minmax({'0px'}, 1fr))",
},
className="grid-layout",
id="layout_id",
)
assert_component_equal(result, expected)
22 changes: 22 additions & 0 deletions vizro-core/tests/unit/vizro/models/test_models_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import re

import pytest

try:
from pydantic.v1 import ValidationError
except ImportError: # pragma: no cov
from pydantic import ValidationError

import vizro.models as vm


class TestSharedValidators:
def test_set_components_validator(self, model_with_layout):
with pytest.raises(ValidationError, match="Ensure this value has at least 1 item."):
model_with_layout(title="Title", components=[])

def test_check_for_valid_component_types(self, model_with_layout):
with pytest.raises(
ValidationError, match=re.escape("(allowed values: 'button', 'card', 'container', 'graph', 'table')")
):
model_with_layout(title="Page Title", components=[vm.Checklist()])
18 changes: 0 additions & 18 deletions vizro-core/tests/unit/vizro/models/test_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ def test_mandatory_components_missing(self):
with pytest.raises(ValidationError, match="field required"):
vm.Page(title="Page 1")

def test_mandatory_components_invalid(self):
with pytest.raises(ValidationError, match="Ensure this value has at least 1 item."):
vm.Page(title="Page 5", components=[])

def test_set_id_duplicate_title_valid(self):
vm.Page(title="Page 1", components=[vm.Button()], id="my-id-1")
vm.Page(title="Page 1", components=[vm.Button()], id="my-id-2")
Expand Down Expand Up @@ -85,20 +81,6 @@ def test_set_path_invalid(self, test_path):
page = vm.Page(title="Page 1", components=[vm.Button()], path=test_path)
assert page.path == "/this-needs-fixing"

def test_set_layout_valid(self):
vm.Page(title="Page 1", components=[vm.Button(), vm.Button()], layout=vm.Layout(grid=[[0, 1]]))

def test_set_layout_invalid(self):
with pytest.raises(ValidationError, match="Number of page and grid components need to be the same."):
vm.Page(title="Page 4", components=[vm.Button()], layout=vm.Layout(grid=[[0, 1]]))

def test_check_for_valid_component_types(self):
with pytest.raises(
ValidationError,
match=re.escape("(allowed values: 'button', 'card', 'container', 'graph', 'table')"),
):
vm.Page(title="Page Title", components=[vm.Checklist()])

def test_check_for_valid_control_types(self):
with pytest.raises(ValidationError, match=re.escape("(allowed values: 'filter', 'parameter')")):
vm.Page(title="Page Title", components=[vm.Button()], controls=[vm.Button()])
Expand Down

0 comments on commit 25a9ce4

Please sign in to comment.