Skip to content

Commit e38121f

Browse files
authored
🧪 TESTS: Add tests for syntax snippets (#1)
1 parent 163ff7d commit e38121f

18 files changed

+470
-12
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ jobs:
4646
- name: Run pytest
4747
run: |
4848
pytest --cov=sphinx_design --cov-report=xml --cov-report=term-missing
49-
# - name: Upload to Codecov
50-
# if: matrix.python-version == 3.8
51-
# uses: codecov/codecov-action@v1
52-
# with:
53-
# name: pytests
54-
# flags: pytests
55-
# file: ./coverage.xml
56-
# fail_ci_if_error: true
49+
- name: Upload to Codecov
50+
if: matrix.python-version == '3.8' && matrix.os == 'ubuntu-latest'
51+
uses: codecov/codecov-action@v1
52+
with:
53+
name: pytests
54+
flags: pytests
55+
file: ./coverage.xml
56+
fail_ci_if_error: true
5757

5858
publish:
5959

File renamed without changes.

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ code_style =
3838
rtd =
3939
myst-parser~=0.15.0
4040
testing =
41-
pytest~=5.4
41+
myst-parser~=0.15.0
42+
pytest~=6.2
4243
pytest-cov
4344
pytest-regressions
4445
theme_furo =

tests/__init__.py

Whitespace-only changes.

tests/conftest.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import os
2+
from pathlib import Path
3+
from typing import Any, Dict, Optional
4+
5+
import pytest
6+
from docutils import nodes
7+
from sphinx.testing.path import path as sphinx_path
8+
from sphinx.testing.util import SphinxTestApp
9+
10+
pytest_plugins = "sphinx.testing.fixtures"
11+
12+
13+
class SphinxBuilder:
14+
def __init__(self, app: SphinxTestApp, src_path: Path):
15+
self.app = app
16+
self._src_path = src_path
17+
18+
@property
19+
def src_path(self) -> Path:
20+
return self._src_path
21+
22+
@property
23+
def out_path(self) -> Path:
24+
return Path(self.app.outdir)
25+
26+
def build(self, assert_pass=True):
27+
self.app.build()
28+
if assert_pass:
29+
assert self.warnings == "", self.status
30+
return self
31+
32+
@property
33+
def status(self):
34+
return self.app._status.getvalue()
35+
36+
@property
37+
def warnings(self):
38+
return self.app._warning.getvalue()
39+
40+
def get_doctree(
41+
self, docname: str, post_transforms: bool = False
42+
) -> nodes.document:
43+
doctree = self.app.env.get_doctree(docname)
44+
if post_transforms:
45+
self.app.env.apply_post_transforms(doctree, docname)
46+
# make source path consistent for test comparisons
47+
doctree["source"] = (
48+
Path(doctree["source"]).relative_to(self.src_path).as_posix()
49+
)
50+
if doctree["source"].endswith(".rst"):
51+
doctree["source"] = doctree["source"][:-4]
52+
elif doctree["source"].endswith(".md"):
53+
doctree["source"] = doctree["source"][:-3]
54+
# remove mathjax classes added by myst parser
55+
if doctree.children and isinstance(doctree.children[0], nodes.section):
56+
doctree.children[0]["classes"] = []
57+
return doctree
58+
59+
60+
@pytest.fixture()
61+
def sphinx_builder(tmp_path: Path, make_app):
62+
def _create_project(
63+
buildername: str = "html", conf_kwargs: Optional[Dict[str, Any]] = None
64+
):
65+
src_path = tmp_path / "srcdir"
66+
src_path.mkdir()
67+
conf_kwargs = conf_kwargs or {
68+
"extensions": ["myst_parser", "sphinx_design"],
69+
"myst_enable_extensions": ["colon_fence"],
70+
}
71+
content = "\n".join(
72+
[f"{key} = {value!r}" for key, value in conf_kwargs.items()]
73+
)
74+
src_path.joinpath("conf.py").write_text(content, encoding="utf8")
75+
app = make_app(
76+
srcdir=sphinx_path(os.path.abspath(str(src_path))), buildername=buildername
77+
)
78+
return SphinxBuilder(app, src_path)
79+
80+
yield _create_project

tests/test_basic.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/test_snippets.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""Test the documented snippets run correctly, and are the same for both RST and MyST."""
2+
from pathlib import Path
3+
from typing import Callable
4+
5+
import pytest
6+
7+
from .conftest import SphinxBuilder
8+
9+
SNIPPETS_PATH = Path(__file__).parent.parent / "docs" / "snippets"
10+
SNIPPETS_GLOB_RST = list((SNIPPETS_PATH / "rst").glob("[!_]*"))
11+
SNIPPETS_GLOB_MYST = list((SNIPPETS_PATH / "myst").glob("[!_]*"))
12+
13+
14+
@pytest.mark.parametrize(
15+
"path",
16+
SNIPPETS_GLOB_RST,
17+
ids=[path.name[: -len(path.suffix)] for path in SNIPPETS_GLOB_RST],
18+
)
19+
def test_snippets_rst(
20+
sphinx_builder: Callable[..., SphinxBuilder], path: Path, file_regression
21+
):
22+
"""Test snippets written in RestructuredText (before post-transforms)."""
23+
builder = sphinx_builder()
24+
content = "Heading\n-------" + "\n\n" + path.read_text(encoding="utf8")
25+
builder.src_path.joinpath("index.rst").write_text(content, encoding="utf8")
26+
builder.build()
27+
file_regression.check(
28+
builder.get_doctree("index").pformat(),
29+
basename=f"snippet_pre_{path.name[:-len(path.suffix)]}",
30+
extension=".xml",
31+
encoding="utf8",
32+
)
33+
34+
35+
@pytest.mark.parametrize(
36+
"path",
37+
SNIPPETS_GLOB_MYST,
38+
ids=[path.name[: -len(path.suffix)] for path in SNIPPETS_GLOB_MYST],
39+
)
40+
def test_snippets_myst(
41+
sphinx_builder: Callable[..., SphinxBuilder], path: Path, file_regression
42+
):
43+
"""Test snippets written in MyST Markdown (before post-transforms)."""
44+
builder = sphinx_builder()
45+
content = "# Heading" + "\n\n\n" + path.read_text(encoding="utf8")
46+
builder.src_path.joinpath("index.md").write_text(content, encoding="utf8")
47+
builder.build()
48+
file_regression.check(
49+
builder.get_doctree("index").pformat(),
50+
basename=f"snippet_pre_{path.name[:-len(path.suffix)]}",
51+
extension=".xml",
52+
encoding="utf8",
53+
)
54+
55+
56+
@pytest.mark.parametrize(
57+
"path",
58+
SNIPPETS_GLOB_RST,
59+
ids=[path.name[: -len(path.suffix)] for path in SNIPPETS_GLOB_RST],
60+
)
61+
def test_snippets_rst_post(
62+
sphinx_builder: Callable[..., SphinxBuilder], path: Path, file_regression
63+
):
64+
"""Test snippets written in RestructuredText (after HTML post-transforms)."""
65+
builder = sphinx_builder()
66+
content = "Heading\n-------" + "\n\n" + path.read_text(encoding="utf8")
67+
builder.src_path.joinpath("index.rst").write_text(content, encoding="utf8")
68+
builder.build()
69+
file_regression.check(
70+
builder.get_doctree("index", post_transforms=True).pformat(),
71+
basename=f"snippet_post_{path.name[:-len(path.suffix)]}",
72+
extension=".xml",
73+
encoding="utf8",
74+
)
75+
76+
77+
@pytest.mark.parametrize(
78+
"path",
79+
SNIPPETS_GLOB_MYST,
80+
ids=[path.name[: -len(path.suffix)] for path in SNIPPETS_GLOB_MYST],
81+
)
82+
def test_snippets_myst_post(
83+
sphinx_builder: Callable[..., SphinxBuilder], path: Path, file_regression
84+
):
85+
"""Test snippets written in MyST Markdown (after HTML post-transforms)."""
86+
builder = sphinx_builder()
87+
content = "# Heading" + "\n\n\n" + path.read_text(encoding="utf8")
88+
builder.src_path.joinpath("index.md").write_text(content, encoding="utf8")
89+
builder.build()
90+
file_regression.check(
91+
builder.get_doctree("index", post_transforms=True).pformat(),
92+
basename=f"snippet_post_{path.name[:-len(path.suffix)]}",
93+
extension=".xml",
94+
encoding="utf8",
95+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<document source="index">
2+
<section ids="heading" names="heading">
3+
<title>
4+
Heading
5+
<container classes="sd-container-fluid sd-sphinx-override sd-mb-4 sd-border" design_component="grid-container" is_div="True">
6+
<container classes="sd-row sd-row-cols-1 sd-row-cols-xs-1 sd-row-cols-sm-2 sd-row-cols-md-3 sd-row-cols-lg-4" design_component="grid-row" is_div="True">
7+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
8+
<paragraph>
9+
A
10+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
11+
<paragraph>
12+
B
13+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
14+
<paragraph>
15+
C
16+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
17+
<paragraph>
18+
D
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<document source="index">
2+
<section ids="heading" names="heading">
3+
<title>
4+
Heading
5+
<container classes="sd-container-fluid sd-sphinx-override sd-mb-4" design_component="grid-container" is_div="True">
6+
<container classes="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-2 sd-row-cols-md-2 sd-row-cols-lg-2" design_component="grid-row" is_div="True">
7+
<container classes="sd-col sd-d-flex sd-col-auto sd-col-xs-auto sd-col-sm-auto sd-col-md-auto sd-col-lg-auto" design_component="grid-item" is_div="True">
8+
<container classes="sd-card sd-sphinx-override sd-w-100 sd-shadow" design_component="card" is_div="True">
9+
<container classes="sd-card-body" design_component="card-body" is_div="True">
10+
<paragraph classes="sd-card-text">
11+
A
12+
<container classes="sd-col sd-d-flex sd-col-12 sd-col-xs-12 sd-col-sm-6 sd-col-md-6 sd-col-lg-6" design_component="grid-item" is_div="True">
13+
<container classes="sd-card sd-sphinx-override sd-w-100 sd-shadow" design_component="card" is_div="True">
14+
<container classes="sd-card-body" design_component="card-body" is_div="True">
15+
<paragraph classes="sd-card-text">
16+
B
17+
<container classes="sd-col sd-d-flex sd-col-12 sd-col-xs-12 sd-col-sm-12 sd-col-md-12 sd-col-lg-12" design_component="grid-item" is_div="True">
18+
<container classes="sd-card sd-sphinx-override sd-w-100 sd-shadow" design_component="card" is_div="True">
19+
<container classes="sd-card-body" design_component="card-body" is_div="True">
20+
<paragraph classes="sd-card-text">
21+
C
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<document source="index">
2+
<section ids="heading" names="heading">
3+
<title>
4+
Heading
5+
<container classes="sd-container-fluid sd-sphinx-override sd-mb-4" design_component="grid-container" is_div="True">
6+
<container classes="sd-row sd-row-cols-2 sd-row-cols-xs-2 sd-row-cols-sm-2 sd-row-cols-md-2 sd-row-cols-lg-2" design_component="grid-row" is_div="True">
7+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
8+
<container classes="sd-card sd-sphinx-override sd-w-100 sd-shadow" design_component="card" is_div="True">
9+
<container classes="sd-card-body" design_component="card-body" is_div="True">
10+
<container classes="sd-card-title sd-font-weight-bold" design_component="card-title" is_div="True">
11+
Title 1
12+
<paragraph classes="sd-card-text">
13+
A
14+
<container classes="sd-col sd-d-flex" design_component="grid-item" is_div="True">
15+
<container classes="sd-card sd-sphinx-override sd-w-100 sd-shadow" design_component="card" is_div="True">
16+
<container classes="sd-card-body" design_component="card-body" is_div="True">
17+
<container classes="sd-card-title sd-font-weight-bold" design_component="card-title" is_div="True">
18+
Title 2
19+
<paragraph classes="sd-card-text">
20+
B

0 commit comments

Comments
 (0)