diff --git a/src/documents/tests/export/test_compression.py b/src/documents/tests/export/test_compression.py index e7288cff3..6e40fe2bc 100644 --- a/src/documents/tests/export/test_compression.py +++ b/src/documents/tests/export/test_compression.py @@ -8,7 +8,15 @@ from documents.export import compression class TestCompressionMethods: def test_choices_always_include_zstd(self) -> None: - # zstd is offered regardless of runtime; availability is checked separately + """ + GIVEN: + - The compression policy module's CLI choices list + WHEN: + - Read on any runtime + THEN: + - zstd is always present; availability is checked separately so + argparse never hides it based on the current Python version + """ assert compression.COMPRESSION_CHOICES == ( "stored", "deflated", @@ -27,13 +35,37 @@ class TestCompressionMethods: ], ) def test_method_maps_to_zipfile_constant(self, name: str, constant: int) -> None: + """ + GIVEN: + - A compression method name + WHEN: + - Looked up in COMPRESSION_METHODS + THEN: + - It maps to the matching zipfile compression constant + """ assert compression.COMPRESSION_METHODS[name] == constant def test_stored_and_deflated_always_available(self) -> None: + """ + GIVEN: + - The stored and deflated compression methods + WHEN: + - Checked with compression_available() + THEN: + - Both are always available (zlib is a hard CPython dependency) + """ assert compression.compression_available("stored") assert compression.compression_available("deflated") def test_zstd_availability_tracks_runtime(self) -> None: + """ + GIVEN: + - The zstd compression method + WHEN: + - Checked with compression_available() on this runtime + THEN: + - Availability matches whether Python is 3.14+ + """ expected: bool = sys.version_info >= (3, 14) assert compression.compression_available("zstd") == expected @@ -51,6 +83,14 @@ class TestLevelError: ], ) def test_valid_levels_return_none(self, method: str, level: int | None) -> None: + """ + GIVEN: + - A method and a level within its valid bounds (or no level) + WHEN: + - Checked with level_error() + THEN: + - No error message is returned + """ assert compression.level_error(method, level) is None @pytest.mark.parametrize( @@ -67,12 +107,28 @@ class TestLevelError: method: str, level: int, ) -> None: + """ + GIVEN: + - A method and a level outside its valid bounds + WHEN: + - Checked with level_error() + THEN: + - An error message naming the valid range is returned + """ msg: str | None = compression.level_error(method, level) assert msg is not None assert "between" in msg @pytest.mark.parametrize("method", ["stored", "lzma"]) def test_level_on_levelless_method_is_rejected(self, method: str) -> None: + """ + GIVEN: + - A method that ignores compression level (stored, lzma) + WHEN: + - A level is passed to level_error() anyway + THEN: + - An error message noting the level has no effect is returned + """ msg: str | None = compression.level_error(method, 5) assert msg is not None assert "no effect" in msg @@ -81,18 +137,50 @@ class TestLevelError: class TestCompressTypeReadable: @pytest.mark.parametrize("ct", [zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED]) def test_stored_and_deflated_always_readable(self, ct: int) -> None: + """ + GIVEN: + - A stored or deflated compress_type id + WHEN: + - Checked with compress_type_readable() + THEN: + - It is always readable + """ assert compression.compress_type_readable(ct) def test_zstd_compress_type_readability_tracks_runtime(self) -> None: + """ + GIVEN: + - The current (93) and legacy (20) zstd compress_type ids + WHEN: + - Checked with compress_type_readable() on this runtime + THEN: + - Readability matches whether Python is 3.14+ + """ # 93 = ZIP_ZSTANDARD; 20 = legacy zstd method id (read-only) expected: bool = sys.version_info >= (3, 14) assert compression.compress_type_readable(93) == expected assert compression.compress_type_readable(20) == expected def test_unknown_compress_type_is_unreadable(self) -> None: + """ + GIVEN: + - An unrecognized compress_type id + WHEN: + - Checked with compress_type_readable() + THEN: + - It is reported as unreadable + """ assert not compression.compress_type_readable(9999) def test_unreadable_method_names_lists_methods(self) -> None: + """ + GIVEN: + - A set containing an unknown compress_type id + WHEN: + - Passed to unreadable_method_names() + THEN: + - It is reported generically as "method " + """ # An unknown method id maps to no name and is reported generically. names: set[str] = compression.unreadable_method_names({9999}) assert names == {"method 9999"} diff --git a/src/documents/tests/export/test_sinks.py b/src/documents/tests/export/test_sinks.py index 1f2064024..78c2936d0 100644 --- a/src/documents/tests/export/test_sinks.py +++ b/src/documents/tests/export/test_sinks.py @@ -323,10 +323,17 @@ class TestZipExportSinkCompression: method: str, constant: int, ) -> None: - # ZipExportSink's only responsibility here is forwarding the - # constructor's compression/compresslevel to zipfile.ZipFile - # unchanged; whether ZipFile actually compresses is Python's contract, - # not ours, so this checks the call args rather than the archive. + """ + GIVEN: + - A ZipExportSink constructed with a compression method and level + WHEN: + - The sink is opened + THEN: + - zipfile.ZipFile is constructed with those values forwarded + unchanged (whether ZipFile actually compresses is Python's own + contract, not ours, so this checks the call args, not a real + archive) + """ target: Path = tmp_path / "out" target.mkdir() zip_cls = mocker.patch("documents.export.sinks.zipfile.ZipFile") diff --git a/src/documents/tests/test_management_exporter.py b/src/documents/tests/test_management_exporter.py index 70c454e21..c298367b2 100644 --- a/src/documents/tests/test_management_exporter.py +++ b/src/documents/tests/test_management_exporter.py @@ -1081,6 +1081,14 @@ class TestExportImport( ) def test_compression_flags_require_zip(self) -> None: + """ + GIVEN: + - A request to export without --zip + WHEN: + - --zip-compression or --zip-compression-level is passed anyway + THEN: + - A CommandError is raised (the flags are meaningless without --zip) + """ for args in ( ["--zip-compression", "lzma"], ["--zip-compression-level", "5"], @@ -1094,6 +1102,14 @@ class TestExportImport( ) def test_zip_compression_level_out_of_range_raises(self) -> None: + """ + GIVEN: + - A request to export to a zip file + WHEN: + - --zip-compression-level is outside the chosen method's valid range + THEN: + - A CommandError is raised + """ with self.assertRaises(CommandError): call_command( "document_exporter", @@ -1107,6 +1123,14 @@ class TestExportImport( ) def test_zip_compression_level_rejected_for_stored(self) -> None: + """ + GIVEN: + - A request to export to a zip file with --zip-compression stored + WHEN: + - --zip-compression-level is also passed + THEN: + - A CommandError is raised (stored ignores level entirely) + """ with self.assertRaises(CommandError): call_command( "document_exporter", @@ -1120,10 +1144,19 @@ class TestExportImport( ) def test_zip_compression_flag_resolves_to_sink_constant(self) -> None: - # Whether zipfile actually compresses with the chosen method is - # Python's contract (and ZipExportSink's own tests already cover the - # forwarding). What this command owns is resolving the CLI string to - # the right constant, so assert that resolution directly. + """ + GIVEN: + - A request to export to a zip file with --zip-compression lzma + WHEN: + - The export runs + THEN: + - ZipExportSink is constructed with the resolved ZIP_LZMA constant + (whether zipfile actually compresses with the chosen method is + Python's own contract, and ZipExportSink's own tests already + cover the forwarding; what this command owns is resolving the + CLI string to the right constant, so assert that resolution + directly) + """ with mock.patch( "documents.management.commands.document_exporter.ZipExportSink", ) as sink_cls: @@ -1144,6 +1177,15 @@ class TestExportImport( ) def test_default_zip_compression_resolves_to_deflate(self) -> None: + """ + GIVEN: + - A request to export to a zip file with no --zip-compression flag + WHEN: + - The export runs + THEN: + - ZipExportSink is constructed with the default ZIP_DEFLATED + constant and compresslevel=None, matching pre-existing behavior + """ with mock.patch( "documents.management.commands.document_exporter.ZipExportSink", ) as sink_cls: