diff --git a/.github/workflows/e2e.yml b/.github/workflows/tests.yml similarity index 57% rename from .github/workflows/e2e.yml rename to .github/workflows/tests.yml index 7263b0a..ba6fa4c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: E2E tests +name: Tests on: push: @@ -17,14 +17,15 @@ jobs: fail-fast: false matrix: os: - - ubuntu-18.04 - - ubuntu-20.04 + - ubuntu-latest + - macos-latest python-version: - '3.7' - '3.8' - '3.9' + - '3.10' - name: E2E tests (Python ${{ matrix.python-version }} on ${{ matrix.os }}) + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - uses: actions/checkout@v1 @@ -35,20 +36,30 @@ jobs: - name: Prepare tests run: | - sudo apt update - sudo apt install ruby sudo gem install ronn - pip install -U setuptools pip requests wheel Babel + pip install -U pip pipenv + pipenv sync --dev + make manpage - name: E2E tests run: | - export ENVIRONMENT="CI" - bash .scripts/tests-e2e.sh + make tests + + - name: Install TeXLive (Ubuntu) + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + sudo apt-get install -y texlive texlive-latex-extra + + - name: E2E tests + env: + TEXLIVE_INSTALLED: 1 + run: | + make tests - name: manpage (section 1) run: | - man -P $(which cat) kosmorro + man -P $(which cat) manpage/kosmorro.1 - name: manpage (section 7) run: | - man -P $(which cat) 7 kosmorro + man -P $(which cat) manpage/kosmorro.7 diff --git a/.scripts/tests-e2e.sh b/.scripts/tests-e2e.sh deleted file mode 100755 index 6a48397..0000000 --- a/.scripts/tests-e2e.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/bash - -VERSION=$(grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' _kosmorro/__version__.py) -PYTHON_BIN=$(command -v python) -PIP_BIN=$(command -v pip) - -if python3 --version > /dev/null; then - PYTHON_BIN=$(command -v python3) - PIP_BIN=$(command -v pip3) -fi - -failures='' - -function fail() { - failures="$failures\n\n - $1\n\n$2" -} - -function run() { - eval "$1" &> /tmp/output.txt - return $? -} - -function canRun() { - if [[ "$1" != "" && "$1" != "$ENVIRONMENT" ]]; then - return 1 - fi - - return 0 -} - -# Asserts that command $1 has finished with sucess -# $1: the command to run -function assertSuccess() { - if ! canRun "$2"; then - echo -n 'I' - return - fi - - run "$1" - returned=$? - - if [ $returned -ne 0 ]; then - fail "Failed asserting that command '$1' finishes with success, returned status $returned." "$(cat /tmp/output.txt)" - echo -n 'F' - return - fi - - echo -n '.' -} - -# Asserts that command $1 has finished with sucess -# $1: the command to run -function assertFailure() { - if ! canRun "$2"; then - echo -n 'I' - return - fi - - run "$1" - returned=$? - - if [ $returned -eq 0 ]; then - fail "Failed asserting that command '$1' finishes with failure." "$(cat /tmp/output.txt)" - echo -n 'F' - return - fi - - echo -n '.' -} - -mkdir -p $HOME/kosmorro/export - -echo -echo "==== RUNNING E2E TESTS ====" -echo - -# Create the package and install it -assertSuccess "make build" -assertSuccess "$PIP_BIN install dist/kosmorro-$VERSION.tar.gz" "CI" - -KOSMORRO_COMMAND="kosmorro --debug" - -assertSuccess "$KOSMORRO_COMMAND" -assertSuccess "$KOSMORRO_COMMAND -h" -assertSuccess "$KOSMORRO_COMMAND -d 2020-01-27" -assertFailure "$KOSMORRO_COMMAND -d yolo-yo-lo" -assertFailure "$KOSMORRO_COMMAND -d 2020-13-32" -assertFailure "$KOSMORRO_COMMAND --date=1789-05-05" -assertFailure "$KOSMORRO_COMMAND --date=3000-01-01" -assertSuccess "$KOSMORRO_COMMAND --date='+3y 5m3d'" -assertSuccess "$KOSMORRO_COMMAND --date='-1y3d'" -assertFailure "$KOSMORRO_COMMAND --date='+3d4m" -assertFailure "$KOSMORRO_COMMAND -date='3y'" -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624" -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27" -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --timezone=1" -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --timezone=-1" -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --format=json" -assertFailure "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --format=pdf" - -assertSuccess "$KOSMORRO_COMMAND -d 2020-01-27 --format=json" - -# Environment variables -assertSuccess "LATITUDE=50.5876 LONGITUDE=3.0624 TIMEZONE=1 kosmorro -d 2020-01-27" -assertSuccess "LATITUDE=50.5876 LONGITUDE=3.0624 TIMEZONE=-1 kosmorro -d 2020-01-27" - -# Missing dependencies, should fail -assertFailure "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --format=pdf -o $HOME/kosmorro/export/document.pdf" -assertFailure "ls $HOME/kosmorro/export/document.pdf" - -assertSuccess "sudo apt-get install -y texlive texlive-latex-extra" "CI" - -# Dependencies installed, should not fail -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --format=pdf -o $HOME/kosmorro/export/document.pdf" -assertSuccess "ls $HOME/kosmorro/export/document.pdf" - -assertSuccess "$KOSMORRO_COMMAND --latitude=50.5876 --longitude=3.0624 -d 2020-01-27 --format=pdf -o $HOME/kosmorro/export/document-no-graph.pdf --no-graph" -assertSuccess "ls $HOME/kosmorro/export/document-no-graph.pdf" - -# man page -assertSuccess "man --pager=cat kosmorro" - -if [ "$failures" != "" ]; then - echo -e "\n$failures" - exit 2 -fi - -echo -e "\n\n==== TESTS RAN SUCCESSFULLY 👍 ====" diff --git a/Makefile b/Makefile index 45dce8e..0b3792c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,14 @@ black: - pipenv run black kosmorro _kosmorro setup.py + pipenv run black kosmorro _kosmorro tests setup.py + +.PHONY: tests +tests: + @if [ "$${TEXLIVE_INSTALLED}" == "" ]; then \ + echo "If you are running the tests locally and TeXLive is installed on your machine, you will need to set the TEXLIVE_INSTALLED environment variable."; \ + echo; \ + fi + + pipenv run python3 -m pytest tests/*.py .PHONY: build build: manpage diff --git a/Pipfile b/Pipfile index ae55f16..0d73dcc 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,8 @@ verify_ssl = true [dev-packages] babel = "*" black = "*" +pytest = "*" +aurornis = "*" [packages] tabulate = "*" diff --git a/Pipfile.lock b/Pipfile.lock index d510eb2..7553526 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c1f6551ee33e3015fa1aaa679059da0744c447948707b7e517cce926f336f6f9" + "sha256": "3ff7290b32da63ca9585dbe947830ae1d1e4692f0ca9a0faeaa3601d7f9c4b8b" }, "pipfile-spec": 6, "requires": { @@ -59,7 +59,6 @@ "sha256:badca914580eb46385e7f7e4e426fea6de0a37b9e06bec252e481ae7ec287082", "sha256:d76a26c5118c4d96e264acc9e3242d72e1a2b92e739807b3b69d8d47684b6677" ], - "markers": "python_version >= '3.8'", "version": "==1.22.2" }, "python-dateutil": { @@ -109,7 +108,6 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "skyfield": { @@ -123,7 +121,6 @@ "sha256:128d407e43a04be66c44b03914f9147b5e65b96078db776e6a4f5538ab0b74bf", "sha256:bd81bf9032d4833a766f4127e868d62674083ca2ccaea07e6d025e132c9c574e" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", "version": "==4.0.0" }, "tabulate": { @@ -143,6 +140,21 @@ } }, "develop": { + "attrs": { + "hashes": [ + "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", + "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" + ], + "version": "==21.4.0" + }, + "aurornis": { + "hashes": [ + "sha256:660b57e9d1701d88fb7cc4af3118c927e9e001d2ab39cb145695eb8470f4642a", + "sha256:bc68845be5cdf2d69d26c677214f7435365967b4a65dc3772ab05353b2136d95" + ], + "index": "pypi", + "version": "==1.2.0" + }, "babel": { "hashes": [ "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9", @@ -185,9 +197,15 @@ "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" ], - "markers": "python_version >= '3.6'", "version": "==8.0.4" }, + "iniconfig": { + "hashes": [ + "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", + "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + ], + "version": "==1.1.1" + }, "mypy-extensions": { "hashes": [ "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", @@ -195,6 +213,13 @@ ], "version": "==0.4.3" }, + "packaging": { + "hashes": [ + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" + ], + "version": "==21.3" + }, "pathspec": { "hashes": [ "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", @@ -207,9 +232,37 @@ "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d", "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227" ], - "markers": "python_version >= '3.7'", "version": "==2.5.1" }, + "pluggy": { + "hashes": [ + "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", + "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" + ], + "version": "==1.0.0" + }, + "py": { + "hashes": [ + "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", + "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" + ], + "version": "==1.11.0" + }, + "pyparsing": { + "hashes": [ + "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea", + "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484" + ], + "version": "==3.0.7" + }, + "pytest": { + "hashes": [ + "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db", + "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171" + ], + "index": "pypi", + "version": "==7.0.1" + }, "pytz": { "hashes": [ "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", @@ -222,8 +275,15 @@ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" ], - "markers": "python_version >= '3.7'", "version": "==2.0.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42", + "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" + ], + "markers": "python_version < '3.10'", + "version": "==4.1.1" } } } diff --git a/_kosmorro/assets/pdf/template.tex b/_kosmorro/assets/pdf/template.tex index ea2a13a..fef839c 100644 --- a/_kosmorro/assets/pdf/template.tex +++ b/_kosmorro/assets/pdf/template.tex @@ -6,6 +6,7 @@ \usepackage{graphicx} \usepackage{hyperref} \usepackage{kosmorro} +\usepackage{lmodern} \newcommand{\currentmoonphasetitle}{+++CURRENT-MOON-PHASE-TITLE+++} \newcommand{\ephemeridesobjecttitle}{+++EPHEMERIDES-OBJECT+++} diff --git a/_kosmorro/locales/messages.pot b/_kosmorro/locales/messages.pot index ce59b19..75ee03a 100644 --- a/_kosmorro/locales/messages.pot +++ b/_kosmorro/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-02-04 13:30+0100\n" +"POT-Creation-Date: 2022-02-16 13:58+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -116,98 +116,98 @@ msgstr "" msgid "The date must be between {minimum_date} and {maximum_date}" msgstr "" -#: _kosmorro/main.py:60 +#: _kosmorro/main.py:62 msgid "" "Save the planet and paper!\n" "Consider printing your PDF document only if really necessary, and use the" " other side of the sheet." msgstr "" -#: _kosmorro/main.py:69 +#: _kosmorro/main.py:71 msgid "" "PDF output will not contain the ephemerides, because you didn't provide " "the observation coordinates." msgstr "" -#: _kosmorro/main.py:114 +#: _kosmorro/main.py:116 msgid "The file could not be saved in \"{path}\": {error}" msgstr "" -#: _kosmorro/main.py:128 +#: _kosmorro/main.py:130 msgid "Please provide a file path to export in this format (--output)." msgstr "" -#: _kosmorro/main.py:161 +#: _kosmorro/main.py:163 msgid "Moon phase can only be displayed between {min_date} and {max_date}" msgstr "" -#: _kosmorro/main.py:200 +#: _kosmorro/main.py:202 msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}" msgstr "" -#: _kosmorro/main.py:213 +#: _kosmorro/main.py:215 msgid "" "Compute the ephemerides and the events for a given date and a given " "position on Earth." msgstr "" -#: _kosmorro/main.py:216 +#: _kosmorro/main.py:218 msgid "" -"By default, only the events will be computed for today ({date}).\n" +"By default, only the events will be computed for today.\n" "To compute also the ephemerides, latitude and longitude arguments are " "needed." msgstr "" -#: _kosmorro/main.py:230 +#: _kosmorro/main.py:231 msgid "Show the program version" msgstr "" -#: _kosmorro/main.py:238 +#: _kosmorro/main.py:239 msgid "The format to output the information to" msgstr "" -#: _kosmorro/main.py:245 +#: _kosmorro/main.py:246 msgid "" "The observer's latitude on Earth. Can also be set in the " "KOSMORRO_LATITUDE environment variable." msgstr "" -#: _kosmorro/main.py:255 +#: _kosmorro/main.py:256 msgid "" "The observer's longitude on Earth. Can also be set in the " "KOSMORRO_LONGITUDE environment variable." msgstr "" -#: _kosmorro/main.py:265 +#: _kosmorro/main.py:266 msgid "" "The date for which the ephemerides must be calculated. Can be in the " "YYYY-MM-DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M," -" and D numbers). Defaults to today ({default_date})." +" and D numbers). Defaults to current date." msgstr "" -#: _kosmorro/main.py:276 +#: _kosmorro/main.py:277 msgid "" "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). " "Can also be set in the KOSMORRO_TIMEZONE environment variable." msgstr "" -#: _kosmorro/main.py:285 +#: _kosmorro/main.py:286 msgid "Disable the colors in the console." msgstr "" -#: _kosmorro/main.py:292 +#: _kosmorro/main.py:293 msgid "" "A file to export the output to. If not given, the standard output is " "used. This argument is needed for PDF format." msgstr "" -#: _kosmorro/main.py:301 +#: _kosmorro/main.py:302 msgid "" "Do not generate a graph to represent the rise and set times in the PDF " "format." msgstr "" -#: _kosmorro/main.py:309 +#: _kosmorro/main.py:310 msgid "Show debugging messages" msgstr "" diff --git a/_kosmorro/main.py b/_kosmorro/main.py index 2235478..6b36682 100644 --- a/_kosmorro/main.py +++ b/_kosmorro/main.py @@ -23,10 +23,10 @@ from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase from kosmorrolib.__version__ import __version__ as kosmorrolib_version from kosmorrolib.exceptions import OutOfRangeDateError from datetime import date -from termcolor import colored from . import dumper, environment, debug from .date import parse_date +from .utils import colored, set_colors_activated from .__version__ import __version__ as kosmorro_version from .exceptions import UnavailableFeatureError, OutOfRangeDateError as DateRangeError from _kosmorro.i18n.utils import _, SHORT_DATE_FORMAT @@ -39,6 +39,8 @@ def main(): debug.show_debug_messages = args.show_debug_messages output_format = args.format + set_colors_activated(args.colors) + if args.special_action is not None: return 0 if args.special_action() else 1 @@ -214,9 +216,8 @@ def get_args(output_formats: [str]): "Compute the ephemerides and the events for a given date and a given position on Earth." ), epilog=_( - "By default, only the events will be computed for today ({date}).\n" - "To compute also the ephemerides, latitude and longitude arguments" - " are needed." + "By default, only the events will be computed for today.\n" + "To compute also the ephemerides, latitude and longitude arguments are needed." ).format(date=today.strftime(dumper.FULL_DATE_FORMAT)), ) @@ -265,7 +266,7 @@ def get_args(output_formats: [str]): help=_( "The date for which the ephemerides must be calculated. Can be in the YYYY-MM-DD format " 'or an interval in the "[+-]YyMmDd" format (with Y, M, and D numbers). ' - "Defaults to today ({default_date})." + "Defaults to current date." ).format(default_date=today.strftime("%Y-%m-%d")), ) parser.add_argument( diff --git a/_kosmorro/utils.py b/_kosmorro/utils.py new file mode 100644 index 0000000..4ee8da8 --- /dev/null +++ b/_kosmorro/utils.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +from termcolor import colored as do_color + + +global _COLORS_ACTIVATED + + +def set_colors_activated(activated: bool): + global _COLORS_ACTIVATED + _COLORS_ACTIVATED = activated + + +def colored(text, color=None, on_color=None, attrs=None): + """Decorator to use colors only when they are activated""" + if not _COLORS_ACTIVATED: + return text + + return do_color(text, color, on_color, attrs) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/dates.py b/tests/dates.py new file mode 100644 index 0000000..fc7ccaf --- /dev/null +++ b/tests/dates.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +from .utils import execute, KOSMORRO + + +def test_with_date(): + for arg in [["-d", "2020-01-27"], ["--date", "2020-01-27"], ["-d2020-01-27"]]: + result = execute(KOSMORRO + arg) + assert result.is_successful() + + assert ( + result.stdout + == """Monday January 27, 2020 + +Moon phase: New Moon +First Quarter on Sunday February 02, 2020 at 01:41 + +Expected events: +20:00 Venus and Neptune are in conjunction + +Note: All the hours are given in UTC. +""" + ) + + +def test_with_incorrect_date_values(): + value = "yolo-yo-lo" + for arg in [["-d", value], ["--date", value], [f"-d{value}"]]: + result = execute(KOSMORRO + arg) + assert not result.is_successful() + assert ( + result.stdout + == f"The date {value} does not match the required YYYY-MM-DD format or the offset format.\n" + ) + + value = "2020-13-32" + for arg in [["-d", value], ["--date", value], [f"-d{value}"]]: + result = execute(KOSMORRO + arg) + assert not result.is_successful() + assert ( + result.stdout == f"The date {value} is not valid: month must be in 1..12\n" + ) + + +def test_with_out_of_range_dates(): + for arg in [["-d", "1789-05-05"], ["-d", "3000-01-01"]]: + result = execute(KOSMORRO + arg) + assert not result.is_successful() + assert ( + result.stdout + == "Moon phase can only be displayed between Aug 09, 1899 and Sep 26, 2053\n" + ) diff --git a/tests/general.py b/tests/general.py new file mode 100644 index 0000000..d2cf96f --- /dev/null +++ b/tests/general.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +from sys import version_info +from .utils import ( + execute, + KOSMORRO, + CURRENT_MOON_PHASE_PATTERN, + NEXT_MOON_PHASE_PATTERN, +) +from datetime import date + + +def test_run_without_argument(): + result = execute(KOSMORRO) + assert result.is_successful() + + stdout = result.stdout.split("\n") + + # It always starts with the current date, an empty line and the current and next Moon date: + assert stdout[0] == date.today().strftime("%A %B %d, %Y") + assert stdout[1] == "" + assert CURRENT_MOON_PHASE_PATTERN.match(stdout[2]) + assert NEXT_MOON_PHASE_PATTERN.match(stdout[3]) + + # It always finishes with an empty line, a note about UTC timezone and an empty line: + assert stdout[-3] == "" + assert stdout[-2] == "Note: All the hours are given in UTC." + assert stdout[-1] == "" + + +def test_help_message(): + python_version = (version_info.major, version_info.minor) + + for arg in ["--help", "-h"]: + result = execute(KOSMORRO + [arg]) + assert result.is_successful() + + # Options header has changed from "optional arguments" to "options" in Python 3.10. + options_header = ( + "options" if python_version == (3, 10) else "optional arguments" + ) + + assert ( + result.stdout + == """usage: kosmorro [-h] [--version] [--format {text,json,pdf}] + [--latitude LATITUDE] [--longitude LONGITUDE] [--date DATE] + [--timezone TIMEZONE] [--no-colors] [--output OUTPUT] + [--no-graph] [--debug] + +Compute the ephemerides and the events for a given date and a given position +on Earth. + +%s: + -h, --help show this help message and exit + --version, -v Show the program version + --format {text,json,pdf}, -f {text,json,pdf} + The format to output the information to + --latitude LATITUDE, -lat LATITUDE + The observer's latitude on Earth. Can also be set in + the KOSMORRO_LATITUDE environment variable. + --longitude LONGITUDE, -lon LONGITUDE + The observer's longitude on Earth. Can also be set in + the KOSMORRO_LONGITUDE environment variable. + --date DATE, -d DATE The date for which the ephemerides must be calculated. + Can be in the YYYY-MM-DD format or an interval in the + "[+-]YyMmDd" format (with Y, M, and D numbers). + Defaults to current date. + --timezone TIMEZONE, -t TIMEZONE + The timezone to display the hours in (e.g. 2 for UTC+2 + or -3 for UTC-3). Can also be set in the + KOSMORRO_TIMEZONE environment variable. + --no-colors Disable the colors in the console. + --output OUTPUT, -o OUTPUT + A file to export the output to. If not given, the + standard output is used. This argument is needed for + PDF format. + --no-graph Do not generate a graph to represent the rise and set + times in the PDF format. + --debug Show debugging messages + +By default, only the events will be computed for today. To compute also the +ephemerides, latitude and longitude arguments are needed. +""" + % options_header + ) diff --git a/tests/output.py b/tests/output.py new file mode 100644 index 0000000..d466f26 --- /dev/null +++ b/tests/output.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 + +from .utils import ( + execute, + KOSMORRO, +) +import tempfile +from os import path, environ +from sys import platform + + +def test_json_output(): + result = execute( + KOSMORRO + + ["--latitude=50.5876", "--longitude=3.0624", "-d2020-01-27", "--format=json"] + ) + assert result.is_successful() + assert ( + result.stdout + == """{ + "ephemerides": [ + { + "object": { + "identifier": "SUN", + "type": "STAR", + "radius": 696342 + }, + "rise_time": "2020-01-27T07:31:00", + "culmination_time": "2020-01-27T12:01:00", + "set_time": "2020-01-27T16:30:00" + }, + { + "object": { + "identifier": "MOON", + "type": "SATELLITE", + "radius": 1737.4 + }, + "rise_time": "2020-01-27T09:06:00", + "culmination_time": "2020-01-27T14:09:00", + "set_time": "2020-01-27T19:13:00" + }, + { + "object": { + "identifier": "MERCURY", + "type": "PLANET", + "radius": 2439.7 + }, + "rise_time": "2020-01-27T08:10:00", + "culmination_time": "2020-01-27T12:49:00", + "set_time": "2020-01-27T17:28:00" + }, + { + "object": { + "identifier": "VENUS", + "type": "PLANET", + "radius": 6051.8 + }, + "rise_time": "2020-01-27T09:01:00", + "culmination_time": "2020-01-27T14:35:00", + "set_time": "2020-01-27T20:10:00" + }, + { + "object": { + "identifier": "MARS", + "type": "PLANET", + "radius": 3396.2 + }, + "rise_time": "2020-01-27T04:19:00", + "culmination_time": "2020-01-27T08:23:00", + "set_time": "2020-01-27T12:28:00" + }, + { + "object": { + "identifier": "JUPITER", + "type": "PLANET", + "radius": 71492 + }, + "rise_time": "2020-01-27T06:15:00", + "culmination_time": "2020-01-27T10:18:00", + "set_time": "2020-01-27T14:21:00" + }, + { + "object": { + "identifier": "SATURN", + "type": "PLANET", + "radius": 60268 + }, + "rise_time": "2020-01-27T06:56:00", + "culmination_time": "2020-01-27T11:09:00", + "set_time": "2020-01-27T15:22:00" + }, + { + "object": { + "identifier": "URANUS", + "type": "PLANET", + "radius": 25559 + }, + "rise_time": "2020-01-27T10:21:00", + "culmination_time": "2020-01-27T17:25:00", + "set_time": "2020-01-27T00:33:00" + }, + { + "object": { + "identifier": "NEPTUNE", + "type": "PLANET", + "radius": 24764 + }, + "rise_time": "2020-01-27T09:01:00", + "culmination_time": "2020-01-27T14:36:00", + "set_time": "2020-01-27T20:10:00" + }, + { + "object": { + "identifier": "PLUTO", + "type": "PLANET", + "radius": 1185 + }, + "rise_time": "2020-01-27T06:57:00", + "culmination_time": "2020-01-27T11:04:00", + "set_time": "2020-01-27T15:11:00" + } + ], + "moon_phase": { + "phase": "NEW_MOON", + "time": "2020-01-24T21:41:59.705921+00:00", + "next": { + "phase": "FIRST_QUARTER", + "time": "2020-02-02T01:41:40.282275+00:00" + } + }, + "events": [ + { + "objects": [ + { + "identifier": "VENUS", + "type": "PLANET", + "radius": 6051.8 + }, + { + "identifier": "NEPTUNE", + "type": "PLANET", + "radius": 24764 + } + ], + "EventType": "CONJUNCTION", + "starts_at": "2020-01-27T20:00:23.242750+00:00", + "ends_at": null, + "details": null + } + ] +} +""" + ) + + +def test_pdf_output(): + if platform != "linux": + # Consider it works everywhere if it does at least on Linux + return + + tmp_dir = tempfile.mkdtemp() + result = execute( + KOSMORRO + + [ + "--latitude=50.5876", + "--longitude=3.0624", + "-d2020-01-27", + "--format=pdf", + f"--output={tmp_dir}/document.pdf", + ] + ) + + if environ.get("TEXLIVE_INSTALLED") is None: + assert not result.is_successful() + assert ( + result.stdout + == """Save the planet and paper! +Consider printing your PDF document only if really necessary, and use the other side of the sheet. +Building PDF was not possible, because some dependencies are not installed. +Please look at the documentation at https://kosmorro.space/cli/generate-pdf/ for more information. +""" + ) + + return + + assert result.is_successful() + assert ( + result.stdout + == """Save the planet and paper! +Consider printing your PDF document only if really necessary, and use the other side of the sheet. +""" + "" + ) + + assert path.exists(f"{tmp_dir}/document.pdf") diff --git a/tests/position.py b/tests/position.py new file mode 100644 index 0000000..918f87b --- /dev/null +++ b/tests/position.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +from .utils import ( + execute, + KOSMORRO, +) + + +def check_command_return(result): + assert result.is_successful() + assert ( + result.stdout + == """Monday January 27, 2020 + +Object Rise time Culmination time Set time +-------- ----------- ------------------ ---------- +Sun 07:31 12:01 16:30 +Moon 09:06 14:09 19:13 +Mercury 08:10 12:49 17:28 +Venus 09:01 14:35 20:10 +Mars 04:19 08:23 12:28 +Jupiter 06:15 10:18 14:21 +Saturn 06:56 11:09 15:22 +Uranus 10:21 17:25 00:33 +Neptune 09:01 14:36 20:10 +Pluto 06:57 11:04 15:11 + +Moon phase: New Moon +First Quarter on Sunday February 02, 2020 at 01:41 + +Expected events: +20:00 Venus and Neptune are in conjunction + +Note: All the hours are given in UTC. +""" + ) + + +def test_with_position(): + result = execute( + KOSMORRO + ["--latitude=50.5876", "--longitude=3.0624", "-d2020-01-27"] + ) + check_command_return(result) + + +def test_with_position_env_vars(): + check_command_return( + execute( + KOSMORRO + ["-d2020-01-27"], + environment={ + "KOSMORRO_LATITUDE": "50.5876", + "KOSMORRO_LONGITUDE": "3.0624", + }, + ) + ) diff --git a/tests/timezone.py b/tests/timezone.py new file mode 100644 index 0000000..e7e8c80 --- /dev/null +++ b/tests/timezone.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +from .utils import ( + execute, + KOSMORRO, +) + + +def check_command_return_t_plus_one(result): + assert result.is_successful() + assert ( + result.stdout + == """Monday January 27, 2020 + +Moon phase: New Moon +First Quarter on Sunday February 02, 2020 at 02:41 + +Expected events: +21:00 Venus and Neptune are in conjunction + +Note: All the hours are given in the UTC+1 timezone. +""" + ) + + +def check_command_return_t_minus_one(result): + assert result.is_successful() + assert ( + result.stdout + == """Monday January 27, 2020 + +Moon phase: New Moon +First Quarter on Sunday February 02, 2020 at 00:41 + +Expected events: +19:00 Venus and Neptune are in conjunction + +Note: All the hours are given in the UTC-1 timezone. +""" + ) + + +def test_timezone(): + check_command_return_t_plus_one( + execute(KOSMORRO + ["--timezone=1", "-d2020-01-27"]) + ) + check_command_return_t_minus_one( + execute(KOSMORRO + ["--timezone=-1", "-d2020-01-27"]) + ) + + +def test_timezone_with_env_var(): + check_command_return_t_plus_one( + execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "1"}) + ) + check_command_return_t_minus_one( + execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "-1"}) + ) + + # If both environment variable and argument are set, use argument: + + check_command_return_t_plus_one( + execute( + KOSMORRO + ["--timezone=1", "-d2020-01-27"], + environment={"KOSMORRO_TIMEZONE": "-1"}, + ) + ) + check_command_return_t_minus_one( + execute( + KOSMORRO + ["--timezone=-1", "-d2020-01-27"], + environment={"KOSMORRO_TIMEZONE": "1"}, + ) + ) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..38373d8 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import aurornis +import re + +from os import environ +from typing import Union + +DEFAULT_ENVIRONMENT = {"PATH": environ["PATH"]} +KOSMORRO = ["./kosmorro", "--no-color"] + +CURRENT_MOON_PHASE_PATTERN = re.compile( + r"^Moon phase: (" + r"(New Moon)|(Waxing Crescent)|" + r"(First Quarter)|(Waxing Gibbous)|" + r"(Full Moon)|(Waning Gibbous)|" + r"(Last Quarter)|(Waning Crescent)" + r")$" +) + +NEXT_MOON_PHASE_PATTERN = re.compile( + r"^((New Moon)|(Waxing Crescent)|" + r"(First Quarter)|(Waxing Gibbous)|" + r"(Full Moon)|(Waning Gibbous)|" + r"(Last Quarter)|(Waning Crescent)" + r") " + r"on ((Monday)|(Tuesday)|(Wednesday)|(Thursday)|(Friday)|(Saturday)|(Sunday)) " + r"((January)|(February)|(March)|(April)|(May)|(June)|" + r"(July)|(August)|(September)|(October)|(November)|(December)) " + r"[0-9]{2}, [0-9]{4} at [0-9]{2}:[0-9]{2}$" +) + + +def execute( + command, environment: {str: Union[int, str]} = None +) -> aurornis.CommandResult: + if environment is None: + environment = DEFAULT_ENVIRONMENT + else: + for variable in DEFAULT_ENVIRONMENT: + environment[variable] = DEFAULT_ENVIRONMENT[variable] + + return aurornis.run(command, environment) + + +def assert_nb_lines(expected_nb: int, in_str: str): + """Check that the string has the specified number of lines and that the last one is empty.""" + lines = in_str.split("\n") + assert len(lines) == expected_nb + assert lines[len(lines) - 1] == ""