Changeset View
Changeset View
Standalone View
Standalone View
swh/deposit/tests/cli/test_client.py
| # Copyright (C) 2020 The Software Heritage developers | # Copyright (C) 2020 The Software Heritage developers | ||||
| # See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
| # License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
| # See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
| import ast | import ast | ||||
| from collections import OrderedDict | |||||
| import contextlib | import contextlib | ||||
| import json | import json | ||||
| import logging | import logging | ||||
| import os | import os | ||||
| from unittest.mock import MagicMock | from unittest.mock import MagicMock | ||||
| import pytest | import pytest | ||||
| import yaml | import yaml | ||||
| from swh.deposit.api.checks import check_metadata | |||||
| from swh.deposit.cli import deposit as cli | from swh.deposit.cli import deposit as cli | ||||
| from swh.deposit.cli.client import InputError, _client, _collection, _url, generate_slug | from swh.deposit.cli.client import ( | ||||
| InputError, | |||||
| _client, | |||||
| _collection, | |||||
| _url, | |||||
| generate_metadata, | |||||
| generate_slug, | |||||
| ) | |||||
| from swh.deposit.client import MaintenanceError, PublicApiDepositClient | from swh.deposit.client import MaintenanceError, PublicApiDepositClient | ||||
| from swh.deposit.parsers import parse_xml | from swh.deposit.parsers import parse_xml | ||||
| from ..conftest import TEST_USER | from ..conftest import TEST_USER | ||||
| @pytest.fixture | @pytest.fixture | ||||
| def deposit_config(): | def deposit_config(): | ||||
| ▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | down_for_maintenance_log_record = ( | ||||
| logging.ERROR, | logging.ERROR, | ||||
| "Database backend maintenance: Temporarily unavailable, try again later.", | "Database backend maintenance: Temporarily unavailable, try again later.", | ||||
| ) | ) | ||||
| assert down_for_maintenance_log_record in caplog.record_tuples | assert down_for_maintenance_log_record in caplog.record_tuples | ||||
| client_mock_api_down.service_document.assert_called_once_with() | client_mock_api_down.service_document.assert_called_once_with() | ||||
| def test_cli_client_generate_metadata_ok(slug): | |||||
| """Generated metadata is well formed and pass service side metadata checks | |||||
| """ | |||||
| actual_metadata_xml = generate_metadata( | |||||
| "deposit-client", "project-name", "external-id", authors=["some", "authors"] | |||||
| ) | |||||
| actual_metadata = dict(parse_xml(actual_metadata_xml)) | |||||
| assert actual_metadata["author"] == "deposit-client" | |||||
| assert actual_metadata["title"] == "project-name" | |||||
| assert actual_metadata["updated"] is not None | |||||
| assert actual_metadata["codemeta:name"] == "project-name" | |||||
| assert actual_metadata["codemeta:identifier"] == "external-id" | |||||
| assert actual_metadata["codemeta:author"] == [ | |||||
| OrderedDict([("codemeta:name", "some")]), | |||||
| OrderedDict([("codemeta:name", "authors")]), | |||||
| ] | |||||
ardumont: With this ^, we won't have that kind of unpleasant surprise any more. | |||||
| checks_ok, detail = check_metadata(actual_metadata) | |||||
| assert checks_ok is True | |||||
| assert detail is None | |||||
| def test_cli_single_minimal_deposit( | def test_cli_single_minimal_deposit( | ||||
| sample_archive, slug, patched_tmp_path, requests_mock_datadir, cli_runner | sample_archive, slug, patched_tmp_path, requests_mock_datadir, cli_runner | ||||
| ): | ): | ||||
| """ This ensure a single deposit upload through the cli is fine, cf. | """ This ensure a single deposit upload through the cli is fine, cf. | ||||
| https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#single-deposit | https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#single-deposit | ||||
| """ # noqa | """ # noqa | ||||
| metadata_path = os.path.join(patched_tmp_path, "metadata.xml") | metadata_path = os.path.join(patched_tmp_path, "metadata.xml") | ||||
| Show All 24 Lines | ): | ||||
| assert json.loads(result.output) == { | assert json.loads(result.output) == { | ||||
| "deposit_id": "615", | "deposit_id": "615", | ||||
| "deposit_status": "partial", | "deposit_status": "partial", | ||||
| "deposit_status_detail": None, | "deposit_status_detail": None, | ||||
| "deposit_date": "Oct. 8, 2020, 4:57 p.m.", | "deposit_date": "Oct. 8, 2020, 4:57 p.m.", | ||||
| } | } | ||||
| with open(metadata_path) as fd: | with open(metadata_path) as fd: | ||||
| assert ( | actual_metadata = dict(parse_xml(fd.read())) | ||||
| fd.read() | assert actual_metadata["author"] == TEST_USER["username"] | ||||
| == f"""\ | assert actual_metadata["codemeta:name"] == "test-project" | ||||
| <?xml version="1.0" encoding="utf-8"?> | assert actual_metadata["title"] == "test-project" | ||||
| <entry xmlns="http://www.w3.org/2005/Atom" \ | assert actual_metadata["updated"] is not None | ||||
| xmlns:codemeta="https://doi.org/10.5063/SCHEMA/CODEMETA-2.0"> | assert actual_metadata["codemeta:identifier"] == slug | ||||
| \t<codemeta:name>test-project</codemeta:name> | assert actual_metadata["codemeta:author"] == OrderedDict( | ||||
| \t<codemeta:identifier>{slug}</codemeta:identifier> | [("codemeta:name", "Jane Doe")] | ||||
| \t<codemeta:author> | |||||
| \t\t<codemeta:name>Jane Doe</codemeta:name> | |||||
| \t</codemeta:author> | |||||
| </entry>""" | |||||
| ) | ) | ||||
| def test_cli_validation_metadata( | def test_cli_validation_metadata( | ||||
| sample_archive, caplog, patched_tmp_path, cli_runner, slug | sample_archive, caplog, patched_tmp_path, cli_runner, slug | ||||
| ): | ): | ||||
| """Multiple metadata flags scenario (missing, conflicts) properly fails the calls | """Multiple metadata flags scenario (missing, conflicts) properly fails the calls | ||||
| ▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | assert json.loads(result.output) == { | ||||
| "deposit_id": "615", | "deposit_id": "615", | ||||
| "deposit_status": "partial", | "deposit_status": "partial", | ||||
| "deposit_status_detail": None, | "deposit_status_detail": None, | ||||
| "deposit_date": "Oct. 8, 2020, 4:57 p.m.", | "deposit_date": "Oct. 8, 2020, 4:57 p.m.", | ||||
| } | } | ||||
| with open(metadata_path) as fd: | with open(metadata_path) as fd: | ||||
| metadata_xml = fd.read() | metadata_xml = fd.read() | ||||
| actual_metadata = parse_xml(metadata_xml) | actual_metadata = dict(parse_xml(metadata_xml)) | ||||
| assert actual_metadata["codemeta:identifier"] is not None | assert actual_metadata["codemeta:identifier"] is not None | ||||
| def test_cli_multisteps_deposit( | def test_cli_multisteps_deposit( | ||||
| sample_archive, datadir, slug, requests_mock_datadir, cli_runner | sample_archive, datadir, slug, requests_mock_datadir, cli_runner | ||||
| ): | ): | ||||
| """ First deposit a partial deposit (no metadata, only archive), then update the metadata part. | """ First deposit a partial deposit (no metadata, only archive), then update the metadata part. | ||||
| https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#multisteps-deposit | https://docs.softwareheritage.org/devel/swh-deposit/getting-started.html#multisteps-deposit | ||||
| ▲ Show 20 Lines • Show All 246 Lines • Show Last 20 Lines | |||||
With this ^, we won't have that kind of unpleasant surprise any more.