diff --git a/lib/Parser/Construct.php b/lib/Parser/Construct.php index b285487..ff88842 100644 --- a/lib/Parser/Construct.php +++ b/lib/Parser/Construct.php @@ -64,7 +64,7 @@ trait Construct { } protected function parseMediaType(string $type, ?Url $url = null): ?string { - if (preg_match('<^\s*([0-9a-z]+(?:/[!#$%&\'\*\+\-\.^_`|~0-9a-z]+)?)(?:\s|;|$)>i', $type, $match)) { + if (preg_match('<^\s*([0-9a-z]+(?:/[!#$%&\'\*\+\-\.^_`|~0-9a-z]+)?)(?:\s|;|,|$)>i', $type, $match)) { /* NOTE: The pattern used here is a subset of what is technically allowed by RFC 7231: the "type" portion is supposed to be as general as the "subtype" portion, @@ -91,6 +91,8 @@ trait Construct { return ($this->mime ?? ($this->mime = new \Mimey\MimeTypes))->getMimeType($ext); } } + } elseif ($url && $url->getScheme() === "data") { + return $this->parseMediaType($url->getPath()) ?? "text/plain"; } return null; } diff --git a/tests/cases/JSON/JSONTest.php b/tests/cases/JSON/JSONTest.php index cf86d9b..fd33345 100644 --- a/tests/cases/JSON/JSONTest.php +++ b/tests/cases/JSON/JSONTest.php @@ -8,27 +8,26 @@ namespace JKingWeb\Lax\TestCase\JSON; /* Test format is as follows: - Each test is a JSON object with the following keys: + Each test is a YAML map with the following keys: - - `description`: a short human-readable description of the test - - `doc_url`: A fictitious URL where a newsfeed might be located, used for relative URL resolution - `input`: The test input, as a string or directly as a JSON Feed structure - `output`: The result of the parsing upon success; described in more detail below - `exception`: The exception ID thrown upon failure + - `type`: An HTTP Content-Type (with or without parameters) for the document + - `doc_url`: A fictitious URL where a newsfeed might be located, used for relative URL resolution - The 'description' and 'input' keys along with either 'output' or 'exception' - are required for all tests. + The 'input' key along with either 'output' or 'exception' are required for all tests. - The test output is necessarily mangled due to the limits of JSON: + The test output is necessarily mangled due to the limits of YAML: - Any field which should be an absolute URL should be written as a string, which will be transformed accordingly. Relative URLs should be represented - as an array with the relative part first, followed by the base that should + as a sequence with the relative part first, followed by the base that should be applied to it - - Any collections should be represented as arrays of objects, which will + - Any collections should be represented as sequences of maps, which will all be transformed accordingly - Rich text can either be supplied as a string (which will yield a Text object - with plain-text content) or as an object with any of the properties of the + with plain-text content) or as a map with any of the properties of the Text class listed The transformations as performed by the `makeFeed` and `makeEntry` methods @@ -49,6 +48,9 @@ use JKingWeb\Lax\Enclosure\Enclosure; use JKingWeb\Lax\Person\Collection as PersonCollection; use JKingWeb\Lax\Category\Collection as CategoryCollection; use JKingWeb\Lax\Enclosure\Collection as EnclosureCollection; +use Symfony\Component\Yaml\Yaml; +use Symfony\Component\Yaml\Parser as YamlParser; + /** * @covers JKingWeb\Lax\Parser\Construct @@ -75,12 +77,12 @@ class JSONTest extends \PHPUnit\Framework\TestCase { } public function provideJSONFeedVersion1(): iterable { - foreach (new \GlobIterator(__DIR__."/*.json", \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::KEY_AS_FILENAME) as $file => $path) { - foreach (json_decode(file_get_contents($path)) as $index => $test) { + foreach (new \GlobIterator(__DIR__."/*.yaml", \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::KEY_AS_FILENAME) as $file => $path) { + foreach ((new YamlParser)->parseFile($path, Yaml::PARSE_OBJECT_FOR_MAP) as $description => $test) { if (isset($test->exception)) { $test->output = new Exception((string) $test->exception); } - yield "$file #$index: {$test->description}" => [ + yield "$file: {$description}" => [ $test->input, $test->type ?? "", $test->doc_url ?? null, @@ -204,4 +206,4 @@ class JSONTest extends \PHPUnit\Framework\TestCase { return new Url($url); } } -} \ No newline at end of file +} diff --git a/tests/cases/JSON/entry.json b/tests/cases/JSON/entry.json deleted file mode 100644 index 51371d1..0000000 --- a/tests/cases/JSON/entry.json +++ /dev/null @@ -1,628 +0,0 @@ -[ - { - "description": "Minimal entry", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": "1" - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1" - } - ] - } - }, - { - "description": "Invalid entry 1 (no ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Invalid entry 2 (null ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": null, - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Invalid entry 3 (boolean ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": true, - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Invalid entry 4 (array ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": ["1"], - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Invalid entry 5 (object ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": {"id": "1"}, - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Invalid entry 6 (empty string ID)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": "", - "title": "Example title" - }] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Integer ID", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": 1 - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1" - } - ] - } - }, - { - "description": "Float ID", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": 3.0e-10 - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "0.0000000003" - } - ] - } - }, - { - "description": "Negative float ID", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": -3.0e-10 - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "-0.0000000003" - } - ] - } - }, - { - "description": "Simple float ID", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": 0.3 - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "0.3" - } - ] - } - }, - { - "description": "Bignum ID", - "input": "{\"version\": \"https://jsonfeed.org/version/1\",\"items\": [{\"id\": 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999}]}", - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" - } - ] - } - }, - { - "description": "Entry language", - "input": { - "version": "https://jsonfeed.org/version/1", - "language": "en", - "items": [ - { - "id": 1, - "language": "fr" - }, - { - "id": "2" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "lang": "en", - "entries": [ - { - "id": "1", - "lang": "fr" - }, - { - "id": "2", - "lang": "en" - } - ] - } - }, - { - "description": "Entry banner", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "banner_image": "http://example.com/banner" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "banner": "http://example.com/banner" - } - ] - } - }, - { - "description": "Entry dates", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "date_published": "2020-03-03T21:12:42Z", - "date_modified": "2020-03-03T21:12:42Z" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "dateCreated": "2020-03-03T21:12:42Z", - "dateModified": "2020-03-03T21:12:42Z" - } - ] - } - }, - { - "description": "Entry URLs", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "url": "http://example.com/", - "external_url": "http://example.org/" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "link": "http://example.com/", - "relatedLink": "http://example.org/" - } - ] - } - }, - { - "description": "Entry title", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "title": "Example title" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "title": "Example title" - } - ] - } - }, - { - "description": "Entry summary", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "summary": "Example summary" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "summary": "Example summary" - } - ] - } - }, - { - "description": "Entry content (plain only)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "content_text": "Plain content" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "content": { - "plain": "Plain content" - } - } - ] - } - }, - { - "description": "Entry content (HTML only)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "content_html": "HTML content" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "content": { - "html": "HTML content" - } - } - ] - } - }, - { - "description": "Entry content (mixed)", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "content_text": "Plain content", - "content_html": "HTML content" - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "content": { - "plain": "Plain content", - "html": "HTML content" - } - } - ] - } - }, - { - "description": "Entry categories", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [ - { - "id": "1", - "tags": ["this", "that", "the other thing", "", null, false, 1, 3.0, " "] - } - ] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "categories": [ - {"name": "this"}, - {"name": "that"}, - {"name": "the other thing"}, - {"name": " "} - ] - } - ] - } - }, - { - "description": "Entry authors", - "input": { - "version": "https://jsonfeed.org/version/1", - "authors": [ - {"name": "Jane Doe"}, - {"name": "John Doe"} - ], - "items": [ - { - "id": 1, - "author": {"name": "John Doe"}, - "authors": [{"name": "Jane Doe"}] - }, - { - "id": 2, - "author": {"name": "John Doe"} - }, - { - "id": 3, - "authors": [{"name": "Jane Doe"}] - }, - { - "id": 4 - }, - { - "id": 5, - "authors": [{"NAME": "Jane Doe"}] - } - ] - }, - "output": { - "format": "json", - "version": "1", - "people": [ - {"name": "Jane Doe", "role": "author"}, - {"name": "John Doe", "role": "author"} - ], - "entries": [ - {"id": "1", "people": [{"name": "Jane Doe", "role": "author"}]}, - {"id": "2", "people": [{"name": "John Doe", "role": "author"}]}, - {"id": "3", "people": [{"name": "Jane Doe", "role": "author"}]}, - {"id": "4", "people": [{"name": "Jane Doe", "role": "author"},{"name": "John Doe", "role": "author"}]}, - {"id": "5", "people": [{"name": "Jane Doe", "role": "author"},{"name": "John Doe", "role": "author"}]} - ] - } - }, - { - "description": "Entry image", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": "1", - "image": "http://example.com/image" - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "enclosures": [ - { - "type": "image", - "url": "http://example.com/image", - "preferred": true - } - ] - } - ] - } - }, - { - "description": "Entry attachments", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": "1", - "attachments": [ - { - "url": "http://example.com/image", - "mime_type": "image/svg+xml; charset=\"urf-8\"", - "title": "Logo", - "size_in_bytes": 2345 - }, - { - "url": "http://example.com/graphic.png" - }, - { - "url": "http://example.com/graphic.PNG" - }, - { - "url": "data:text/plain,Hello%20World!", - "title": "Example text" - }, - { - "url": "data:text/plain,File:example.jpg", - "title": "Sneaky URN" - }, - { - "url": "http://example.com/talk", - "mime_type": "audio", - "duration_in_seconds": 72 - }, - { - "title": "Invalid URL", - "url": "http://[.com/bogus" - }, - { - "title": "No URL" - } - ] - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "enclosures": [ - { - "type": "image/svg+xml", - "url": "http://example.com/image", - "title": "Logo", - "size": 2345 - }, - { - "type": "image/png", - "url": "http://example.com/graphic.png" - }, - { - "type": "image/png", - "url": "http://example.com/graphic.PNG" - }, - { - "url": "data:text/plain,Hello%20World!", - "title": "Example text" - }, - { - "url": "data:text/plain,File:example.jpg", - "title": "Sneaky URN" - }, - { - "url": "http://example.com/talk", - "type": "audio", - "duration": 72 - } - ] - } - ] - } - }, - { - "description": "Entry image and attachments", - "input": { - "version": "https://jsonfeed.org/version/1", - "items": [{ - "id": "1", - "attachments": [ - { - "url": "http://example.com/image", - "mime_type": "image/svg+xml; charset=\"urf-8\"", - "title": "Logo", - "size_in_bytes": 2345 - } - ], - "image": "http://example.com/image" - }] - }, - "output": { - "format": "json", - "version": "1", - "entries": [ - { - "id": "1", - "enclosures": [ - { - "type": "image", - "url": "http://example.com/image", - "preferred": true - }, - { - "type": "image/svg+xml", - "url": "http://example.com/image", - "title": "Logo", - "size": 2345 - } - ] - } - ] - } - } -] \ No newline at end of file diff --git a/tests/cases/JSON/entry.yaml b/tests/cases/JSON/entry.yaml new file mode 100644 index 0000000..56b0f52 --- /dev/null +++ b/tests/cases/JSON/entry.yaml @@ -0,0 +1,547 @@ +Minimal entry: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": "1" + }] + } + output: + format: json + version: '1' + entries: + - id: '1' + +Invalid entry 1: # no ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title" + }] + } + output: + format: json + version: '1' + +Invalid entry 2: # null ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title", + "id": null + }] + } + output: + format: json + version: '1' + +Invalid entry 3: # boolean ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title", + "id": true + }] + } + output: + format: json + version: '1' + +Invalid entry 4: # array ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title", + "id": ["1"] + }] + } + output: + format: json + version: '1' + +Invalid entry 5: # object ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title", + "id": {"id": "1"} + }] + } + output: + format: json + version: '1' + +Invalid entry 6: # empty string ID + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "title": "Example title", + "id": "" + }] + } + output: + format: json + version: '1' + +Integer ID: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": 1 + }] + } + output: + format: json + version: '1' + entries: + - id: '1' + +Float ID: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": 3.0e-10 + }] + } + output: + format: json + version: '1' + entries: + - id: '0.0000000003' + +Negative float ID: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": -3.0e-10 + }] + } + output: + format: json + version: '1' + entries: + - id: '-0.0000000003' + +Simple float ID: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": 0.3 + }] + } + output: + format: json + version: '1' + entries: + - id: '0.3' + +Bignum ID: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + }] + } + output: + format: json + version: '1' + entries: + - id: '9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999' + +Entry language: + input: > + { + "version": "https://jsonfeed.org/version/1", + "language": "en", + "items": [ + { + "id": 1, + "language": "fr" + }, + { + "id": "2" + } + ] + } + output: + format: json + version: '1' + lang: en + entries: + - id: '1' + lang: fr + - id: '2' + lang: en + +Entry banner: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "banner_image": "http://example.com/banner" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + banner: 'http://example.com/banner' + +Entry dates: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "date_published": "2020-03-03T21:12:42Z", + "date_modified": "2020-03-03T21:12:42Z" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + dateCreated: '2020-03-03T21:12:42Z' + dateModified: '2020-03-03T21:12:42Z' + +Entry URLs: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "url": "http://example.com/", + "external_url": "http://example.org/" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + link: 'http://example.com/' + relatedLink: 'http://example.org/' + +Entry title: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "title": "Example title" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + title: 'Example title' + +Entry summary: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "summary": "Example summary" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + summary: 'Example summary' + +Entry content (plain only): + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "content_text": "Plain content" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + content: + plain: 'Plain content' + +Entry content (HTML only): + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "content_html": "HTML content" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + content: + html: 'HTML content' + +Entry content (mixed): + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "content_text": "Plain content", + "content_html": "HTML content" + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + content: + plain: 'Plain content' + html: 'HTML content' + +Entry categories: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [ + { + "id": "1", + "tags": ["this", "that", "the other thing", "", null, false, 1, 3.0, " "] + } + ] + } + output: + format: json + version: '1' + entries: + - id: '1' + categories: + - name: this + - name: that + - name: 'the other thing' + - name: ' ' + +Entry authors: + input: > + { + "version": "https://jsonfeed.org/version/1", + "authors": [ + {"name": "Jane Doe"}, + {"name": "John Doe"} + ], + "items": [ + { + "id": 1, + "author": {"name": "John Doe"}, + "authors": [{"name": "Jane Doe"}] + }, + { + "id": 2, + "author": {"name": "John Doe"} + }, + { + "id": 3, + "authors": [{"name": "Jane Doe"}] + }, + { + "id": 4 + }, + { + "id": 5, + "authors": [{"NAME": "Jane Doe"}] + } + ] + } + output: + format: json + version: '1' + people: + - name: Jane Doe + role: author + - name: John Doe + role: author + entries: + - id: '1' + people: + - name: Jane Doe + role: author + - id: '2' + people: + - name: John Doe + role: author + - id: '3' + people: + - name: Jane Doe + role: author + - id: '4' + people: + - name: Jane Doe + role: author + - name: John Doe + role: author + - id: '5' + people: + - name: Jane Doe + role: author + - name: John Doe + role: author + +Entry image: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": "1", + "image": "http://example.com/image" + }] + } + output: + format: json + version: '1' + entries: + - id: '1' + enclosures: + - url: 'http://example.com/image' + type: image + preferred: true + +Entry attachments: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": "1", + "attachments": [ + { + "url": "http://example.com/image", + "mime_type": "image/svg+xml; charset=\"urf-8\"", + "title": "Logo", + "size_in_bytes": 2345 + }, + { + "url": "http://example.com/graphic.png" + }, + { + "url": "http://example.com/graphic.PNG" + }, + { + "url": "data:text/rtf,Hello%20World!", + "title": "Example text" + }, + { + "url": "data:,Hello%20World!", + "title": "Example text" + }, + { + "url": "urn:bogus:example.jpg", + "title": "Sneaky URN" + }, + { + "url": "http://example.com/talk", + "mime_type": "audio", + "duration_in_seconds": 72 + }, + { + "title": "Invalid URL", + "url": "http://[.com/bogus" + }, + { + "title": "No URL" + } + ] + }] + } + output: + format: json + version: '1' + entries: + - id: '1' + enclosures: + - url: 'http://example.com/image' + type: 'image/svg+xml' + title: Logo + size: 2345 + - url: 'http://example.com/graphic.png' + type: 'image/png' + - url: 'http://example.com/graphic.PNG' + type: 'image/png' + - url: 'data:text/rtf,Hello%20World!' + type: 'text/rtf' + title: 'Example text' + - url: 'data:,Hello%20World!' + type: 'text/plain' + title: 'Example text' + - url: 'urn:bogus:example.jpg' + title: 'Sneaky URN' + - url: 'http://example.com/talk' + type: 'audio' + duration: 72 + +Entry image and attachments: + input: > + { + "version": "https://jsonfeed.org/version/1", + "items": [{ + "id": "1", + "attachments": [ + { + "url": "http://example.com/logo", + "mime_type": "image/svg+xml; charset=\"urf-8\"", + "title": "Logo", + "size_in_bytes": 2345 + } + ], + "image": "http://example.com/image" + }] + } + output: + format: json + version: '1' + entries: + - id: '1' + enclosures: + - url: 'http://example.com/image' + type: image + preferred: true + - url: 'http://example.com/logo' + type: 'image/svg+xml' + title: Logo + size: 2345 diff --git a/tests/cases/JSON/failures.json b/tests/cases/JSON/failures.json deleted file mode 100644 index 0bb8d1b..0000000 --- a/tests/cases/JSON/failures.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "description": "Content-Type mismatch", - "type": "text/html", - "input": {"version": "https://jsonfeed.org/version/1"}, - "exception": "notJSONType" - }, - { - "description": "Not valid JSON 1", - "input": "{", - "exception": "notJSON" - }, - { - "description": "Not valid JSON 2", - "input": "", - "exception": "notJSON" - }, - { - "description": "Not a JSON feed 1", - "input": "{}", - "exception": "notJSONFeed" - }, - { - "description": "Not a JSON feed 2", - "input": {"version": "https://example.com/"}, - "exception": "notJSONFeed" - }, - { - "description": "Not a JSON feed 3", - "input": {"version": "https://jsonfeed.org/version/"}, - "exception": "notJSONFeed" - } -] \ No newline at end of file diff --git a/tests/cases/JSON/failures.yaml b/tests/cases/JSON/failures.yaml new file mode 100644 index 0000000..b68a4f8 --- /dev/null +++ b/tests/cases/JSON/failures.yaml @@ -0,0 +1,24 @@ +Content-Type mismatch: + type: text/html + input: '{"version": "https://jsonfeed.org/version/1"}' + exception: notJSONType + +Not valid JSON 1: + input: '{' + exception: notJSON + +Not valid JSON 2: + input: '' + exception: notJSON + +Not a JSON feed 1: + input: '{}' + exception: notJSONFeed + +Not a JSON feed 2: + input: '{"version": "https://example.com/"}' + exception: notJSONFeed + +Not a JSON feed 3: + input: '{"version": "https://jsonfeed.org/version/"}' + exception: notJSONFeed diff --git a/tests/cases/JSON/feed.json b/tests/cases/JSON/feed.json deleted file mode 100644 index c196efe..0000000 --- a/tests/cases/JSON/feed.json +++ /dev/null @@ -1,261 +0,0 @@ -[ - { - "description": "Minimal example 1", - "input": { - "version": "https://jsonfeed.org/version/1" - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Minimal example 2", - "input": { - "version": "https://jsonfeed.org/version/1.1" - }, - "output": { - "format": "json", - "version": "1.1" - } - }, - { - "description": "Correct type of member", - "input": { - "version": "https://jsonfeed.org/version/1", - "title": "Example title" - }, - "output": { - "format": "json", - "version": "1", - "title": "Example title" - } - }, - { - "description": "Incorrect type of member", - "input": { - "version": "https://jsonfeed.org/version/1", - "title": 1001001 - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "URL -> ID equivalence", - "input": { - "version": "https://jsonfeed.org/version/1", - "title": "Example title", - "feed_url": "http://example.com/" - }, - "output": { - "format": "json", - "version": "1", - "title": "Example title", - "id": "http://example.com/", - "url": "http://example.com/" - } - }, - { - "description": "Single author", - "input": { - "version": "https://jsonfeed.org/version/1", - "author": {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"} - }, - "output": { - "format": "json", - "version": "1", - "people": [ - { - "role": "author", - "name": "John Doe", - "url": "http://example.org/", - "avatar": "http://example.org/avatar" - } - ] - } - }, - { - "description": "Multiple authors", - "input": { - "version": "https://jsonfeed.org/version/1", - "authors": [ - {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"}, - {"name": "Jane Doe", "url": "http://example.net/", "avatar": "http://example.net/avatar"} - ] - }, - "output": { - "format": "json", - "version": "1", - "people": [ - { - "role": "author", - "name": "John Doe", - "url": "http://example.org/", - "avatar": "http://example.org/avatar" - }, - { - "role": "author", - "name": "Jane Doe", - "url": "http://example.net/", - "avatar": "http://example.net/avatar" - } - ] - } - }, - { - "description": "Fallback author", - "input": { - "version": "https://jsonfeed.org/version/1", - "authors": [ - {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"}, - {"name": "Jane Doe", "url": "http://example.net/", "avatar": "http://example.net/avatar"} - ], - "author": {"name": "John Smith", "url": "http://example.biz/", "avatar": "http://example.biz/avatar"} - }, - "output": { - "format": "json", - "version": "1", - "people": [ - { - "role": "author", - "name": "John Doe", - "url": "http://example.org/", - "avatar": "http://example.org/avatar" - }, - { - "role": "author", - "name": "Jane Doe", - "url": "http://example.net/", - "avatar": "http://example.net/avatar" - } - ] - } - }, - { - "description": "Empty author", - "input": { - "version": "https://jsonfeed.org/version/1", - "author": {} - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Empty authors", - "input": { - "version": "https://jsonfeed.org/version/1", - "authors": [{}] - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Empty authors with fallback", - "input": { - "version": "https://jsonfeed.org/version/1", - "authors": [{}], - "author": {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"} - }, - "output": { - "format": "json", - "version": "1", - "people": [ - { - "role": "author", - "name": "John Doe", - "url": "http://example.org/", - "avatar": "http://example.org/avatar" - } - ] - } - }, - { - "description": "Expired feed", - "input": { - "version": "https://jsonfeed.org/version/1", - "expired": true - }, - "output": { - "format": "json", - "version": "1", - "sched": { - "expired": true - } - } - }, - { - "description": "Not expired feed", - "input": { - "version": "https://jsonfeed.org/version/1", - "expired": false - }, - "output": { - "format": "json", - "version": "1", - "sched": { - "expired": false - } - } - }, - { - "description": "Invalidly expired feed", - "input": { - "version": "https://jsonfeed.org/version/1", - "expired": 1 - }, - "output": { - "format": "json", - "version": "1" - } - }, - { - "description": "Basic example", - "input": { - "version": "https://jsonfeed.org/version/1", - "language": "en", - "title": "Example title", - "feed_url": "http://example.com/", - "home_page_url": "http://example.net/", - "description": "Example description", - "user_comment": "Example comment", - "next_url": "http://example.com/next", - "icon": "http://example.com/image", - "favicon": "http://example.com/icon" - }, - "output": { - "format": "json", - "version": "1", - "lang": "en", - "title": "Example title", - "id": "http://example.com/", - "url": "http://example.com/", - "link": "http://example.net/", - "summary": "Example description", - "icon": "http://example.com/icon", - "image": "http://example.com/image" - } - }, - { - "description": "Relative URL resolution", - "doc_url": "http://example.com", - "input": { - "version": "https://jsonfeed.org/version/1", - "feed_url": "feed.json" - }, - "output": { - "meta": { - "url": "http://example.com" - }, - "format": "json", - "version": "1", - "id": "feed.json", - "url": ["feed.json", "http://example.com"] - } - } -] \ No newline at end of file diff --git a/tests/cases/JSON/feed.yaml b/tests/cases/JSON/feed.yaml new file mode 100644 index 0000000..6cfd122 --- /dev/null +++ b/tests/cases/JSON/feed.yaml @@ -0,0 +1,221 @@ +Minimal example 1: + input: > + { + "version": "https://jsonfeed.org/version/1" + } + output: + format: json + version: '1' + +Minimal example 2: + input: > + { + "version": "https://jsonfeed.org/version/1.1" + } + output: + format: json + version: '1.1' + +Correct type of member: + input: > + { + "version": "https://jsonfeed.org/version/1", + "title": "Example title" + } + output: + format: json + version: '1' + title: 'Example title' + +Incorrect type of member: + input: > + { + "version": "https://jsonfeed.org/version/1", + "title": 1001001 + } + output: + format: json + version: '1' + +URL -> ID equivalence: + input: > + { + "version": "https://jsonfeed.org/version/1", + "feed_url": "http://example.com/" + } + output: + format: json + version: '1' + id: 'http://example.com/' + url: 'http://example.com/' + +Single author: + input: > + { + "version": "https://jsonfeed.org/version/1", + "author": {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"} + } + output: + format: json + version: '1' + people: + - role: author + name: John Doe + url: 'http://example.org/' + avatar: http://example.org/avatar + +Multiple authors: + input: > + { + "version": "https://jsonfeed.org/version/1", + "authors": [ + {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"}, + {"name": "Jane Doe", "url": "http://example.net/", "avatar": "http://example.net/avatar"} + ] + } + output: + format: json + version: '1' + people: + - role: author + name: John Doe + url: 'http://example.org/' + avatar: http://example.org/avatar + - role: author + name: Jane Doe + url: 'http://example.net/' + avatar: http://example.net/avatar + +Fallback author: + input: > + { + "version": "https://jsonfeed.org/version/1", + "authors": [ + {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"}, + {"name": "Jane Doe", "url": "http://example.net/", "avatar": "http://example.net/avatar"} + ], + "author": {"name": "John Smith", "url": "http://example.biz/", "avatar": "http://example.biz/avatar"} + } + output: + format: json + version: '1' + people: + - role: author + name: John Doe + url: 'http://example.org/' + avatar: http://example.org/avatar + - role: author + name: Jane Doe + url: 'http://example.net/' + avatar: http://example.net/avatar + +Empty author: + input: > + { + "version": "https://jsonfeed.org/version/1", + "author": {} + } + output: + format: json + version: '1' + +Empty authors: + input: > + { + "version": "https://jsonfeed.org/version/1", + "authors": [{}] + } + output: + format: json + version: '1' + +Empty authors with fallback: + input: > + { + "version": "https://jsonfeed.org/version/1", + "authors": [{}], + "author": {"name": "John Doe", "url": "http://example.org/", "avatar": "http://example.org/avatar"} + } + output: + format: json + version: '1' + people: + - role: author + name: John Doe + url: 'http://example.org/' + avatar: http://example.org/avatar + +Expired feed: + input: > + { + "version": "https://jsonfeed.org/version/1", + "expired": true + } + output: + format: json + version: '1' + sched: + expired: true + +Not expired feed: + input: > + { + "version": "https://jsonfeed.org/version/1", + "expired": false + } + output: + format: json + version: '1' + sched: + expired: false + +Improperly expired feed: # the 'expired' JSON Feed key is explicitly a boolean + input: > + { + "version": "https://jsonfeed.org/version/1", + "expired": 1 + } + output: + format: json + version: '1' + +Multiple elements: + input: > + { + "version": "https://jsonfeed.org/version/1", + "language": "en", + "title": "Example title", + "feed_url": "http://example.com/", + "home_page_url": "http://example.net/", + "description": "Example description", + "user_comment": "Example comment", + "next_url": "http://example.com/next", + "icon": "http://example.com/image", + "favicon": "http://example.com/icon" + } + output: + format: json + version: '1' + lang: en + title: Example title + id: 'http://example.com/' + url: 'http://example.com/' + link: 'http://example.net/' + summary: Example description + icon: 'http://example.com/icon' + image: 'http://example.com/image' + +Relative URL resolution: + doc_url: 'http://example.com' + input: > + { + "version": "https://jsonfeed.org/version/1", + "feed_url": "feed.json" + } + output: + meta: + url: 'http://example.com' + format: json + version: '1' + id: 'feed.json' + url: ['feed.json', 'http://example.com'] diff --git a/vendor-bin/phpunit/composer.json b/vendor-bin/phpunit/composer.json index f76e141..bc16564 100644 --- a/vendor-bin/phpunit/composer.json +++ b/vendor-bin/phpunit/composer.json @@ -1,5 +1,6 @@ { "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^9.0", + "symfony/yaml": "^5.0" } } diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index 128459d..5319864 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b7670d90fa803400168312d1b096854c", + "content-hash": "5f6ef85b0137813e2008ed286079c104", "packages": [], "packages-dev": [ { @@ -1501,6 +1501,65 @@ ], "time": "2020-01-13T11:15:53+00:00" }, + { + "name": "symfony/yaml", + "version": "v5.0.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a4b613d7e44f62941adff5a802cff70adee57d3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a4b613d7e44f62941adff5a802cff70adee57d3f", + "reference": "a4b613d7e44f62941adff5a802cff70adee57d3f", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2020-02-03T13:51:17+00:00" + }, { "name": "theseer/tokenizer", "version": "1.1.3",