From 6fb0cbe4abb5bc29e9081afbe24f71d864b40475 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Fri, 28 Aug 2020 12:35:40 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20TESTS:=20Add=20Windows=20OS=20to?= =?UTF-8?q?=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This involved numerous fixes to the code and tests, to use posix strings. There was also an issue of the tempdir being created on a different drive. Therefore, a pytest cmdline option was added to set the location of this directory. Additionally, pip caching was set up on the GitHub CI, and and pytest-timeout config Co-authored-by: phaustin Co-authored-by: foster999 " --- .github/workflows/tests.yml | 53 ++++++++++++++++++----- MANIFEST.in | 1 + conftest.py | 40 +++++++++++++++++ jupyter_book/commands/__init__.py | 10 +++-- setup.py | 1 + tests/conftest.py | 22 ++++------ tests/test_build.py | 44 ++++++++++--------- tests/test_clean.py | 44 +++++++++---------- tests/test_pdf.py | 8 ++-- tests/test_toc.py | 22 +++++++--- tests/test_tocdirective.py | 72 +++++++++++++++++++++++++------ tests/test_utils.py | 6 +-- tox.ini | 1 + 13 files changed, 223 insertions(+), 101 deletions(-) create mode 100644 conftest.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e0ceab01a..3690246bb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python 3.8 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: 3.8 - uses: pre-commit/action@v2.0.0 @@ -34,12 +34,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install Python dependencies run: | python -m pip install --upgrade pip + pip install wheel pip install -e .[testing] - name: Install Headless Chrome dependencies @@ -56,7 +57,6 @@ jobs: texlive-latex-extra \ latexmk - # Tests - name: Run pytest run: | pytest --durations=10 --cov=jupyter_book --cov-report=xml --cov-report=term-missing @@ -87,12 +87,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install Python dependencies run: | python -m pip install --upgrade pip + pip install wheel pip install "sphinx${{ matrix.sphinx }}" pip install -e .[testing] @@ -101,10 +102,33 @@ jobs: sudo apt-get update sudo apt-get install -yq $(cat .github/workflows/pyppeteer_reqs.txt) - # Tests - name: Run pytest + run: pytest --durations=10 -m 'not requires_tex' + + windows: + + name: Tests on Windows + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.7 + uses: actions/setup-python@v2 + with: + python-version: 3.7 + - uses: actions/cache@v2 + with: + path: ~\AppData\Local\pip\Cache + key: ${{ runner.os }}-pip-${{ hashFiles('setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install Python dependencies run: | - pytest --durations=10 -m 'not requires_tex' + python -m pip install --upgrade pip + pip install wheel + pip install --upgrade-strategy eager -e .[testing] + - name: Run pytest + run: pytest --durations=10 -m 'not requires_chrome and not requires_tex' --jb-tempdir local_path # Build the book on OSX to make sure that building the docs works there too build-book-osx: @@ -114,13 +138,20 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python 3.7 - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: 3.7 - - name: Install dependencies + - uses: actions/cache@v2 + with: + path: ~\AppData\Local\pip\Cache + key: ${{ runner.os }}-pip-${{ hashFiles('setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Install Python dependencies run: | python -m pip install --upgrade pip - pip install -e .[sphinx] + pip install wheel + pip install --upgrade-strategy eager -e .[sphinx] - name: Build the book run: | diff --git a/MANIFEST.in b/MANIFEST.in index 253e9e896..d660ff0da 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -17,6 +17,7 @@ exclude .flake8 exclude tox.ini exclude codecov.yml exclude RELEASES.md +exclude conftest.py include LICENSE include CHANGELOG.md diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..9f7819da4 --- /dev/null +++ b/conftest.py @@ -0,0 +1,40 @@ +"""On GH Actions windows-latest, the supplied tmpdir is on a different Drive to the CWD, +and so relative path computations fail. +Therefore, here we allow for the directory to be directly supplied, +via an environmental variable. +""" +import shutil +from pathlib import Path +from uuid import uuid4 + +import pytest + + +def pytest_addoption(parser): + """Define pytest command-line option""" + group = parser.getgroup("jupyter_book") + group.addoption( + "--jb-tempdir", + dest="jb_tempdir", + default=None, + help="Specify a directory in which to create tempdirs", + ) + + +def pytest_report_header(config): + path = "" + if config.getoption("jb_tempdir"): + path = Path(config.getoption("jb_tempdir")).absolute().as_posix() + return [f"JB TEMPDIR: {path}"] + + +@pytest.fixture() +def temp_with_override(pytestconfig, tmpdir): + if pytestconfig.getoption("jb_tempdir"): + path = Path(pytestconfig.getoption("jb_tempdir")).resolve().absolute() + path = path / str(uuid4()) + path.mkdir(parents=True) + yield path + shutil.rmtree(path) + else: + yield Path(tmpdir.dirname) / tmpdir.basename diff --git a/jupyter_book/commands/__init__.py b/jupyter_book/commands/__init__.py index 21cd8c960..d6b0a1269 100644 --- a/jupyter_book/commands/__init__.py +++ b/jupyter_book/commands/__init__.py @@ -385,12 +385,14 @@ def find_config_path(path: Path) -> Tuple[Path, bool]: else: current_dir = path.parent - root_dir = current_dir.root - while str(current_dir) != root_dir: - config_file = os.path.join(str(current_dir), "_config.yml") - if os.path.isfile(config_file): + if (current_dir / "_config.yml").is_file(): + return (current_dir, True) + + while current_dir != current_dir.parent: + if (current_dir / "_config.yml").is_file(): return (current_dir, True) current_dir = current_dir.parent + if not path.is_dir(): return (path.parent, False) return (path, False) diff --git a/setup.py b/setup.py index 8b6cbe967..a79c9ee5e 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ "pytest>=3.6,<4", "pytest-cov", "pytest-xdist", + "pytest-timeout", "beautifulsoup4", "matplotlib", "pytest-regressions", diff --git a/tests/conftest.py b/tests/conftest.py index 0ed7f5fcd..3c9a58630 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,42 +7,38 @@ @pytest.fixture() -def build_resources(tmpdir): +def build_resources(temp_with_override): """Copys ./books and ./books/tocs to a temporary directory and yields the paths as `pathlib.Path` objects. """ src = Path(__file__).parent.resolve().joinpath("books").absolute() - dst = tmpdir.join("books") + dst = temp_with_override / "books" shutil.copytree(src, dst) - books = Path(dst) - tocs = books / "toc" - yield books, tocs + yield Path(dst), Path(dst) / "toc" shutil.rmtree(dst) @pytest.fixture() -def pages(tmpdir): +def pages(temp_with_override): """Copys ./pages to a temporary directory and yields the path as a `pathlib.Path` object. """ src = Path(__file__).parent.joinpath("pages").absolute() - dst = tmpdir.join("pages") + dst = temp_with_override / "pages" shutil.copytree(src, dst) - pages = Path(dst) - yield pages + yield Path(dst) shutil.rmtree(dst) @pytest.fixture() -def docs(tmpdir): +def docs(temp_with_override): """Copys ../docs to a temporary directory and yields the path as a `pathlib.Path` object. """ src = Path(__file__).parent.parent.joinpath("docs").absolute() - dst = tmpdir.join("docs") + dst = temp_with_override / "docs" shutil.copytree(src, dst) - docs = Path(dst) - yield docs + yield Path(dst) shutil.rmtree(dst) diff --git a/tests/test_build.py b/tests/test_build.py index a9d184737..7d0bd17bb 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -16,9 +16,9 @@ def test_version(cli: CliRunner): assert "Jupyter Book" in result.output, result.output -def test_create(tmpdir, cli): - book = Path(tmpdir) / "new_book" - result = cli.invoke(commands.create, str(book)) +def test_create(temp_with_override: Path, cli): + book = temp_with_override / "new_book" + result = cli.invoke(commands.create, book.as_posix()) assert result.exit_code == 0 assert book.joinpath("_config.yml").exists() assert len(list(book.iterdir())) == 9 @@ -31,13 +31,13 @@ def test_validate_yaml(): assert validate_yaml({"title": ""}, raise_on_errors=False) is None -def test_build_from_template(tmpdir, cli): +def test_build_from_template(temp_with_override, cli): """Test building the book template and a few test configs.""" # Create the book from the template - book = Path(tmpdir) / "new_book" - _ = cli.invoke(commands.create, str(book)) - build_result = cli.invoke(commands.build, str(book)) - assert build_result.exit_code == 0 + book = temp_with_override / "new_book" + _ = cli.invoke(commands.create, book.as_posix()) + build_result = cli.invoke(commands.build, book.as_posix()) + assert build_result.exit_code == 0, build_result.output html = book.joinpath("_build", "html") assert html.joinpath("index.html").exists() assert html.joinpath("intro.html").exists() @@ -47,9 +47,9 @@ def test_custom_config(cli, build_resources): """Test a variety of custom configuration values.""" books, _ = build_resources config = books.joinpath("config") - result = cli.invoke(commands.build, str(config)) + result = cli.invoke(commands.build, config.as_posix()) assert result.exit_code == 0 - html = config.joinpath("_build", "html", "index.html").read_text() + html = config.joinpath("_build", "html", "index.html").read_text(encoding="utf8") soup = BeautifulSoup(html, "html.parser") assert '

TEST PROJECT NAME

' in html assert '
' in html @@ -62,11 +62,12 @@ def test_custom_config(cli, build_resources): @pytest.mark.parametrize("toc", ["_toc.yml", "_toc_startwithlist.yml"]) -def test_toc_builds(cli, build_resources, toc, tmpdir): +def test_toc_builds(cli, build_resources, toc): """Test building the book template with several different TOC files.""" books, tocs = build_resources - toc = str(tocs / toc) - result = cli.invoke(commands.build, [str(tocs), "--toc", toc, "-W"]) + result = cli.invoke( + commands.build, [tocs.as_posix(), "--toc", (tocs / toc).as_posix(), "-W"] + ) assert result.exit_code == 0 @@ -79,17 +80,17 @@ def test_toc_rebuild(cli, build_resources): index_html = tocs.joinpath("_build", "html", "index.html") # Not using -W because we expect warnings for pages not listed in TOC - result = cli.invoke(commands.build, [str(tocs), "--toc", str(toc)]) - html = BeautifulSoup(index_html.read_text(), "html.parser") + result = cli.invoke(commands.build, [tocs.as_posix(), "--toc", toc.as_posix()]) + html = BeautifulSoup(index_html.read_text(encoding="utf8"), "html.parser") tags = html.find_all("a", "reference internal") assert result.exit_code == 0 assert tags[1].attrs["href"] == "content1.html" assert tags[2].attrs["href"] == "content2.html" toc.write_text("- file: index\n- file: content2\n- file: content1\n") - result = cli.invoke(commands.build, [str(tocs), "--toc", str(toc)]) + result = cli.invoke(commands.build, [tocs.as_posix(), "--toc", toc.as_posix()]) assert result.exit_code == 0 - html = BeautifulSoup(index_html.read_text(), "html.parser") + html = BeautifulSoup(index_html.read_text(encoding="utf8"), "html.parser") tags = html.find_all("a", "reference internal") # The rendered TOC should reflect the order in the modified _toc.yml assert tags[1].attrs["href"] == "content2.html" @@ -107,9 +108,10 @@ def test_toc_rebuild(cli, build_resources): ) def test_corrupt_toc(build_resources, cli, toc, msg): books, tocs = build_resources - toc = str(tocs / toc) with pytest.raises(RuntimeError): - result = cli.invoke(commands.build, [str(tocs), "--toc", toc, "-W"]) + result = cli.invoke( + commands.build, [tocs.as_posix(), "--toc", (tocs / toc).as_posix(), "-W"] + ) assert result.exit_code == 1 assert msg in result.output raise result.exception @@ -167,7 +169,7 @@ def test_build_page(pages, cli): assert result.exit_code == 0 assert html.joinpath("single_page.html").exists() assert not html.joinpath("extra_page.html").exists() - assert 'url=single_page.html" />' in index.read_text() + assert 'url=single_page.html" />' in index.read_text(encoding="utf8") def test_build_page_nested(build_resources, cli): @@ -181,7 +183,7 @@ def test_build_page_nested(build_resources, cli): assert result.exit_code == 0 assert html.joinpath("markdown.html").exists() assert not html.joinpath("extra_page.html").exists() - assert 'url=markdown.html" />' in index.read_text() + assert 'url=markdown.html" />' in index.read_text(encoding="utf8") @pytest.mark.skipif(sphinx.version_info[0] == 2, reason="randomly fails on CI") diff --git a/tests/test_clean.py b/tests/test_clean.py index 3be9f9a32..a66cae035 100644 --- a/tests/test_clean.py +++ b/tests/test_clean.py @@ -1,21 +1,16 @@ """Testing clean functionality of the CLI.""" import os -from pathlib import Path from click.testing import CliRunner from jupyter_book.commands import build, clean -path_tests = Path(__file__).parent.resolve() -path_books = path_tests.joinpath("books") -path_root = path_tests.parent - - -def test_clean_book(cli: CliRunner, tmpdir): - path = path_books.joinpath("clean_cache") +def test_clean_book(cli: CliRunner, build_resources): + books, tocs = build_resources + path = books.joinpath("clean_cache") build_path = path.joinpath("_build") - result = cli.invoke(build, str(path)) + result = cli.invoke(build, path.as_posix()) assert result.exit_code == 0 # Ensure _build exists @@ -25,14 +20,14 @@ def test_clean_book(cli: CliRunner, tmpdir): assert build_path.joinpath(".jupyter_cache").exists() # Empty _build except .jupyter_cache - result = cli.invoke(clean, str(path)) + result = cli.invoke(clean, path.as_posix()) assert result.exit_code == 0 # Ensure _build and .jupyter_cache exist assert build_path.exists() assert build_path.joinpath(".jupyter_cache").exists() - result = cli.invoke(clean, ("--all", str(path))) + result = cli.invoke(clean, ("--all", path.as_posix())) assert result.exit_code == 0 # Ensure _build is removed assert not path.joinpath("_build").exists() @@ -45,10 +40,11 @@ def test_clean_book(cli: CliRunner, tmpdir): assert "Path to book isn't a directory" in str(result.exception) -def test_clean_html(cli, tmpdir): - path = path_books.joinpath("clean_cache") +def test_clean_html(cli, build_resources): + books, tocs = build_resources + path = books.joinpath("clean_cache") build_path = path.joinpath("_build") - result = cli.invoke(build, str(path)) + result = cli.invoke(build, path.as_posix()) assert result.exit_code == 0 # Ensure _build exists @@ -57,7 +53,7 @@ def test_clean_html(cli, tmpdir): assert build_path.joinpath("html").exists() # Remove html - result = cli.invoke(clean, ("--html", str(path))) + result = cli.invoke(clean, ("--html", path.as_posix())) assert result.exit_code == 0 # Ensure _build exists @@ -67,9 +63,10 @@ def test_clean_html(cli, tmpdir): assert not build_path.joinpath("html").exists() -def test_clean_latex(cli, tmpdir): - path = path_books.joinpath("clean_cache") - result = cli.invoke(build, str(path)) +def test_clean_latex(cli, build_resources): + books, tocs = build_resources + path = books.joinpath("clean_cache") + result = cli.invoke(build, path.as_posix()) assert result.exit_code == 0 build_path = path.joinpath("_build") @@ -82,7 +79,7 @@ def test_clean_latex(cli, tmpdir): assert build_path.joinpath("latex").exists() # Remove html - result = cli.invoke(clean, ("--latex", str(path))) + result = cli.invoke(clean, ("--latex", path.as_posix())) assert result.exit_code == 0 # Ensure _build exists @@ -92,9 +89,10 @@ def test_clean_latex(cli, tmpdir): assert not build_path.joinpath("latex").exists() -def test_clean_html_latex(cli, tmpdir): - path = path_books.joinpath("clean_cache") - result = cli.invoke(build, str(path)) +def test_clean_html_latex(cli, build_resources): + books, tocs = build_resources + path = books.joinpath("clean_cache") + result = cli.invoke(build, path.as_posix()) assert result.exit_code == 0 build_path = path.joinpath("_build") @@ -110,7 +108,7 @@ def test_clean_html_latex(cli, tmpdir): assert build_path.joinpath("html").exists() # Remove html - result = cli.invoke(clean, ("--html", "--latex", str(path))) + result = cli.invoke(clean, ("--html", "--latex", path.as_posix())) assert result.exit_code == 0 # Ensure _build exists diff --git a/tests/test_pdf.py b/tests/test_pdf.py index 918323bd8..7ee01932b 100644 --- a/tests/test_pdf.py +++ b/tests/test_pdf.py @@ -11,8 +11,8 @@ @pytest.mark.requires_chrome -def test_pdfhtml(cli: CliRunner, tmpdir): - path_output = Path(tmpdir).absolute() +def test_pdfhtml(cli: CliRunner, temp_with_override: Path): + path_output = temp_with_override.absolute() # test for build path_template = path_tests.parent.joinpath("jupyter_book", "book_template") @@ -39,8 +39,8 @@ def test_pdfhtml(cli: CliRunner, tmpdir): # TODO: Update to include more detailed tests for pdflatex build chain @pytest.mark.requires_tex -def test_pdflatex(cli: CliRunner, tmpdir): - path_output = Path(tmpdir).absolute() +def test_pdflatex(cli: CliRunner, temp_with_override: Path): + path_output = temp_with_override.absolute() # test for build path_template = path_tests.parent.joinpath("jupyter_book", "book_template") diff --git a/tests/test_toc.py b/tests/test_toc.py index 69ec7af12..b6037bf57 100644 --- a/tests/test_toc.py +++ b/tests/test_toc.py @@ -12,7 +12,7 @@ def test_toc_basic(cli: CliRunner, build_resources): books, tocs = build_resources # run(f"jb toc {tocs}".split(), check=True) - result = cli.invoke(toc, str(tocs)) + result = cli.invoke(toc, tocs.as_posix()) assert result.exit_code == 0 toc_yaml = tocs.joinpath("_toc.yml") @@ -23,7 +23,7 @@ def test_toc_fail(cli: CliRunner, build_resources): """Folder with no content should return none""" books, tocs = build_resources p_empty = tocs.parent - result = cli.invoke(toc, str(p_empty)) + result = cli.invoke(toc, p_empty.as_posix()) assert result.exit_code != 0 assert isinstance(result.exception, RuntimeError) assert "No content files were found in" in str(result.exception) @@ -31,7 +31,7 @@ def test_toc_fail(cli: CliRunner, build_resources): def test_toc_add_titles(cli: CliRunner, build_resources): books, tocs = build_resources - result = cli.invoke(toc, str(tocs)) + result = cli.invoke(toc, tocs.as_posix()) assert result.exit_code == 0 toc_yaml = tocs.joinpath("_toc.yml") res = yaml.safe_load(toc_yaml.read_text(encoding="utf8")) @@ -39,7 +39,7 @@ def test_toc_add_titles(cli: CliRunner, build_resources): for section in res["sections"]: assert "title" not in section - result = cli.invoke(toc, (str(tocs), "--add-titles")) + result = cli.invoke(toc, (tocs.as_posix(), "--add-titles")) assert result.exit_code == 0 toc_yaml = tocs.joinpath("_toc.yml") res = yaml.safe_load(toc_yaml.read_text(encoding="utf8")) @@ -48,9 +48,9 @@ def test_toc_add_titles(cli: CliRunner, build_resources): assert "title" in section -def test_toc_numbered(cli: CliRunner, tmpdir, file_regression): +def test_toc_numbered(cli: CliRunner, temp_with_override, file_regression): """Testing that numbers make it into the sidebar""" - path_output = Path(tmpdir).joinpath("mybook").absolute() + path_output = temp_with_override.joinpath("mybook").absolute() toc_list = [ "_toc_numbered.yml", # Numbered in top-level title "_toc_numbered_parts.yml", # Numbered in top-level title w/ parts @@ -61,7 +61,15 @@ def test_toc_numbered(cli: CliRunner, tmpdir, file_regression): p_toc = path_books.joinpath("toc") path_toc = p_toc.joinpath(itoc) result = cli.invoke( - build, f"{p_toc} --path-output {path_output} --toc {path_toc} -W".split() + build, + [ + p_toc.as_posix(), + "--path-output", + path_output.as_posix(), + "--toc", + path_toc.as_posix(), + "-W", + ], ) assert result.exit_code == 0 diff --git a/tests/test_tocdirective.py b/tests/test_tocdirective.py index 3dd289b1d..a27ed1efa 100644 --- a/tests/test_tocdirective.py +++ b/tests/test_tocdirective.py @@ -1,6 +1,9 @@ +import os from pathlib import Path + from click.testing import CliRunner from bs4 import BeautifulSoup +import pytest from jupyter_book.commands import build @@ -9,14 +12,22 @@ path_root = path_tests.parent -def test_toc_startwithlist(cli: CliRunner, tmpdir, file_regression): +def test_toc_startwithlist(cli: CliRunner, temp_with_override, file_regression): """Testing a basic _toc.yml for tableofcontents directive""" - path_output = Path(tmpdir).joinpath("mybook").absolute() + path_output = temp_with_override.joinpath("mybook").absolute() # Regular TOC should work p_toc = path_books.joinpath("toc") path_toc = p_toc.joinpath("_toc_startwithlist.yml") result = cli.invoke( - build, f"{p_toc} --path-output {path_output} --toc {path_toc} -W".split() + build, + [ + p_toc.as_posix(), + "--path-output", + path_output.as_posix(), + "--toc", + path_toc.as_posix(), + "-W", + ], ) assert result.exit_code == 0 @@ -26,17 +37,25 @@ def test_toc_startwithlist(cli: CliRunner, tmpdir, file_regression): soup = BeautifulSoup(path_toc_directive.read_text(encoding="utf8"), "html.parser") toc = soup.find_all("div", class_="tableofcontents-wrapper")[0] - file_regression.check(str(toc), extension=".html") + file_regression.check(str(toc), extension=".html", encoding="utf8") -def test_toc_parts(cli: CliRunner, tmpdir, file_regression): +def test_toc_parts(cli: CliRunner, temp_with_override, file_regression): """Testing `header` in _toc.yml""" - path_output = Path(tmpdir).joinpath("mybook").absolute() + path_output = temp_with_override.joinpath("mybook").absolute() # Regular TOC should work p_toc = path_books.joinpath("toc") path_toc = p_toc.joinpath("_toc_parts.yml") result = cli.invoke( - build, f"{p_toc} --path-output {path_output} --toc {path_toc} -W".split() + build, + [ + p_toc.as_posix(), + "--path-output", + path_output.as_posix(), + "--toc", + path_toc.as_posix(), + "-W", + ], ) assert result.exit_code == 0 @@ -47,7 +66,10 @@ def test_toc_parts(cli: CliRunner, tmpdir, file_regression): toc = soup.find_all("div", class_="tableofcontents-wrapper")[0] file_regression.check( - str(toc), basename="test_toc_parts_directive", extension=".html" + str(toc), + basename="test_toc_parts_directive", + extension=".html", + encoding="utf8", ) # check the sidebar structure is correct @@ -55,13 +77,21 @@ def test_toc_parts(cli: CliRunner, tmpdir, file_regression): soup.select(".bd-links")[0].prettify(), basename="test_toc_parts_sidebar", extension=".html", + encoding="utf8", ) # TODO: remove these tests in 0.7.5 when chapters: is deprecated # check that using `chapter:` raises a warning but outputs the same thing path_toc = p_toc.joinpath("_toc_chapters.yml") result = cli.invoke( - build, f"{p_toc} --path-output {path_output} --toc {path_toc}".split() + build, + [ + p_toc.as_posix(), + "--path-output", + path_output.as_posix(), + "--toc", + path_toc.as_posix(), + ], ) assert result.exit_code == 0 @@ -71,23 +101,37 @@ def test_toc_parts(cli: CliRunner, tmpdir, file_regression): soup.select(".bd-links")[0].prettify(), basename="test_toc_parts_sidebar", extension=".html", + encoding="utf8", ) -def test_toc_urllink(cli: CliRunner, tmpdir, file_regression): +@pytest.mark.skipif( + os.name == "nt", + reason="Theme error writing content1: " + "filename, directory name, or volume label syntax is incorrect", +) +def test_toc_urllink(cli: CliRunner, temp_with_override, file_regression): """Testing with additional `url` link key in _toc.yml""" - path_output = Path(tmpdir).joinpath("mybook").absolute() + path_output = temp_with_override.joinpath("mybook").absolute() # Regular TOC should work p_toc = path_books.joinpath("toc") path_toc = p_toc.joinpath("_toc_urllink.yml") result = cli.invoke( - build, f"{p_toc} --path-output {path_output} --toc {path_toc} -W".split() + build, + [ + p_toc.as_posix(), + "--path-output", + path_output.as_posix(), + "--toc", + path_toc.as_posix(), + "-W", + ], ) - assert result.exit_code == 0 + assert result.exit_code == 0, result.output path_toc_directive = path_output.joinpath("_build", "html", "index.html") # get the tableofcontents markup soup = BeautifulSoup(path_toc_directive.read_text(encoding="utf8"), "html.parser") toc = soup.find_all("div", class_="tableofcontents-wrapper")[0] - file_regression.check(str(toc), extension=".html") + file_regression.check(str(toc), extension=".html", encoding="utf8") diff --git a/tests/test_utils.py b/tests/test_utils.py index ff36b0c6f..7c00feb2b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,3 @@ -from pathlib import Path - from click.testing import CliRunner import pytest @@ -7,9 +5,9 @@ from jupyter_book.utils import init_myst_file -def test_myst_init(cli: CliRunner, tmpdir): +def test_myst_init(cli: CliRunner, temp_with_override): """Test adding myst metadata to text files.""" - path = Path(tmpdir).joinpath("tmp.md").absolute() + path = temp_with_override.joinpath("tmp.md").absolute() text = "TEST" with open(path, "w") as ff: ff.write(text) diff --git a/tox.ini b/tox.ini index b39359fb6..75e25ac85 100644 --- a/tox.ini +++ b/tox.ini @@ -31,6 +31,7 @@ commands = jupyter-book build -W -n --keep-going --builder html {posargs:docs/} [pytest] +timeout = 100 markers = requires_tex: mark a test which requires a TeX installation. requires_chrome: mark a test which requires a chrome/chromium browser