def test_semantic_analyzer_does_correctly_processes_valid_ast(self): manifest = RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), ) media_types_registry = RWPMMediaTypesRegistry() link_relations_registry = RWPMLinkRelationsRegistry() collection_roles_registry = RWPMCollectionRolesRegistry() semantic_analyzer = RWPMSemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest)
def test_cast(self): # Arrange navigation_links = LinkList([Link(href="http://example.com")]) navigation = OPDS2Navigation(links=navigation_links) # Act casted_navigation = cast(navigation, CompactCollection) # Assert self.assertIsInstance(casted_navigation, CompactCollection) self.assertEqual(navigation_links, casted_navigation.links)
def test_syntax_analyzer_returns_ast(self): # Arrange syntax_analyzer = RWPMSyntaxAnalyzer() input_steam = six.StringIO(RWPM_MANIFEST) manifest_json = ManifestParser.get_manifest_json(input_steam) # Act manifest = syntax_analyzer.analyze(manifest_json) # Assert self.assertIsInstance(manifest, RWPMManifest) self.assertIsInstance(manifest.context, list) self.assertEqual(1, len(manifest.context)) [context] = manifest.context self.assertEqual(context, "https://readium.org/webpub-manifest/context.jsonld") self.assertIsInstance(manifest.metadata, Metadata) self.assertEqual("http://schema.org/Book", manifest.metadata.type) self.assertEqual("Moby-Dick", manifest.metadata.title) self.assertEqual( [Contributor(name="Herman Melville", roles=[], links=LinkList())], manifest.metadata.authors, ) self.assertEqual("urn:isbn:978031600000X", manifest.metadata.identifier) self.assertEqual(["en"], manifest.metadata.languages) self.assertEqual( datetime.datetime(2015, 9, 29, 17, 0, 0, tzinfo=tzutc()), manifest.metadata.modified, ) self.assertIsInstance(manifest.links, list) self.assertEqual(1, len(manifest.links)) [link] = manifest.links self.assertIsInstance(link.rels, list) self.assertEqual(1, len(link.rels)) self.assertEqual(RWPMLinkRelationsRegistry.SELF.key, link.rels[0]) self.assertEqual("https://example.com/manifest.json", link.href) self.assertEqual(RWPMMediaTypesRegistry.MANIFEST.key, link.type) self.assertIsInstance(manifest.reading_order, CompactCollection) self.assertIsInstance(manifest.reading_order.links, list) self.assertEqual(1, len(manifest.reading_order.links)) [reading_order_link] = manifest.reading_order.links self.assertEqual("https://example.com/c001.html", reading_order_link.href) self.assertEqual(RWPMMediaTypesRegistry.HTML.key, reading_order_link.type) self.assertEqual("Chapter 1", reading_order_link.title)
class RWPMSyntaxAnalyzerTest(TestCase): @parameterized.expand([ ( "when_manifest_does_not_contain_metadata", RWPM_MANIFEST_WITHOUT_METADATA, RWPMManifest, RWPMManifest.metadata.key, ), ( "when_manifest_metadata_does_not_contain_title", RWPM_MANIFEST_WITH_MISSING_METADATA_TITLE_PROPERTY, PresentationMetadata, PresentationMetadata.title.key, ), ( "when_metadata_contributor_does_not_contain_name", RWPM_MANIFEST_WITH_MISSING_CONTRIBUTOR_NAME_PROPERTY, Contributor, Contributor.name.key, ), ( "when_metadata_subject_does_not_contain_name", RWPM_MANIFEST_WITH_MISSING_SUBJECT_NAME_PROPERTY, Subject, Subject.name.key, ), ( "when_manifest_does_not_contain_links", RWPM_MANIFEST_WITHOUT_LINKS, RWPMManifest, RWPMManifest.links.key, ), ( "when_manifest_link_does_not_contain_href", RWPM_MANIFEST_WITH_MISSING_LINK_HREF_PROPERTY, Link, Link.href.key, ), ( "when_manifest_link_does_not_contain_reading_order_sub_collection", RWPM_MANIFEST_WITH_MISSING_READING_ORDER, RWPMManifest, RWPMManifest.reading_order.key, ), ]) def test_syntax_analyzer_raises_missing_property_error_correctly( self, _, rwpm_manifest_content, expected_class_with_missing_property, expected_missing_property, ): # Arrange syntax_analyzer = RWPMSyntaxAnalyzer() input_steam = six.StringIO(rwpm_manifest_content) manifest_json = DocumentParser.get_manifest_json(input_steam) # Act with self.assertRaises(MissingPropertyError) as assert_raises_context: syntax_analyzer.analyze(manifest_json) # Assert self.assertEqual( expected_class_with_missing_property, assert_raises_context.exception.cls, ) self.assertEqual( expected_missing_property, assert_raises_context.exception.object_property.key, ) @parameterized.expand([ ( "when_manifest_context_has_duplicated_items", RWPM_MANIFEST_WINT_INCORRECT_CONTEXT, "Item 'context1' is not unique", ), ( "when_metadata_modified_property_has_incorrect_format", RWPM_MANIFEST_WITH_INCORRECT_METADATA_MODIFIED_PROPERTY, "'2015-09-29T17:00:00Z---' is not a 'date-time'", ), ( "when_metadata_modified_language_has_incorrect_format", RWPM_MANIFEST_WITH_INCORRECT_METADATA_LANGUAGE_PROPERTY, "String value 'eng;dat' does not match regular expression ^((?P<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?P<language>([A-Za-z]{2,3}(-(?P<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?P<script>[A-Za-z]{4}))?(-(?P<region>[A-Za-z]{2}|[0-9]{3}))?(-(?P<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?P<extension>[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?P<privateUse>x(-[A-Za-z0-9]{1,8})+))?)|(?P<privateUse2>x(-[A-Za-z0-9]{1,8})+))$", ), ( "when_contributor_identifier_has_incorrect_format", RWPM_MANIFEST_WITH_INCORRECT_CONTRIBUTOR_IDENTIFIER_PROPERTY, "'x' is not a 'uri'", ), ( "when_link_height_less_or_equal_than_the_exclusive_minimum", RWPM_MANIFEST_WITH_INCORRECT_LINK_HEIGHT_PROPERTY, "Value -10 is less or equal than the exclusive minimum (0)", ), ]) def test_syntax_analyzer_raises_value_parsing_error_when_property_has_incorrect_value( self, _, rwpm_manifest_content, expected_error_message): # Arrange syntax_analyzer = RWPMSyntaxAnalyzer() input_steam = six.StringIO(rwpm_manifest_content) manifest_json = DocumentParser.get_manifest_json(input_steam) # Act with self.assertRaises(ValueParsingError) as assert_raises_context: syntax_analyzer.analyze(manifest_json) # Assert self.assertEqual( expected_error_message, six.text_type(assert_raises_context.exception).strip("u"), ) @parameterized.expand([ ( "when_manifest_has_author_encoded_as_string", RWPM_MANIFEST_WITH_AUTHOR_ENCODED_AS_STRING, [Contributor(name="Herman Melville", roles=[], links=LinkList())], ), ( "when_manifest_has_authors_encoded_as_array_of_strings", RWPM_MANIFEST_WITH_AUTHORS_ENCODED_AS_ARRAY_OF_STRINGS, [ Contributor(name="Herman Melville 1", roles=[], links=LinkList()), Contributor(name="Herman Melville 2", roles=[], links=LinkList()), ], ), ( "when_manifest_has_author_encoded_as_object", RWPM_MANIFEST_WITH_AUTHOR_ENCODED_AS_OBJECT, [Contributor(name="Herman Melville", roles=[], links=LinkList())], ), ( "when_manifest_has_authors_encoded_as_array_of_objects", RWPM_MANIFEST_WITH_AUTHORS_ENCODED_AS_ARRAY_OF_OBJECTS, [ Contributor(name="Herman Melville 1", roles=[], links=LinkList()), Contributor(name="Herman Melville 2", roles=[], links=LinkList()), ], ), ( "when_manifest_has_authors_encoded_as_mixed_array_of_strings_and_objects", RWPM_MANIFEST_WITH_AUTHORS_ENCODED_AS_MIXED_ARRAY_OF_STRINGS_AND_OBJECTS, [ Contributor(name="Herman Melville 1", roles=[], links=LinkList()), Contributor(name="Herman Melville 2", roles=[], links=LinkList()), ], ), ]) def test_syntax_analyzer_correctly_parses_contributor_metadata_as_contributor_objects( self, _, rwpm_manifest_content, expected_authors): # Arrange syntax_analyzer = RWPMSyntaxAnalyzer() input_steam = six.StringIO(rwpm_manifest_content) manifest_json = DocumentParser.get_manifest_json(input_steam) # Act manifest = syntax_analyzer.analyze(manifest_json) # Assert self.assertEqual(expected_authors, manifest.metadata.authors) def test_syntax_analyzer_returns_ast(self): # Arrange syntax_analyzer = RWPMSyntaxAnalyzer() input_steam = six.StringIO(RWPM_MANIFEST) manifest_json = DocumentParser.get_manifest_json(input_steam) # Act manifest = syntax_analyzer.analyze(manifest_json) # Assert self.assertIsInstance(manifest, RWPMManifest) self.assertIsInstance(manifest.context, list) self.assertEqual(1, len(manifest.context)) [context] = manifest.context self.assertEqual(context, "https://readium.org/webpub-manifest/context.jsonld") self.assertIsInstance(manifest.metadata, Metadata) self.assertEqual("http://schema.org/Book", manifest.metadata.type) self.assertEqual("Moby-Dick", manifest.metadata.title) self.assertEqual( [Contributor(name="Herman Melville", roles=[], links=LinkList())], manifest.metadata.authors, ) self.assertEqual("urn:isbn:978031600000X", manifest.metadata.identifier) self.assertEqual(["en"], manifest.metadata.languages) self.assertEqual(datetime.datetime(2015, 9, 29, 17, 0, 0), manifest.metadata.modified) self.assertIsInstance(manifest.links, list) self.assertEqual(1, len(manifest.links)) [link] = manifest.links self.assertIsInstance(link.rels, list) self.assertEqual(1, len(link.rels)) self.assertEqual(RWPMLinkRelationsRegistry.SELF.key, link.rels[0]) self.assertEqual("https://example.com/manifest.json", link.href) self.assertEqual(RWPMMediaTypesRegistry.MANIFEST.key, link.type) self.assertIsInstance(manifest.reading_order, CompactCollection) self.assertIsInstance(manifest.reading_order.links, list) self.assertEqual(1, len(manifest.reading_order.links)) [reading_order_link] = manifest.reading_order.links self.assertEqual("https://example.com/c001.html", reading_order_link.href) self.assertEqual(RWPMMediaTypesRegistry.HTML.key, reading_order_link.type) self.assertEqual("Chapter 1", reading_order_link.title)
"Expected error for {0} node's property '{1}' with error message \"{2}\" wasn't raised".format( expected_error.node.__class__, expected_error.node_property.key if expected_error.node_property else "", expected_error.error_message, ) ) MANIFEST = Manifestlike( metadata=PresentationMetadata(title="Manifest # 1"), links=LinkList( [ Link( href="http://example.com", rels=["test"], ) ] ), ) RWPM_MANIFEST = RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList( [ Link( href="example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ] ),
class SemanticAnalyzerTest(TestCase): @parameterized.expand([ ( "when_feed_does_not_contain_neither_publications_nor_navigation_nor_groups", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), ), MISSING_REQUIRED_FEED_SUB_COLLECTIONS, ), ( "when_navigation_link_does_not_contain_title", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), navigation=OPDS2Navigation( links=LinkList([Link(href="http://example.com")])), ), MISSING_NAVIGATION_LINK_TITLE_ERROR, ), ( "when_publication_does_not_contain_acquisition_link", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([Link(href="http://example.com")]), ) ]), ), MISSING_ACQUISITION_LINK, ), ( "when_navigation_contains_both_links_and_publications", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), groups=CollectionList([ OPDS2Group( navigation=OPDS2Navigation(links=LinkList([ Link( href="http://example.com", rels=["current"], ) ])), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata( title="Publication 1"), links=LinkList( [Link(href="http://example.com")]), ) ]), ) ]), ), WRONG_GROUP_STRUCTURE, ), ]) def test_semantic_analyzer_raises_error(self, _, manifest, expected_error): # Arrange media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = OPDS2SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act with assert_raises(expected_error.__class__) as assert_raises_context: semantic_analyzer.visit(manifest) # Assert eq_(str(assert_raises_context.exception), str(expected_error)) def test_semantic_analyzer_does_correctly_processes_valid_ast(self): # Arrange feed = OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([ Link( href="http://example.com", rels=[OPDS2LinkRelationsRegistry.ACQUISITION.key], ) ]), ) ]), navigation=OPDS2Navigation(links=LinkList([ Link( href="/new", title="New Publications", _type=OPDS2MediaTypesRegistry.OPDS_FEED, rels=["current"], ) ])), groups=CollectionList([ OPDS2Group( metadata=OPDS2FeedMetadata(title="Group 1"), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata( title="Publication 1.1"), links=LinkList([ Link( href="http://example.com", rels=[ OPDS2LinkRelationsRegistry.ACQUISITION. key ], ) ]), ) ]), ) ]), ) media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = OPDS2SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) semantic_analyzer.visit = MagicMock( side_effect=semantic_analyzer.visit) # Act semantic_analyzer.visit(feed) # Assert semantic_analyzer.visit.assert_has_calls( calls=[ call(feed), call(feed.metadata), call(feed.links), call(feed.links[0]), call(feed.sub_collections), call(feed.publications), call(feed.publications[0]), call(feed.publications[0].metadata), call(feed.publications[0].links), call(feed.publications[0].links[0]), call(feed.publications[0].sub_collections), call(feed.navigation), call(feed.navigation), call(feed.navigation.links), call(feed.navigation.links[0]), call(feed.groups), call(feed.groups[0]), call(feed.groups[0].metadata), call(feed.groups[0].publications), call(feed.groups[0].publications[0]), call(feed.groups[0].publications[0].metadata), call(feed.groups[0].publications[0].links), call(feed.groups[0].publications[0].links[0]), ], any_order=False, )
def test_semantic_analyzer_does_correctly_processes_valid_ast(self): # Arrange feed = OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([ Link( href="http://example.com", rels=[OPDS2LinkRelationsRegistry.ACQUISITION.key], ) ]), ) ]), navigation=OPDS2Navigation(links=LinkList([ Link( href="/new", title="New Publications", _type=OPDS2MediaTypesRegistry.OPDS_FEED, rels=["current"], ) ])), groups=CollectionList([ OPDS2Group( metadata=OPDS2FeedMetadata(title="Group 1"), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata( title="Publication 1.1"), links=LinkList([ Link( href="http://example.com", rels=[ OPDS2LinkRelationsRegistry.ACQUISITION. key ], ) ]), ) ]), ) ]), ) media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = OPDS2SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) semantic_analyzer.visit = MagicMock( side_effect=semantic_analyzer.visit) # Act semantic_analyzer.visit(feed) # Assert semantic_analyzer.visit.assert_has_calls( calls=[ call(feed), call(feed.metadata), call(feed.links), call(feed.links[0]), call(feed.sub_collections), call(feed.publications), call(feed.publications[0]), call(feed.publications[0].metadata), call(feed.publications[0].links), call(feed.publications[0].links[0]), call(feed.publications[0].sub_collections), call(feed.navigation), call(feed.navigation), call(feed.navigation.links), call(feed.navigation.links[0]), call(feed.groups), call(feed.groups[0]), call(feed.groups[0].metadata), call(feed.groups[0].publications), call(feed.groups[0].publications[0]), call(feed.groups[0].publications[0].metadata), call(feed.groups[0].publications[0].links), call(feed.groups[0].publications[0].links[0]), ], any_order=False, )
class SemanticAnalyzerTest(TestCase): @parameterized.expand([ ( "when_reading_order_link_does_not_have_type_property", RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), ), MISSING_READING_ORDER_LINK_TYPE_PROPERTY_ERROR, ), ( "when_resources_link_does_not_have_type_property", RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key) ]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), ), MISSING_RESOURCES_LINK_TYPE_PROPERTY_ERROR, ), ]) def test_semantic_analyzer_raises_error(self, _, manifest, expected_error): # Arrange media_types_registry = RWPMMediaTypesRegistry() link_relations_registry = RWPMLinkRelationsRegistry() collection_roles_registry = RWPMCollectionRolesRegistry() semantic_analyzer = RWPMSemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act with assert_raises(expected_error.__class__) as assert_raises_context: semantic_analyzer.visit(manifest) # Assert eq_(str(assert_raises_context.exception), str(expected_error)) def test_semantic_analyzer_does_correctly_processes_valid_ast(self): manifest = RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), ) media_types_registry = RWPMMediaTypesRegistry() link_relations_registry = RWPMLinkRelationsRegistry() collection_roles_registry = RWPMCollectionRolesRegistry() semantic_analyzer = RWPMSemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest)
def test(self): # Arrange parser_factory = OPDS2FeedParserFactory() parser = parser_factory.create() input_file_path = os.path.join(os.path.dirname(__file__), "../../files/opds2/feed.json") # Act result = parser.parse_file(input_file_path) # Assert self.assertIsInstance(result, ManifestParserResult) self.assertEqual(0, len(result.errors)) feed = result.root self.assertIsInstance(feed, OPDS2Feed) self.assertIsInstance(feed.metadata, OPDS2FeedMetadata) self.assertEqual("Example listing publications", feed.metadata.title) self.assertIsInstance(feed.links, list) self.assertEqual(1, len(feed.links)) [manifest_link] = feed.links self.assertEqual(OPDS2LinkRelationsRegistry.SELF.key, manifest_link.rels[0]) self.assertEqual("http://example.com/new", manifest_link.href) self.assertEqual(OPDS2MediaTypesRegistry.OPDS_FEED.key, manifest_link.type) self.assertIsInstance(feed.publications, list) self.assertEqual(2, len(feed.publications)) publication = feed.publications[0] self.assertIsInstance(publication.metadata, PresentationMetadata) self.assertEqual("http://schema.org/Book", publication.metadata.type) self.assertEqual("Moby-Dick", publication.metadata.title) self.assertEqual( [Contributor(name="Herman Melville", roles=[], links=LinkList())], publication.metadata.authors, ) self.assertEqual("urn:isbn:978-3-16-148410-0", publication.metadata.identifier) self.assertEqual(["en"], publication.metadata.languages) self.assertEqual( datetime.datetime(2015, 9, 29, 17, 0, tzinfo=tzutc()), publication.metadata.modified, ) self.assertIsInstance(publication.links, list) self.assertEqual(len(publication.links), 2) publication_self_link = first_or_default( publication.links.get_by_rel(OPDS2LinkRelationsRegistry.SELF.key)) self.assertEqual(OPDS2LinkRelationsRegistry.SELF.key, publication_self_link.rels[0]) self.assertEqual("http://example.org/publication.json", publication_self_link.href) self.assertEqual(OPDS2MediaTypesRegistry.OPDS_PUBLICATION.key, publication_self_link.type) publication_acquisition_link = first_or_default( publication.links.get_by_rel( OPDS2LinkRelationsRegistry.OPEN_ACCESS.key)) self.assertEqual( OPDS2LinkRelationsRegistry.OPEN_ACCESS.key, publication_acquisition_link.rels[0], ) self.assertEqual("http://example.org/file.epub", publication_acquisition_link.href) self.assertEqual( OPDS2MediaTypesRegistry.EPUB_PUBLICATION_PACKAGE.key, publication_acquisition_link.type, ) self.assertIsInstance(publication.images, CompactCollection) self.assertIsInstance(publication.images.links, list) self.assertEqual(3, len(publication.images.links)) jpeg_cover_link = first_or_default( publication.images.links.get_by_href( "http://example.org/cover.jpg")) self.assertEqual([], jpeg_cover_link.rels) self.assertEqual("http://example.org/cover.jpg", jpeg_cover_link.href) self.assertEqual(OPDS2MediaTypesRegistry.JPEG.key, jpeg_cover_link.type) self.assertEqual(1400, jpeg_cover_link.height) self.assertEqual(800, jpeg_cover_link.width) small_jpeg_cover_link = first_or_default( publication.images.links.get_by_href( "http://example.org/cover-small.jpg")) self.assertEqual("http://example.org/cover-small.jpg", small_jpeg_cover_link.href) self.assertEqual(OPDS2MediaTypesRegistry.JPEG.key, small_jpeg_cover_link.type) self.assertEqual(700, small_jpeg_cover_link.height) self.assertEqual(400, small_jpeg_cover_link.width) svg_cover_link = first_or_default( publication.images.links.get_by_href( "http://example.org/cover.svg")) self.assertEqual(svg_cover_link.href, "http://example.org/cover.svg") self.assertEqual(svg_cover_link.type, OPDS2MediaTypesRegistry.SVG_XML.key) publication = feed.publications[1] self.assertIsInstance(publication.metadata, PresentationMetadata) self.assertEqual("http://schema.org/Book", publication.metadata.type) self.assertEqual("Adventures of Huckleberry Finn", publication.metadata.title) self.assertEqual( [ Contributor(name="Mark Twain", roles=[], links=LinkList()), Contributor(name="Samuel Langhorne Clemens", roles=[], links=LinkList()), ], publication.metadata.authors, ) self.assertEqual("urn:isbn:978-3-16-148410-0", publication.metadata.identifier) self.assertEqual(["eng", "fre"], publication.metadata.languages) self.assertEqual( datetime.datetime(2015, 9, 29, 0, 0, tzinfo=tzutc()), publication.metadata.published, ) self.assertEqual( datetime.datetime(2015, 9, 29, 17, 0, 0, tzinfo=tzutc()), publication.metadata.modified, ) self.assertIsInstance(publication.links, list) publication_acquisition_link = first_or_default( publication.links.get_by_rel( OPDS2LinkRelationsRegistry.BORROW.key)) self.assertEqual(OPDS2LinkRelationsRegistry.BORROW.key, publication_acquisition_link.rels[0]) self.assertEqual( OPDS2MediaTypesRegistry.OPDS_PUBLICATION.key, publication_acquisition_link.type, ) link_properties = publication_acquisition_link.properties self.assertIsInstance(link_properties, OPDS2LinkProperties) self.assertEqual(OPDS2AvailabilityType.AVAILABLE.value, link_properties.availability.state) self.assertEqual(2, len(link_properties.indirect_acquisition)) indirect_acquisition_object = link_properties.indirect_acquisition[0] self.assertEqual("application/vnd.adobe.adept+xml", indirect_acquisition_object.type) self.assertEqual(1, len(indirect_acquisition_object.child)) self.assertIsInstance(indirect_acquisition_object.child[0], OPDS2AcquisitionObject) self.assertEqual("application/epub+zip", indirect_acquisition_object.child[0].type) indirect_acquisition_object = link_properties.indirect_acquisition[1] self.assertEqual( "application/vnd.readium.lcp.license.v1.0+json", indirect_acquisition_object.type, ) self.assertEqual(1, len(indirect_acquisition_object.child)) self.assertIsInstance(indirect_acquisition_object.child[0], OPDS2AcquisitionObject) self.assertEqual("application/epub+zip", indirect_acquisition_object.child[0].type)
class RWPMSemanticAnalyzerTest(AnalyzerTest): @parameterized.expand([ ( "when_reading_order_link_does_not_have_type_property", RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), ), [ READING_ORDER_SUBCOLLECTION_LINK_MISSING_TYPE_PROPERTY_ERROR( node=Link(href="test"), node_property=Link.type) ], ), ( "when_resources_link_does_not_have_type_property", RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key) ]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), ), [ RESOURCES_SUBCOLLECTION_MISSING_LINK_TYPE_PROPERTY_ERROR( node=Link(href="test"), node_property=Link.type) ], ), ( "when_reading_order_and_resource_links_do_not_have_type_property_and_self_link_has_incorrect_href", RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([Link(href="test")]), ), ), [ MANIFEST_SELF_LINK_WRONG_HREF_FORMAT_ERROR( node=Link(href="example.com"), node_property=Link.href), READING_ORDER_SUBCOLLECTION_LINK_MISSING_TYPE_PROPERTY_ERROR( node=Link(href="test"), node_property=Link.type), RESOURCES_SUBCOLLECTION_MISSING_LINK_TYPE_PROPERTY_ERROR( node=Link(href="test"), node_property=Link.type), ], ), ]) def test_semantic_analyzer_raises_error(self, _, manifest, expected_errors): """Ensure that the base semantic analyzer correctly raises errors and saves them in the current context. :param manifest: AST object containing the RWPM-like manifest :type manifest: webpub_manifest_parser.core.ast.Node :param expected_errors: List of expected semantic errors :type expected_errors: List[webpub_manifest_parser.core.analyzer.BaseAnalyzerError] """ # Arrange media_types_registry = RWPMMediaTypesRegistry() link_relations_registry = RWPMLinkRelationsRegistry() collection_roles_registry = RWPMCollectionRolesRegistry() semantic_analyzer = RWPMSemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest) # Assert self.check_analyzer_errors(semantic_analyzer.context.errors, expected_errors, SemanticAnalyzerError) def test_semantic_analyzer_does_correctly_processes_valid_ast(self): manifest = RWPMManifest( metadata=PresentationMetadata("test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), reading_order=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), resources=CompactCollection( role=RWPMCollectionRolesRegistry.READING_ORDER.key, links=LinkList([ Link(href="test", _type=RWPMMediaTypesRegistry.JPEG.key), ]), ), ) media_types_registry = RWPMMediaTypesRegistry() link_relations_registry = RWPMLinkRelationsRegistry() collection_roles_registry = RWPMCollectionRolesRegistry() semantic_analyzer = RWPMSemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest)
result[property_object.key] = property_value elif isinstance(rwpm_item, RegistryItem): result = rwpm_item.key return result PROQUEST_PUBLICATION_1 = OPDS2Publication( metadata=PresentationMetadata( identifier="urn:proquest.com/document-id/1", title="Publićation # 1", modified=datetime_utc(2020, 1, 31, 0, 0, 0), ), links=LinkList([ Link( href="https://feed.org/document-id/1", rels=[OPDS2LinkRelationsRegistry.ACQUISITION], ) ]), ) PROQUEST_PUBLICATION_2 = OPDS2Publication( metadata=PresentationMetadata( identifier="urn:proquest.com/document-id/2", title="Publication # 2", modified=datetime_utc(2020, 1, 30, 0, 0, 0), ), links=LinkList([ Link( href="https://feed.org/document-id/2", rels=[OPDS2LinkRelationsRegistry.ACQUISITION], )
class OPDS2SemanticAnalyzerTest(AnalyzerTest): @parameterized.expand([ ( "when_feed_does_not_contain_neither_publications_nor_navigation_nor_groups", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), ), [ MISSING_REQUIRED_FEED_SUB_COLLECTIONS(node=OPDS2Feed(), node_property=None) ], ), ( "when_navigation_link_does_not_contain_title", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), navigation=OPDS2Navigation( links=LinkList([Link(href="http://example.com")])), ), [ MISSING_NAVIGATION_LINK_TITLE_ERROR(node=Link(), node_property=Link.title) ], ), ( "when_publication_does_not_contain_acquisition_link", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([Link(href="http://example.com")]), ) ]), ), [ MISSING_ACQUISITION_LINK(node=OPDS2Publication(), node_property=None) ], ), ( "when_navigation_contains_both_links_and_publications", OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), groups=CollectionList([ OPDS2Group( navigation=OPDS2Navigation(links=LinkList([ Link( href="http://example.com", rels=["current"], ) ])), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata( title="Publication 1"), links=LinkList( [Link(href="http://example.com")]), ) ]), ) ]), ), [ WRONG_GROUP_STRUCTURE(node=OPDS2Group(), node_property=None), MISSING_ACQUISITION_LINK(node=OPDS2Publication(), node_property=None), MISSING_NAVIGATION_LINK_TITLE_ERROR(node=Link(), node_property=Link.title), ], ), ]) def test_semantic_analyzer_raises_error(self, _, manifest, expected_errors): """Ensure that the OPDS 2.x semantic analyzer correctly raises errors and saves them in the current context. :param manifest: AST object containing the RWPM-like manifest :type manifest: webpub_manifest_parser.core.ast.Node :param expected_errors: List of expected semantic errors :type expected_errors: List[webpub_manifest_parser.core.analyzer.BaseAnalyzerError] """ # Arrange media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = OPDS2SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest) # Assert self.check_analyzer_errors(semantic_analyzer.context.errors, expected_errors, SemanticAnalyzerError) def test_semantic_analyzer_does_correctly_processes_valid_ast(self): # Arrange feed = OPDS2Feed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList([ Link( href="http://example.com", rels=[RWPMLinkRelationsRegistry.SELF.key], ) ]), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([ Link( href="http://example.com", rels=[OPDS2LinkRelationsRegistry.ACQUISITION.key], ) ]), ) ]), navigation=OPDS2Navigation(links=LinkList([ Link( href="/new", title="New Publications", _type=OPDS2MediaTypesRegistry.OPDS_FEED, rels=["current"], ) ])), groups=CollectionList([ OPDS2Group( metadata=OPDS2FeedMetadata(title="Group 1"), publications=CollectionList([ OPDS2Publication( metadata=PresentationMetadata( title="Publication 1.1"), links=LinkList([ Link( href="http://example.com", rels=[ OPDS2LinkRelationsRegistry.ACQUISITION. key ], ) ]), ) ]), ) ]), ) media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = OPDS2SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) semantic_analyzer.visit = MagicMock( side_effect=semantic_analyzer.visit) # Act semantic_analyzer.visit(feed) # Assert semantic_analyzer.visit.assert_has_calls( calls=[ call(feed), call(feed.metadata), call(feed.links), call(feed.links[0]), call(feed.sub_collections), call(feed.publications), call(feed.publications[0]), call(feed.publications[0].metadata), call(feed.publications[0].links), call(feed.publications[0].links[0]), call(feed.publications[0].sub_collections), call(feed.navigation), call(feed.navigation), call(feed.navigation.links), call(feed.navigation.links[0]), call(feed.groups), call(feed.groups[0]), call(feed.groups[0].metadata), call(feed.groups[0].publications), call(feed.groups[0].publications[0]), call(feed.groups[0].publications[0].metadata), call(feed.groups[0].publications[0].links), call(feed.groups[0].publications[0].links[0]), ], any_order=False, )
def test(self): # Arrange parser_factory = RWPMDocumentParserFactory() parser = parser_factory.create() input_file_path = os.path.join( os.path.dirname(__file__), "../../files/rwpm/spec_example.json" ) # Act manifest = parser.parse_file(input_file_path) # Assert self.assertIsInstance(manifest.context, list) self.assertEqual(1, len(manifest.context)) [context] = manifest.context self.assertEqual(context, "https://readium.org/webpub-manifest/context.jsonld") self.assertIsInstance(manifest.metadata, Metadata) self.assertEqual("http://schema.org/Book", manifest.metadata.type) self.assertEqual("Moby-Dick", manifest.metadata.title) self.assertEqual( [Contributor(name="Herman Melville", roles=[], links=LinkList())], manifest.metadata.authors, ) self.assertEqual("urn:isbn:978031600000X", manifest.metadata.identifier) self.assertEqual(["en"], manifest.metadata.languages) self.assertEqual( datetime.datetime(2015, 9, 29, 17, 0, 0), manifest.metadata.modified ) self.assertIsInstance(manifest.links, list) self.assertEqual(3, len(manifest.links)) self_link = first_or_default( manifest.links.get_by_rel(RWPMLinkRelationsRegistry.SELF.key) ) self.assertIsNotNone(self_link) self.assertIn(RWPMLinkRelationsRegistry.SELF.key, self_link.rels) self.assertEqual("https://example.com/manifest.json", self_link.href) self.assertEqual(RWPMMediaTypesRegistry.MANIFEST.key, self_link.type) alternate_link = first_or_default( manifest.links.get_by_rel(RWPMLinkRelationsRegistry.ALTERNATE.key) ) self.assertIsNotNone(alternate_link) self.assertIn(RWPMLinkRelationsRegistry.ALTERNATE.key, alternate_link.rels) self.assertEqual("https://example.com/publication.epub", alternate_link.href) self.assertEqual( RWPMMediaTypesRegistry.EPUB_PUBLICATION_PACKAGE.key, alternate_link.type ) search_link = first_or_default( manifest.links.get_by_rel(RWPMLinkRelationsRegistry.SEARCH.key) ) self.assertIsNotNone(search_link) self.assertIn(RWPMLinkRelationsRegistry.SEARCH.key, search_link.rels) self.assertEqual("https://example.com/search{?query}", search_link.href) self.assertEqual(RWPMMediaTypesRegistry.HTML.key, search_link.type) self.assertIsInstance(manifest.reading_order, CompactCollection) self.assertIsInstance(manifest.reading_order.links, list) self.assertEqual(2, len(manifest.reading_order.links)) reading_order_link = manifest.reading_order.links[0] self.assertEqual("https://example.com/c001.html", reading_order_link.href) self.assertEqual(RWPMMediaTypesRegistry.HTML.key, reading_order_link.type) self.assertEqual("Chapter 1", reading_order_link.title) reading_order_link = manifest.reading_order.links[1] self.assertEqual("https://example.com/c002.html", reading_order_link.href) self.assertEqual(RWPMMediaTypesRegistry.HTML.key, reading_order_link.type) self.assertEqual("Chapter 2", reading_order_link.title) resources_sub_collection = manifest.resources self.assertEqual(5, len(resources_sub_collection.links)) self.assertEqual( [RWPMLinkRelationsRegistry.COVER.key], resources_sub_collection.links[0].rels, ) self.assertEqual( "https://example.com/cover.jpg", resources_sub_collection.links[0].href ) self.assertEqual( RWPMMediaTypesRegistry.JPEG.key, resources_sub_collection.links[0].type ) self.assertEqual(600, resources_sub_collection.links[0].height) self.assertEqual(400, resources_sub_collection.links[0].width) self.assertEqual( "https://example.com/style.css", resources_sub_collection.links[1].href ) self.assertEqual( RWPMMediaTypesRegistry.CSS.key, resources_sub_collection.links[1].type ) self.assertEqual( "https://example.com/whale.jpg", resources_sub_collection.links[2].href ) self.assertEqual( RWPMMediaTypesRegistry.JPEG.key, resources_sub_collection.links[2].type ) self.assertEqual( "https://example.com/boat.svg", resources_sub_collection.links[3].href ) self.assertEqual( RWPMMediaTypesRegistry.SVG_XML.key, resources_sub_collection.links[3].type ) self.assertEqual( "https://example.com/notes.html", resources_sub_collection.links[4].href ) self.assertEqual( RWPMMediaTypesRegistry.HTML.key, resources_sub_collection.links[4].type )
class ODLSemanticAnalyzerTest(AnalyzerTest): @parameterized.expand( [ ( "when_feed_does_not_contain_publications", ODLFeed(metadata=OPDS2FeedMetadata(title="test"), links=LinkList()), [ ODL_FEED_MISSING_PUBLICATIONS_SUBCOLLECTION_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.publications, ), MANIFEST_MISSING_SELF_LINK_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=None, ), ], ), ( "when_feed_contains_groups", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList(), groups=CollectionList([OPDS2Group()]), ), [ ODL_FEED_MISSING_PUBLICATIONS_SUBCOLLECTION_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.publications, ), MANIFEST_MISSING_SELF_LINK_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=None, ), ODL_FEED_CONTAINS_REDUNDANT_GROUPS_SUBCOLLECTIONS_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.groups, ), ], ), ( "when_feed_contains_facets", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList(), facets=CollectionList([OPDS2Facet()]), ), [ ODL_FEED_MISSING_PUBLICATIONS_SUBCOLLECTION_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.publications, ), MANIFEST_MISSING_SELF_LINK_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=None, ), ODL_FEED_CONTAINS_REDUNDANT_FACETS_SUBCOLLECTIONS_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.facets, ), ], ), ( "when_feed_contains_navigation", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList(), navigation=OPDS2Navigation(), ), [ ODL_FEED_MISSING_PUBLICATIONS_SUBCOLLECTION_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.publications, ), MANIFEST_MISSING_SELF_LINK_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=None, ), ODL_FEED_CONTAINS_REDUNDANT_NAVIGATION_SUBCOLLECTION_ERROR( node=ODLFeed(metadata=OPDS2FeedMetadata(title="test")), node_property=ODLFeed.navigation, ), ], ), ( "when_publication_does_not_contain_neither_licenses_nor_oa_link", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList( [ Link( href="http://example.com", rels=[LinkRelationsRegistry.SELF.key], ) ] ), publications=CollectionList( [ ODLPublication( metadata=PresentationMetadata(title="Publication 1"), licenses=CollectionList(), ) ] ), ), [ ODL_PUBLICATION_MUST_CONTAIN_EITHER_LICENSES_OR_OA_ACQUISITION_LINK_ERROR( node=ODLPublication( metadata=PresentationMetadata(title="Publication 1") ), node_property=None, ) ], ), ( "when_publication_does_not_contain_neither_licenses_nor_oa_link", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList( [ Link( href="http://example.com", rels=[LinkRelationsRegistry.SELF.key], ) ] ), publications=CollectionList( [ ODLPublication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([Link(href="http://example.com")]), ) ] ), ), [ ODL_PUBLICATION_MUST_CONTAIN_EITHER_LICENSES_OR_OA_ACQUISITION_LINK_ERROR( node=ODLPublication( metadata=PresentationMetadata(title="Publication 1") ), node_property=None, ) ], ), ( "when_license_does_not_contain_self_link_and_borrow_link", ODLFeed( metadata=OPDS2FeedMetadata(title="test"), links=LinkList( [ Link( href="http://example.com", rels=[LinkRelationsRegistry.SELF.key], ) ] ), publications=CollectionList( [ ODLPublication( metadata=PresentationMetadata(title="Publication 1"), links=LinkList([Link(href="http://example.com")]), licenses=CollectionList( [ ODLLicense( metadata=ODLLicenseMetadata( identifier="license-1", formats=["text/html"], created=datetime.datetime( 2021, 1, 1, 0, 0, 0 ), ) ) ] ), ) ] ), ), [ ODL_LICENSE_MUST_CONTAIN_SELF_LINK_TO_LICENSE_INFO_DOCUMENT_ERROR( node=ODLLicense( metadata=ODLLicenseMetadata(identifier="license-1") ), node_property=None, ), ODL_LICENSE_MUST_CONTAIN_CHECKOUT_LINK_TO_LICENSE_STATUS_DOCUMENT_ERROR( node=ODLLicense( metadata=ODLLicenseMetadata(identifier="license-1") ), node_property=None, ), ], ), ] ) def test_semantic_analyzer_raises_error(self, _, manifest, expected_errors): """Ensure that the ODL 2.x semantic analyzer correctly raises errors and saves them in the current context. :param manifest: AST object containing the RWPM-like manifest :type manifest: webpub_manifest_parser.odl.ast.ODLFeed :param expected_errors: List of expected semantic errors :type expected_errors: List[webpub_manifest_parser.core.analyzer.BaseAnalyzerError] """ # Arrange media_types_registry = OPDS2MediaTypesRegistry() link_relations_registry = OPDS2LinkRelationsRegistry() collection_roles_registry = OPDS2CollectionRolesRegistry() semantic_analyzer = ODLSemanticAnalyzer( media_types_registry, link_relations_registry, collection_roles_registry ) # Act semantic_analyzer.visit(manifest) # Assert self.check_analyzer_errors( semantic_analyzer.context.errors, expected_errors, SemanticAnalyzerError )
class SemanticAnalyzerTest(AnalyzerTest): @parameterized.expand([ ( "when_manifest_link_rel_property_is_missing", Manifestlike( metadata=PresentationMetadata(title="Manifest # 1"), links=LinkList([Link(href="http://example.com")]), ), [ MANIFEST_LINK_MISSING_REL_PROPERTY_ERROR( node=Link(href="http://example.com"), node_property=Link.rels), MANIFEST_MISSING_SELF_LINK_ERROR( node=Manifestlike(metadata=PresentationMetadata( identifier="Manifest # 1")), node_property=None, ), ], ), ( "when_manifest_self_link_is_missing", Manifestlike( metadata=PresentationMetadata(title="Manifest # 1"), links=LinkList( [Link( href="http://example.com", rels=["test"], )]), ), [ MANIFEST_MISSING_SELF_LINK_ERROR( node=Manifestlike(metadata=PresentationMetadata( title="Manifest # 1")), node_property=None, ) ], ), ( "when_manifest_self_link_has_wrong_href", Manifestlike( metadata=PresentationMetadata(title="Manifest # 1"), links=LinkList([ Link( href="example.com", rels=[LinkRelationsRegistry.SELF.key], ) ]), ), [ MANIFEST_SELF_LINK_WRONG_HREF_FORMAT_ERROR( node=Link(href="example.com"), node_property=Link.href) ], ), ( "when_manifest_link_rel_property_is_missing_and_self_link_has_incorrect_href", Manifestlike( metadata=PresentationMetadata(title="Manifest # 1"), links=LinkList([ Link(href="http://example.com"), Link( href="example.com", rels=[LinkRelationsRegistry.SELF.key], ), ]), ), [ MANIFEST_LINK_MISSING_REL_PROPERTY_ERROR( node=Link(href="http://example.com"), node_property=Link.rels), MANIFEST_SELF_LINK_WRONG_HREF_FORMAT_ERROR( node=Link(href="example.com"), node_property=Link.href), ], ), ]) def test_semantic_analyzer_raises_error(self, _, manifest, expected_errors): """Ensure that the base semantic analyzer correctly raises errors and saves them in the current context. :param manifest: AST object containing the RWPM-like manifest :type manifest: webpub_manifest_parser.core.ast.Manifestlike :param expected_errors: List of expected semantic errors :type expected_errors: List[webpub_manifest_parser.core.analyzer.BaseAnalyzerError] """ # Arrange media_types_registry = Registry() link_relations_registry = Registry() collection_roles_registry = Registry() semantic_analyzer = SemanticAnalyzer(media_types_registry, link_relations_registry, collection_roles_registry) # Act semantic_analyzer.visit(manifest) # Assert self.check_analyzer_errors(semantic_analyzer.context.errors, expected_errors, SemanticAnalyzerError)