From da5e6e787a228787db0efd5e5b78f5662623be03 Mon Sep 17 00:00:00 2001 From: Cody Scott Date: Sat, 27 Jan 2024 21:33:39 -0500 Subject: [PATCH] Refactor tests and run linting on tests --- README.md | 4 +- pyproject.toml | 3 + tests/conftest.py | 15 ++ tests/test_app.py | 26 +-- tests/test_build.py | 209 +++++++++------------ tests/test_drafts.py | 30 ++-- tests/test_post_dates.py | 380 +++++++++++++++++---------------------- tests/test_preview.py | 9 +- tests/test_templates.py | 9 +- tests/test_verify.py | 181 ++++++++----------- tests/utils.py | 2 +- 11 files changed, 379 insertions(+), 489 deletions(-) create mode 100644 tests/conftest.py diff --git a/README.md b/README.md index 6f944fd..289c623 100644 --- a/README.md +++ b/README.md @@ -71,14 +71,14 @@ $ ../venv/bin/htmd build ```shell $ venv/bin/python -m pip install mypy types-Pygments types-beautifulsoup4 -$ venv/bin/python -m mypy htmd typehints +$ venv/bin/python -m mypy . ``` ### Running ruff ```shell $ venv/bin/python -m pip install ruff -$ venv/bin/python -m ruff check htmd +$ venv/bin/python -m ruff check --exclude typehints ``` diff --git a/pyproject.toml b/pyproject.toml index 6ff168d..0d2c204 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,10 @@ order-by-type = false section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"] [tool.ruff.per-file-ignores] +"tests/test_app.py" = ["ARG001"] "tests/test_build.py" = ["I001"] +"tests/test_drafts.py" = ["ARG001", "I001"] +"tests/test_post_dates.py" = ["I001"] "tests/test_verify.py" = ["I001"] [tool.setuptools] diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..7123adc --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,15 @@ +from collections.abc import Generator + +from click.testing import CliRunner +from htmd.cli import start +import pytest + + +@pytest.fixture(scope='function') # noqa: PT003 +def run_start() -> Generator[CliRunner, None, None]: + runner = CliRunner() + with runner.isolated_filesystem(): + result = runner.invoke(start) + assert result.exit_code == 0 + # Tests code is run here + yield runner diff --git a/tests/test_app.py b/tests/test_app.py index 8120393..cfabc3e 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,41 +1,45 @@ +from collections.abc import Generator + from click.testing import CliRunner +from flask import Flask +from flask.testing import FlaskClient from htmd.cli import start import pytest @pytest.fixture(scope='module') -def run_start(): +def run_start() -> Generator[CliRunner, None, None]: runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke(start) assert result.exit_code == 0 # Tests code is run here - yield + yield runner @pytest.fixture() -def flask_app(run_start): +def flask_app(run_start: CliRunner) -> Flask: from htmd.site import app app.config.update({ 'TESTING': True, }) - yield app + return app @pytest.fixture() -def client(flask_app): +def client(flask_app: Flask) -> FlaskClient: return flask_app.test_client() -def test_author_does_not_exist(client) -> None: +def test_author_does_not_exist(client: FlaskClient) -> None: # If the author doesn't exist it will be a 404 - response = client.get("/author/dne/") - assert 404 == response.status_code + response = client.get('/author/dne/') + assert response.status_code == 404 # noqa: PLR2004 -def test_page_does_not_exist(client) -> None: +def test_page_does_not_exist(client: FlaskClient) -> None: # Ensure htmd preview matches build # Only pages will be served # before this change pages.page was serving templates - response = client.get("/author/") - assert 404 == response.status_code + response = client.get('/author/') + assert response.status_code == 404 # noqa: PLR2004 diff --git a/tests/test_build.py b/tests/test_build.py index 3a114f9..7467191 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -4,7 +4,7 @@ import shutil from click.testing import CliRunner -from htmd.cli import build, start +from htmd.cli import build from utils import remove_fields_from_example_post @@ -15,128 +15,97 @@ ) -def test_build() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(build) +def test_build(run_start: CliRunner) -> None: + result = run_start.invoke(build) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_verify_fails() -> None: +def test_build_verify_fails(run_start: CliRunner) -> None: expected_output = 'Post "example" does not have field title.\n' - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - remove_fields_from_example_post(('title',)) - result = runner.invoke(build) + remove_fields_from_example_post(('title',)) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_js_minify() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) +def test_build_js_minify(run_start: CliRunner) -> None: + with (Path('static') / 'app.js').open('w') as js_file: + js_file.write('console.log("htmd");') - with (Path('static') / 'app.js').open('w') as js_file: - js_file.write('console.log("htmd");') - - result = runner.invoke(build, ['--js-minify']) + result = run_start.invoke(build, ['--js-minify']) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_js_minify_no_js_files() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(build, ['--js-minify']) +def test_build_js_minify_no_js_files(run_start: CliRunner) -> None: + result = run_start.invoke(build, ['--js-minify']) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_no_js_minify() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(build, ['--no-js-minify']) +def test_build_no_js_minify(run_start: CliRunner) -> None: + result = run_start.invoke(build, ['--no-js-minify']) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_css_minify() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(build, ['--css-minify']) - with (Path('build') / 'index.html').open('r') as built_index: - contents = built_index.read() +def test_build_css_minify(run_start: CliRunner) -> None: + result = run_start.invoke(build, ['--css-minify']) + with (Path('build') / 'index.html').open('r') as built_index: + contents = built_index.read() assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) assert 'combined.min.css' in contents -def test_build_no_css_minify() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(build, ['--no-css-minify']) +def test_build_no_css_minify(run_start: CliRunner) -> None: + result = run_start.invoke(build, ['--no-css-minify']) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_css_minify_no_css_files() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - (Path('static') / 'style.css').unlink() - (Path('static') / '_reset.css').unlink() - result = runner.invoke(build, ['--css-minify']) +def test_build_css_minify_no_css_files(run_start: CliRunner) -> None: + (Path('static') / 'style.css').unlink() + (Path('static') / '_reset.css').unlink() + result = run_start.invoke(build, ['--css-minify']) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_html_pretty_true() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with Path('config.toml').open('r') as config_file: - lines = config_file.readlines() +def test_build_html_pretty_true(run_start: CliRunner) -> None: + with Path('config.toml').open('r') as config_file: + lines = config_file.readlines() - with Path('config.toml').open('w') as config_file: - for line in lines: - if 'pretty =' in line: - config_file.write('pretty = true\n') - else: - config_file.write(line) + with Path('config.toml').open('w') as config_file: + for line in lines: + if 'pretty =' in line: + config_file.write('pretty = true\n') + else: + config_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_html_minify_true() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with Path('config.toml').open('r') as config_file: - lines = config_file.readlines() +def test_build_html_minify_true(run_start: CliRunner) -> None: + with Path('config.toml').open('r') as config_file: + lines = config_file.readlines() - with Path('config.toml').open('w') as config_file: - for line in lines: - if 'minify =' in line: - config_file.write('minify = true\n') - else: - config_file.write(line) + with Path('config.toml').open('w') as config_file: + for line in lines: + if 'minify =' in line: + config_file.write('minify = true\n') + else: + config_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_page_404() -> None: +def test_build_page_404(run_start: CliRunner) -> None: # Linking to a page that doesn't exist # will cause a 404 status code # and stop the build @@ -144,61 +113,48 @@ def test_build_page_404() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /dne/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() - - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) - - result = runner.invoke(build) + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() + + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) + + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_multiple_posts() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - shutil.copyfile( - Path('posts') / 'example.md', - Path('posts') / 'sample.md', - ) - result = runner.invoke(build) +def test_build_multiple_posts(run_start: CliRunner) -> None: + shutil.copyfile( + Path('posts') / 'example.md', + Path('posts') / 'sample.md', + ) + result = run_start.invoke(build) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_from_sub_directory() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - current_directory = Path.cwd() - os.chdir(Path(current_directory) / 'posts') - result = runner.invoke(build) +def test_build_from_sub_directory(run_start: CliRunner) -> None: + current_directory = Path.cwd() + os.chdir(Path(current_directory) / 'posts') + result = run_start.invoke(build) assert result.exit_code == 0 assert re.search(SUCCESS_REGEX, result.output) -def test_build_feed_dot_atom() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - result = runner.invoke(build) - assert result.exit_code == 0 - current_directory = Path.cwd() - assert (Path(current_directory) / 'build' / 'feed.atom').is_file +def test_build_feed_dot_atom(run_start: CliRunner) -> None: + result = run_start.invoke(build) + assert result.exit_code == 0 + current_directory = Path.cwd() + assert (Path(current_directory) / 'build' / 'feed.atom').is_file() -def test_build_page_without_link() -> None: +def test_build_page_without_link(run_start: CliRunner) -> None: page_lines = ( "{% extends '_layout.html' %}\n", '\n', @@ -211,14 +167,11 @@ def test_build_page_without_link() -> None: ' \n', '{% endblock content %}\n', ) - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - # Create page that is doesn't have a link in the site - with (Path('pages') / 'new.html').open('w') as page_file: - for line in page_lines: - page_file.write(line) - result = runner.invoke(build) - assert result.exit_code == 0 - with (Path('build') / 'new' / 'index.html').open('r') as page_file: - assert 'Totally new' in page_file.read() + # Create page that is doesn't have a link in the site + with (Path('pages') / 'new.html').open('w') as page_file: + for line in page_lines: + page_file.write(line) + result = run_start.invoke(build) + assert result.exit_code == 0 + with (Path('build') / 'new' / 'index.html').open('r') as page_file: + assert 'Totally new' in page_file.read() diff --git a/tests/test_drafts.py b/tests/test_drafts.py index 2be73c1..8123c32 100644 --- a/tests/test_drafts.py +++ b/tests/test_drafts.py @@ -1,3 +1,4 @@ +from collections.abc import Generator from pathlib import Path from click.testing import CliRunner @@ -7,7 +8,7 @@ from utils import remove_fields_from_example_post -def set_example_as_draft(): +def set_example_as_draft() -> None: remove_fields_from_example_post(('draft',)) post_path = Path('posts') / 'example.md' with post_path.open('r') as post_file: @@ -20,7 +21,7 @@ def set_example_as_draft(): @pytest.fixture(scope='module') -def build_draft(): +def build_draft() -> Generator[None, None, None]: # noqa: PT004 runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke(start) @@ -29,55 +30,56 @@ def build_draft(): assert result.exit_code == 0 # Tests code is run here yield - -def test_draft_is_built(build_draft) -> None: - with (Path('build') / '2014' / '10' / '30' / 'example' / 'index.html').open('r') as post_page: + +def test_draft_is_built(build_draft: None) -> None: + post_path = (Path('build') / '2014' / '10' / '30' / 'example' / 'index.html') + with post_path.open('r') as post_page: assert 'Example Post' in post_page.read() -def test_no_drafts_home(build_draft) -> None: +def test_no_drafts_home(build_draft: None) -> None: with (Path('build') / 'index.html').open('r') as home_page: assert 'Example Post' not in home_page.read() -def test_no_drafts_atom_feed(build_draft) -> None: +def test_no_drafts_atom_feed(build_draft: None) -> None: with (Path('build') / 'feed.atom').open('r') as feed_page: assert 'Example Post' not in feed_page.read() -def test_no_drafts_all_posts(build_draft) -> None: +def test_no_drafts_all_posts(build_draft: None) -> None: with (Path('build') / 'all' / 'index.html').open('r') as web_page: assert 'Example Post' not in web_page.read() -def test_no_drafts_all_tags(build_draft) -> None: +def test_no_drafts_all_tags(build_draft: None) -> None: with (Path('build') / 'tags' / 'index.html').open('r') as web_page: assert 'first' not in web_page.read() -def test_no_drafts_in_tag(build_draft) -> None: +def test_no_drafts_in_tag(build_draft: None) -> None: # tag page exists because the draft links to it with (Path('build') / 'tags' / 'first' / 'index.html').open('r') as web_page: assert 'Example Post' not in web_page.read() -def test_no_drafts_for_author(build_draft) -> None: +def test_no_drafts_for_author(build_draft: None) -> None: # author page exists because the draft links to it with (Path('build') / 'author' / 'Taylor' / 'index.html').open('r') as web_page: assert 'Example Post' not in web_page.read() -def test_no_drafts_for_year(build_draft) -> None: +def test_no_drafts_for_year(build_draft: None) -> None: # folder exists becaues of URL for post assert (Path('build') / '2014' / 'index.html').exists() is False -def test_no_drafts_for_month(build_draft) -> None: +def test_no_drafts_for_month(build_draft: None) -> None: # folder exists becaues of URL for post assert (Path('build') / '2014' / '10' / 'index.html').exists() is False -def test_no_drafts_for_day(build_draft) -> None: +def test_no_drafts_for_day(build_draft: None) -> None: # folder exists becaues of URL for post assert (Path('build') / '2014' / '10' / '30' / 'index.html').exists() is False diff --git a/tests/test_post_dates.py b/tests/test_post_dates.py index 8236659..f154e79 100644 --- a/tests/test_post_dates.py +++ b/tests/test_post_dates.py @@ -2,99 +2,89 @@ from pathlib import Path from click.testing import CliRunner -from htmd.cli import build, start +from htmd.cli import build from utils import remove_fields_from_example_post -def test_build_post_404_invalid_date_year() -> None: +def test_build_post_404_invalid_date_year(run_start: CliRunner) -> None: # Linking to a post with incorrect values # for dates will cause 404 and stop the build expected_output = ( 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /14/10/30/example/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_post_404_invalid_date_month() -> None: +def test_build_post_404_invalid_date_month(run_start: CliRunner) -> None: # Linking to a post with incorrect values # for dates will cause 404 and stop the build expected_output = ( 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2014/1/30/example/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with (Path('posts') / 'example.md').open('r') as post_file: - lines = post_file.readlines() + with (Path('posts') / 'example.md').open('r') as post_file: + lines = post_file.readlines() - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_post_404_invalid_date_day() -> None: +def test_build_post_404_invalid_date_day(run_start: CliRunner) -> None: # Linking to a post with incorrect values # for dates will cause 404 and stop the build expected_output = ( 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2014/10/3/example/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) + with (Path('posts') / 'example.md').open('r') as post_file: + lines = post_file.readlines() - with (Path('posts') / 'example.md').open('r') as post_file: - lines = post_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) - - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_post_404_different_date() -> None: +def test_build_post_404_different_date(run_start: CliRunner) -> None: # Linking to a page with the wrong date # will cause a 404 status code # and stop the build @@ -102,27 +92,23 @@ def test_build_post_404_different_date() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2014/10/29/example/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() - - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) - - result = runner.invoke(build) + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() + + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) + + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_year_404_incorrect() -> None: +def test_build_year_404_incorrect(run_start: CliRunner) -> None: # Linking to a page with the wrong date # will cause a 404 status code # and stop the build @@ -130,27 +116,24 @@ def test_build_year_404_incorrect() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /14/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) + new_line = '''

DNE link

\n''' + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_year_404_no_posts() -> None: +def test_build_year_404_no_posts(run_start: CliRunner) -> None: # Linking to a page with the wrong date # will cause a 404 status code # and stop the build @@ -158,27 +141,23 @@ def test_build_year_404_no_posts() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2013/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() - - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) - - result = runner.invoke(build) + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() + + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) + + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_month_404_no_posts() -> None: +def test_build_month_404_no_posts(run_start: CliRunner) -> None: # Linking to a page with the wrong date # will cause a 404 status code # and stop the build @@ -186,27 +165,24 @@ def test_build_month_404_no_posts() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2014/01/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_day_404_no_posts() -> None: +def test_build_day_404_no_posts(run_start: CliRunner) -> None: # Linking to a page with the wrong date # will cause a 404 status code # and stop the build @@ -214,40 +190,34 @@ def test_build_day_404_no_posts() -> None: 'All posts are correctly formatted.\n' "Unexpected status '404 NOT FOUND' on URL /2014/10/29/\n" ) - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - with (Path('pages') / 'about.html').open('r') as about_file: - lines = about_file.readlines() + with (Path('pages') / 'about.html').open('r') as about_file: + lines = about_file.readlines() - new_line = '''

DNE link

\n''' # noqa: E501 - with (Path('pages') / 'about.html').open('w') as about_file: - for line in lines: - if '

This is the about page.

' in line: - about_file.write(new_line) - else: - about_file.write(line) + new_line = '''

DNE link

\n''' # noqa: E501 + with (Path('pages') / 'about.html').open('w') as about_file: + for line in lines: + if '

This is the about page.

' in line: + about_file.write(new_line) + else: + about_file.write(line) - result = runner.invoke(build) + result = run_start.invoke(build) assert result.exit_code == 1 assert result.output == expected_output -def test_build_updated_time_is_added() -> None: +def test_build_updated_time_is_added(run_start: CliRunner) -> None: # If there is no published/updated time then # build will add it # verify that time is not there # ensure correct time is added - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - with (Path('posts') / 'example.md').open('r') as post_file: - b_lines = post_file.readlines() - result = runner.invoke(build) - assert result.exit_code == 0 - with (Path('posts') / 'example.md').open('r') as post_file: - a_lines = post_file.readlines() + with (Path('posts') / 'example.md').open('r') as post_file: + b_lines = post_file.readlines() + result = run_start.invoke(build) + assert result.exit_code == 0 + with (Path('posts') / 'example.md').open('r') as post_file: + a_lines = post_file.readlines() for b_line, a_line in zip(b_lines, a_lines, strict=True): if 'updated' in b_line: b_updated = b_line @@ -284,21 +254,18 @@ def test_build_updated_time_is_added() -> None: assert time_difference.total_seconds() < threshold_seconds -def test_build_published_time_is_added() -> None: +def test_build_published_time_is_added(run_start: CliRunner) -> None: # If there is no published/updated time then # build will add it # verify that time is not there # ensure correct time is added - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - remove_fields_from_example_post(('updated',)) - with (Path('posts') / 'example.md').open('r') as post_file: - b_lines = post_file.readlines() - result = runner.invoke(build) - assert result.exit_code == 0 - with (Path('posts') / 'example.md').open('r') as post_file: - a_lines = post_file.readlines() + remove_fields_from_example_post(('updated',)) + with (Path('posts') / 'example.md').open('r') as post_file: + b_lines = post_file.readlines() + result = run_start.invoke(build) + assert result.exit_code == 0 + with (Path('posts') / 'example.md').open('r') as post_file: + a_lines = post_file.readlines() for b_line, a_line in zip(b_lines, a_lines, strict=True): if 'published' in b_line: b_published = b_line @@ -331,23 +298,23 @@ def test_build_published_time_is_added() -> None: assert 'updated' not in ''.join(a_lines) -def test_build_updated_is_added() -> None: - # If published has a time - # and there is no updated then - # build will add updated with time - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - # Remove updated from example post - remove_fields_from_example_post(('updated',)) - # First build adds time to published - result = runner.invoke(build) - assert result.exit_code == 0 - # Second build adds updated with time - result2 = runner.invoke(build) - assert result2.exit_code == 0 - with (Path('posts') / 'example.md').open('r') as post_file: - a_lines = post_file.readlines() +def test_build_updated_is_added(run_start: CliRunner) -> None: + """ + Verify updated is added. + + If published has a time and there is no updated + then build will add updated with time. + """ + # Remove updated from example post + remove_fields_from_example_post(('updated',)) + # First build adds time to published + result = run_start.invoke(build) + assert result.exit_code == 0 + # Second build adds updated with time + result2 = run_start.invoke(build) + assert result2.exit_code == 0 + with (Path('posts') / 'example.md').open('r') as post_file: + a_lines = post_file.readlines() for a_line in a_lines: if 'updated' in a_line: a_updated = a_line @@ -367,28 +334,25 @@ def test_build_updated_is_added() -> None: assert time_difference.total_seconds() < threshold_seconds -def test_build_updated_is_added_once() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - # Remove updated from example post - with (Path('posts') / 'example.md').open('r') as post_file: - b_lines = post_file.readlines() - with (Path('posts') / 'example.md').open('w') as post_file: - for line in b_lines: - if 'updated' not in line: - post_file.write(line) - # add "..." to post content - post_file.write('...\n') - - # First build adds published time - result = runner.invoke(build) - assert result.exit_code == 0 - # Second build adds updated - result2 = runner.invoke(build) - assert result2.exit_code == 0 - with (Path('posts') / 'example.md').open('r') as post_file: - a_lines = post_file.readlines() +def test_build_updated_is_added_once(run_start: CliRunner) -> None: + # Remove updated from example post + with (Path('posts') / 'example.md').open('r') as post_file: + b_lines = post_file.readlines() + with (Path('posts') / 'example.md').open('w') as post_file: + for line in b_lines: + if 'updated' not in line: + post_file.write(line) + # add "..." to post content + post_file.write('...\n') + + # First build adds published time + result = run_start.invoke(build) + assert result.exit_code == 0 + # Second build adds updated + result2 = run_start.invoke(build) + assert result2.exit_code == 0 + with (Path('posts') / 'example.md').open('r') as post_file: + a_lines = post_file.readlines() count = 0 for a_line in a_lines: if 'updated' in a_line: @@ -397,17 +361,14 @@ def test_build_updated_is_added_once() -> None: assert count == 1 -def test_build_without_published() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - remove_fields_from_example_post(('published', 'updated')) +def test_build_without_published(run_start: CliRunner) -> None: + remove_fields_from_example_post(('published', 'updated')) - # First build adds published time - result = runner.invoke(build) - assert result.exit_code == 0 - with (Path('posts') / 'example.md').open('r') as post_file: - a_lines = post_file.readlines() + # First build adds published time + result = run_start.invoke(build) + assert result.exit_code == 0 + with (Path('posts') / 'example.md').open('r') as post_file: + a_lines = post_file.readlines() count = 0 for a_line in a_lines: if 'published' in a_line: @@ -416,20 +377,17 @@ def test_build_without_published() -> None: assert count == 1 -def test_build_with_post_in_each_month() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - post_path = Path('posts') / 'example.md' - with post_path.open('r') as post_file: - lines = post_file.readlines() - for month in range(1, 13): - with post_path.open('w') as post_file: - for line in lines: - if 'published' in line: - post_file.write(f'published: 2014-{month:02}-03\n') - else: - post_file.write(line) - - result = runner.invoke(build) - assert result.exit_code == 0 +def test_build_with_post_in_each_month(run_start: CliRunner) -> None: + post_path = Path('posts') / 'example.md' + with post_path.open('r') as post_file: + lines = post_file.readlines() + for month in range(1, 13): + with post_path.open('w') as post_file: + for line in lines: + if 'published' in line: + post_file.write(f'published: 2014-{month:02}-03\n') + else: + post_file.write(line) + + result = run_start.invoke(build) + assert result.exit_code == 0 diff --git a/tests/test_preview.py b/tests/test_preview.py index 6ec643d..5e5f3fc 100644 --- a/tests/test_preview.py +++ b/tests/test_preview.py @@ -1,12 +1,9 @@ from click.testing import CliRunner -from htmd.cli import preview, start +from htmd.cli import preview -def test_preview() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - result = runner.invoke(start) - result = runner.invoke(preview) +def test_preview(run_start: CliRunner) -> None: + result = run_start.invoke(preview) # Why is this 5? expected_exit_code = 5 assert result.exit_code == expected_exit_code diff --git a/tests/test_templates.py b/tests/test_templates.py index ab9ef52..c84e6af 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -1,8 +1,8 @@ from click.testing import CliRunner -from htmd.cli import start, templates +from htmd.cli import templates -def test_templates() -> None: +def test_templates(run_start: CliRunner) -> None: expected_output = ( 'templates/404.html was created.\n' 'templates/_layout.html already exists and was not created.\n' @@ -17,10 +17,7 @@ def test_templates() -> None: 'templates/tag.html was created.\n' 'templates/year.html was created.\n' ) - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - result = runner.invoke(templates) + result = run_start.invoke(templates) assert result.exit_code == 0 assert result.output == expected_output diff --git a/tests/test_verify.py b/tests/test_verify.py index 81c0de7..5c581cc 100644 --- a/tests/test_verify.py +++ b/tests/test_verify.py @@ -1,58 +1,43 @@ from pathlib import Path from click.testing import CliRunner -from htmd.cli import start, verify +from htmd.cli import verify from utils import remove_fields_from_example_post -def test_verify() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - result = runner.invoke(verify) +def test_verify(run_start: CliRunner) -> None: + result = run_start.invoke(verify) assert result.exit_code == 0 expected_output = 'All posts are correctly formatted.\n' assert result.output == expected_output -def test_verify_author_missing() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) +def test_verify_author_missing(run_start: CliRunner) -> None: + # Remove author from example post + remove_fields_from_example_post(('author',)) - # Remove author from example post - remove_fields_from_example_post(('author',)) - - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 1 expected_output = 'Post "example" does not have field author.\n' assert result.output == expected_output -def test_verify_title_missing() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - # Remove title from example post - remove_fields_from_example_post(('title',)) +def test_verify_title_missing(run_start: CliRunner) -> None: + # Remove title from example post + remove_fields_from_example_post(('title',)) - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 1 expected_output = 'Post "example" does not have field title.\n' assert result.output == expected_output -def test_verify_published_missing() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - # Remove published from example post - remove_fields_from_example_post(('published',)) +def test_verify_published_missing(run_start: CliRunner) -> None: + # Remove published from example post + remove_fields_from_example_post(('published',)) - result = runner.invoke(verify) + result = run_start.invoke(verify) # verify doesn't check for published # since it will be added on build. expected_output = 'All posts are correctly formatted.\n' @@ -60,21 +45,17 @@ def test_verify_published_missing() -> None: assert result.exit_code == 0 -def test_verify_published_invalid_year() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) +def test_verify_published_invalid_year(run_start: CliRunner) -> None: + with (Path('posts') / 'example.md').open('r') as post: + lines = post.readlines() + with (Path('posts') / 'example.md').open('w') as post: + for line in lines: + if 'published' in line: + post.write('published: 14-10-30\n') + else: + post.write(line) - with (Path('posts') / 'example.md').open('r') as post: - lines = post.readlines() - with (Path('posts') / 'example.md').open('w') as post: - for line in lines: - if 'published' in line: - post.write('published: 14-10-30\n') - else: - post.write(line) - - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 1 expected_output = ( 'Published date 14-10-30 for example' @@ -83,21 +64,17 @@ def test_verify_published_invalid_year() -> None: assert result.output == expected_output -def test_verify_published_invalid_month() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - with (Path('posts') / 'example.md').open('r') as post: - lines = post.readlines() - with (Path('posts') / 'example.md').open('w') as post: - for line in lines: - if 'published' in line: - post.write('published: 2014-1-30\n') - else: - post.write(line) +def test_verify_published_invalid_month(run_start: CliRunner) -> None: + with (Path('posts') / 'example.md').open('r') as post: + lines = post.readlines() + with (Path('posts') / 'example.md').open('w') as post: + for line in lines: + if 'published' in line: + post.write('published: 2014-1-30\n') + else: + post.write(line) - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 1 expected_output = ( 'Published date 2014-1-30 for example' @@ -106,21 +83,17 @@ def test_verify_published_invalid_month() -> None: assert result.output == expected_output -def test_verify_published_invalid_day() -> None: - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) +def test_verify_published_invalid_day(run_start: CliRunner) -> None: + with (Path('posts') / 'example.md').open('r') as post: + lines = post.readlines() + with (Path('posts') / 'example.md').open('w') as post: + for line in lines: + if 'published' in line: + post.write('published: 2014-01-3\n') + else: + post.write(line) - with (Path('posts') / 'example.md').open('r') as post: - lines = post.readlines() - with (Path('posts') / 'example.md').open('w') as post: - for line in lines: - if 'published' in line: - post.write('published: 2014-01-3\n') - else: - post.write(line) - - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 1 expected_output = ( 'Published date 2014-01-3 for example' @@ -129,64 +102,52 @@ def test_verify_published_invalid_day() -> None: assert result.output == expected_output -def test_verify_site_name_empty() -> None: +def test_verify_site_name_empty(run_start: CliRunner) -> None: expected_output = ( 'All posts are correctly formatted.\n' '[site] name is not set in config.toml.\n' ) - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - with Path('config.toml').open('r') as post: - lines = post.readlines() - with Path('config.toml').open('w') as post: - seen = False - for line in lines: - if 'name' in line and not seen: - # [site] name is the first name - seen = True - post.write("name = ''\n") - else: - post.write(line) - - result = runner.invoke(verify) + + with Path('config.toml').open('r') as post: + lines = post.readlines() + with Path('config.toml').open('w') as post: + seen = False + for line in lines: + if 'name' in line and not seen: + # [site] name is the first name + seen = True + post.write("name = ''\n") + else: + post.write(line) + + result = run_start.invoke(verify) # [site] name isn't required assert result.exit_code == 0 assert result.output == expected_output -def test_verify_site_name_missing() -> None: +def test_verify_site_name_missing(run_start: CliRunner) -> None: expected_output = ( 'All posts are correctly formatted.\n' '[site] name is not set in config.toml.\n' ) - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - with Path('config.toml').open('r') as post: - lines = post.readlines() - with Path('config.toml').open('w') as post: - for line in lines: - if 'name' not in line: - post.write(line) + with Path('config.toml').open('r') as post: + lines = post.readlines() + with Path('config.toml').open('w') as post: + for line in lines: + if 'name' not in line: + post.write(line) - result = runner.invoke(verify) + result = run_start.invoke(verify) assert result.exit_code == 0 assert result.output == expected_output -def test_verify_no_config() -> None: +def test_verify_no_config(run_start: CliRunner) -> None: expected_output = 'Can not find config.toml\n' - runner = CliRunner() - with runner.isolated_filesystem(): - runner.invoke(start) - - Path('config.toml').unlink() - - result = runner.invoke(verify) + Path('config.toml').unlink() + result = run_start.invoke(verify) assert result.exit_code == 1 assert result.output == expected_output diff --git a/tests/utils.py b/tests/utils.py index 486b318..c4d9c80 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,7 @@ from pathlib import Path -def remove_fields_from_example_post(field_names: (str,)) -> None: +def remove_fields_from_example_post(field_names: tuple[str, ...]) -> None: with (Path('posts') / 'example.md').open('r') as post: lines = post.readlines() with (Path('posts') / 'example.md').open('w') as post: