diff options
Diffstat (limited to 'app/src/test/java')
| -rw-r--r-- | app/src/test/java/org/terst/feedreader/readability/ExtractionFailureTest.kt | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/app/src/test/java/org/terst/feedreader/readability/ExtractionFailureTest.kt b/app/src/test/java/org/terst/feedreader/readability/ExtractionFailureTest.kt new file mode 100644 index 0000000..6f691fd --- /dev/null +++ b/app/src/test/java/org/terst/feedreader/readability/ExtractionFailureTest.kt @@ -0,0 +1,82 @@ +package org.terst.feedreader.readability + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +/** + * Extraction failures used to be discarded entirely — ReaderScreen did + * `extracted?.content?.let { }`, so any failure left the reader silently showing + * the raw feed content. The bug report that prompted this could say only + * "extraction failed", because the app itself never knew why. + * + * These pin the two things a failure has to produce: something short enough to + * put in front of the user, and something specific enough to debug from. + */ +class ExtractionFailureTest { + + @Test + fun `load error names the underlying description`() { + val f = ExtractionFailure.LoadError(-2, "net::ERR_NAME_NOT_RESOLVED") + assertEquals("Couldn't load the page (net::ERR_NAME_NOT_RESOLVED)", f.userMessage()) + assertTrue(f.diagnostic().contains("code=-2")) + assertTrue(f.diagnostic().contains("ERR_NAME_NOT_RESOLVED")) + } + + @Test + fun `load error without a description still reads properly`() { + assertEquals("Couldn't load the page", ExtractionFailure.LoadError(-1, null).userMessage()) + assertEquals("Couldn't load the page", ExtractionFailure.LoadError(-1, " ").userMessage()) + } + + @Test + fun `http error names the status`() { + val f = ExtractionFailure.HttpError(403, "Forbidden") + assertEquals("Server returned HTTP 403", f.userMessage()) + assertTrue(f.diagnostic().contains("status=403")) + } + + @Test + fun `timeout is reported in seconds`() { + assertEquals("Page took longer than 25s to load", ExtractionFailure.TimedOut(25_000).userMessage()) + assertTrue(ExtractionFailure.TimedOut(25_000).diagnostic().contains("25000ms")) + } + + @Test + fun `readability error carries the thrown message`() { + val f = ExtractionFailure.ReadabilityError("TypeError: x is null") + assertTrue(f.userMessage().contains("TypeError")) + assertTrue(f.diagnostic().contains("TypeError")) + } + + @Test + fun `no content is distinct from an error`() { + assertEquals("No article text found on the page", ExtractionFailure.NoContent.userMessage()) + } + + // The raw JS result can be enormous; a diagnostic that pastes all of it is + // unusable in a bug report. + @Test + fun `bad result truncates the raw payload`() { + val f = ExtractionFailure.BadResult("x".repeat(5_000)) + assertTrue("diagnostic should be bounded", f.diagnostic().length < 400) + } + + // Every case must produce a non-empty message; a blank one would put the + // user back where they started. + @Test + fun `every failure produces both messages`() { + val all = listOf( + ExtractionFailure.LoadError(-6, "ERR_CONNECTION_REFUSED"), + ExtractionFailure.HttpError(500, null), + ExtractionFailure.TimedOut(25_000), + ExtractionFailure.ReadabilityError("boom"), + ExtractionFailure.NoContent, + ExtractionFailure.BadResult("{}"), + ) + for (f in all) { + assertTrue("$f has a blank user message", f.userMessage().isNotBlank()) + assertTrue("$f has a blank diagnostic", f.diagnostic().isNotBlank()) + } + } +} |
