示例#1
0
    def test_post_render_config_with_clean_urls(self):
        with TemporaryDirectory() as output_directory_path:
            configuration = Configuration(
                output_directory_path, 'http://example.com')
            configuration.plugins[Nginx] = {}
            configuration.clean_urls = True
            site = Site(configuration)
            render(site)
            expected = '''server {
	listen 80;
	server_name example.com;
	root %s;
	add_header Cache-Control "max-age=86400";
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_types text/css application/javascript application/json application/xml;

        set $content_type_extension html;
    index index.$content_type_extension;

        location / {
            # Handle HTTP error responses.
            error_page 401 /.error/401.$content_type_extension;
            error_page 403 /.error/403.$content_type_extension;
            error_page 404 /.error/404.$content_type_extension;
            location /.error {
                internal;
            }

            try_files $uri $uri/ =404;
        }
}''' % configuration.www_directory_path  # noqa: E101 W191
            with open(join(configuration.output_directory_path, 'nginx', 'nginx.conf')) as f:  # noqa: E101
                self.assertEquals(expected, f.read())
示例#2
0
 async def test_front_page(self):
     configuration = Configuration(self._output_directory.name,
                                   'https://ancestry.example.com')
     app = App(configuration)
     async with app:
         await generate(app)
     self.assert_betty_html(app, '/index.html')
示例#3
0
 async def _render(self, data: Optional[Dict] = None, template_file: Optional[Template] = None, template_string: Optional[str] = None, update_configuration: Optional[Callable[[Configuration], None]] = None) -> Tuple[str, Site]:
     if template_string is not None and template_file is not None:
         raise RuntimeError('You must define either `template_string` or `template_file`, but not both.')
     if template_string is not None:
         template = template_string
         template_factory = Environment.from_string
     elif template_file is not None:
         template = template_file
         template_factory = Environment.get_template
     elif self.template_string is not None:
         template = self.template_string
         template_factory = Environment.from_string
     elif self.template_file is not None:
         template = self.template_file
         template_factory = Environment.get_template
     else:
         class_name = self.__class__.__name__
         raise RuntimeError(f'You must define one of `template_string`, `template_file`, `{class_name}.template_string`, or `{class_name}.template_file`.')
     if data is None:
         data = {}
     with TemporaryDirectory() as output_directory_path:
         configuration = Configuration(output_directory_path, 'https://example.com')
         configuration.mode = 'development'
         if update_configuration is not None:
             update_configuration(configuration)
         async with Site(configuration) as site:
             rendered = await template_factory(site.jinja2_environment, template).render_async(**data)
             # We want to keep the site around, but we must make sure all dispatched tasks are done, so we shut down
             # the executor. Crude, but effective.
             site.executor.shutdown()
             yield rendered, site
示例#4
0
    async def test_post_parse(self):
        person = Person('P0')
        Presence(person, Subject(), Event(Birth()))

        source_file = File('F0', __file__)
        source = IdentifiableSource('S0', 'The Source')
        source.private = True
        source.files.append(source_file)

        citation_file = File('F0', __file__)
        citation_source = Source('The Source')
        citation = IdentifiableCitation('C0', citation_source)
        citation.private = True
        citation.files.append(citation_file)

        with TemporaryDirectory() as output_directory_path:
            configuration = Configuration(output_directory_path,
                                          'https://example.com')
            configuration.plugins[Privatizer] = None
            async with Site(configuration) as site:
                site.ancestry.people[person.id] = person
                site.ancestry.sources[source.id] = source
                site.ancestry.citations[citation.id] = citation
                await parse(site)

            self.assertTrue(person.private)
            self.assertTrue(source_file.private)
            self.assertTrue(citation_file.private)
示例#5
0
 def test_with_one_plugin(self):
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.plugins[NonConfigurablePlugin] = {}
     sut = Site(configuration)
     self.assertEquals(1, len(sut.plugins))
     self.assertIsInstance(
         sut.plugins[NonConfigurablePlugin], NonConfigurablePlugin)
示例#6
0
 def test_with_unknown_plugin_class(self):
     with TemporaryDirectory() as www_directory_path:
         environment = create_environment(
             Site(Configuration(www_directory_path, 'https://example.com')))
         template = '{% if "betty.UnknownPlugin" in plugins %}true{% else %}false{% endif %}'
         self.assertEquals('false',
                           environment.from_string(template).render())
示例#7
0
    async def test_populate_should_populate_existing_link(self,
                                                          m_retriever) -> None:
        entry_language = 'en'
        entry_name = 'Amsterdam'
        entry_title = 'Amsterdam'
        entry_content = 'Capitol of the Netherlands'
        entry = Entry(entry_language, entry_name, entry_title, entry_content)
        m_retriever.get_entry.return_value = entry

        resource = IdentifiableSource('the_source', 'The Source')
        link = Link('https://en.wikipedia.org/wiki/Amsterdam')
        resource.links.add(link)
        with TemporaryDirectory() as output_directory_path:
            with TemporaryDirectory() as cache_directory_path:
                configuration = Configuration(output_directory_path,
                                              'https://example.com')
                configuration.cache_directory_path = cache_directory_path
                async with Site(configuration) as site:
                    site.ancestry.sources[resource.id] = resource
                    sut = _Populator(site, m_retriever)
                    await sut.populate()
        m_retriever.get_entry.assert_called_once_with(entry_language,
                                                      entry_name)
        self.assertEqual(1, len(resource.links))
        self.assertEqual('Amsterdam', link.label)
        self.assertEqual('en', link.locale)
        self.assertEqual(MediaType('text/html'), link.media_type)
        self.assertIsNotNone(link.description)
        self.assertEqual('external', link.relationship)
示例#8
0
 def test_output_directory_path_with_relative_path(self):
     output_directory_path = './betty'
     sut = Configuration(output_directory_path, 'https://example.com')
     site_directory_path = '/tmp/betty-working-directory'
     sut.site_directory_path = site_directory_path
     self.assertEquals('/tmp/betty-working-directory/betty',
                       sut.output_directory_path)
示例#9
0
 def test_resources_with_resources_directory_path(self):
     resources_directory_path = '/tmp/betty'
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.resources_directory_path = resources_directory_path
     sut = Site(configuration)
     self.assertEquals(2, len(sut.resources.paths))
     self.assertEquals(resources_directory_path, sut.resources.paths[0])
示例#10
0
    def setUpClass(cls):
        cls._outputDirectory = TemporaryDirectory()
        configuration = Configuration(cls._outputDirectory.name,
                                      'https://ancestry.example.com')
        cls.site = Site(configuration)

        place1 = Place('PLACE1', 'one')

        event1 = Event('EVENT1', Event.Type.BIRTH)
        event1.place = place1

        event1_person_1_presence = Presence(Presence.Role.SUBJECT)
        event1_person_1_presence.event = event1

        person1 = Person('PERSON1', 'Janet', 'Dough')
        person1.presences.add(event1_person_1_presence)

        source1 = Source('SOURCE1', 'A Little Birdie')

        places = [place1]
        cls.site.ancestry.places.update({place.id: place for place in places})
        events = [event1]
        cls.site.ancestry.events.update({event.id: event for event in events})
        people = [person1]
        cls.site.ancestry.people.update(
            {person.id: person
             for person in people})
        sources = [source1]
        cls.site.ancestry.sources.update(
            {source.id: source
             for source in sources})

        render(cls.site)
示例#11
0
 def test(self, expected, template, data):
     with TemporaryDirectory() as www_directory_path:
         environment = create_environment(
             Site(Configuration(www_directory_path, 'https://example.com')))
         self.assertEquals(
             expected,
             environment.from_string(template).render(data=data))
示例#12
0
 async def test_resources_with_assets_directory_path(self):
     assets_directory_path = '/tmp/betty'
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.assets_directory_path = assets_directory_path
     async with Site(configuration) as sut:
         self.assertEquals(2, len(sut.assets.paths))
         self.assertEquals(assets_directory_path, sut.assets.paths[0])
示例#13
0
    async def test_filter(self, m_aioresponses) -> None:
        entry_url = 'https://en.wikipedia.org/wiki/Amsterdam'
        links = [
            Link(entry_url),
            # Add a link to Wikipedia, but using a locale that's not used by the site, to test it's ignored.
            Link('https://nl.wikipedia.org/wiki/Amsterdam'),
            # Add a link that doesn't point to Wikipedia at all to test it's ignored.
            Link('https://example.com'),
        ]
        api_url = 'https://en.wikipedia.org/w/api.php?action=query&titles=Amsterdam&prop=extracts&exintro&format=json&formatversion=2'
        title = 'Amstelredam'
        extract = 'De hoofdstad van Nederland.'
        api_response_body = {
            'query': {
                'pages': [
                    {
                        'title': title,
                        'extract': extract,
                    },
                ],
            }
        }
        m_aioresponses.get(api_url, payload=api_response_body)

        with TemporaryDirectory() as output_directory_path:
            with TemporaryDirectory() as cache_directory_path:
                configuration = Configuration(output_directory_path,
                                              'https://ancestry.example.com')
                configuration.cache_directory_path = cache_directory_path
                configuration.plugins[Wikipedia] = None
                async with Site(configuration) as site:
                    actual = await site.jinja2_environment.from_string(
                        '{% for entry in (links | wikipedia) %}{{ entry.content }}{% endfor %}'
                    ).render_async(links=links)
        self.assertEquals(extract, actual)
示例#14
0
    def test_filter(self, m_expanduser, m_requests):
        with TemporaryDirectory() as cache_directory_path:
            m_expanduser.side_effect = lambda _: cache_directory_path
            with TemporaryDirectory() as output_directory_path:
                configuration = Configuration(output_directory_path,
                                              'https://ancestry.example.com')
                configuration.plugins[Wikipedia] = {}

                environment = create_environment(Site(configuration))
                page_uri = 'https://en.wikipedia.org/wiki/Amsterdam'
                link = Link(page_uri)
                api_uri = 'https://en.wikipedia.org/w/api.php?action=query&titles=Amsterdam&prop=extracts&exintro&format=json&formatversion=2'
                title = 'Amstelredam'
                extract = 'De hoofdstad van Nederland.'
                api_response_body = {
                    'query': {
                        'pages': [
                            {
                                'title': title,
                                'extract': extract,
                            },
                        ],
                    }
                }
                m_requests.register_uri('GET', api_uri, json=api_response_body)
                actual = environment.from_string(
                    '{% for entry in ([link] | wikipedia) %}{{ entry.content }}{% endfor %}'
                ).render(link=link)
                self.assertEquals(extract, actual)
示例#15
0
    async def test_post_render_config_with_clean_urls(self):
        with TemporaryDirectory() as output_directory_path:
            configuration = Configuration(output_directory_path,
                                          'http://example.com')
            configuration.plugins[Nginx] = {}
            configuration.clean_urls = True
            expected = r'''
server {
    listen 80;
    server_name example.com;
    root %s;
    add_header Cache-Control "max-age=86400";
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_types text/css application/javascript application/json application/xml;

    set $media_type_extension html;
    index index.$media_type_extension;

    location / {
        # Handle HTTP error responses.
        error_page 401 /.error/401.$media_type_extension;
        error_page 403 /.error/403.$media_type_extension;
        error_page 404 /.error/404.$media_type_extension;
        location /.error {
            internal;
        }

        try_files $uri $uri/ =404;
    }
}
''' % configuration.www_directory_path
            await self._assert_configuration_equals(expected, configuration)
示例#16
0
    async def test_post_load(self):
        person = Person('P0')
        Presence(person, Subject(), Event(None, Birth()))

        source_file = File('F0', __file__)
        source = Source('S0', 'The Source')
        source.private = True
        source.files.append(source_file)

        citation_file = File('F0', __file__)
        citation_source = Source('The Source')
        citation = Citation('C0', citation_source)
        citation.private = True
        citation.files.append(citation_file)

        with TemporaryDirectory() as output_directory_path:
            configuration = Configuration(output_directory_path,
                                          'https://example.com')
            configuration.extensions.add(ExtensionConfiguration(Privatizer))
            async with App(configuration) as app:
                app.ancestry.entities.append(person)
                app.ancestry.entities.append(source)
                app.ancestry.entities.append(citation)
                await load(app)

            self.assertTrue(person.private)
            self.assertTrue(source_file.private)
            self.assertTrue(citation_file.private)
示例#17
0
 async def test_with_one_extension(self):
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.extensions[NonConfigurableExtension] = None
     async with App(configuration) as sut:
         self.assertEquals(1, len(sut.extensions))
         self.assertIsInstance(
             sut.extensions[NonConfigurableExtension], NonConfigurableExtension)
示例#18
0
 async def test_extensions_with_one_extension(self) -> None:
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.extensions.add(
         ExtensionConfiguration(NonConfigurableExtension))
     async with App(configuration) as sut:
         self.assertIsInstance(sut.extensions[NonConfigurableExtension],
                               NonConfigurableExtension)
示例#19
0
 async def test_extensions_with_multiple_extensions_with_cyclic_dependencies(
         self) -> None:
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.extensions.add(
         ExtensionConfiguration(CyclicDependencyOneExtension))
     with self.assertRaises(CycleError):
         async with App(configuration) as sut:
             sut.extensions
示例#20
0
 async def test_xml_tar_gz(self):
     with TemporaryDirectory() as output_directory_path:
         configuration = Configuration(output_directory_path,
                                       'https://example.com')
         async with Site(configuration) as site:
             gramps_file_path = join(dirname(abspath(__file__)), 'assets',
                                     'minimal.gpkg')
             parse_xml(site, gramps_file_path)
示例#21
0
 def test_resources_directory_path_with_relative_path(self):
     sut = Configuration('/tmp/betty', 'https://example.com')
     site_directory_path = '/tmp/betty-working-directory'
     sut.site_directory_path = site_directory_path
     resources_directory_path = './betty-resources'
     sut.resources_directory_path = resources_directory_path
     self.assertEquals(
         '/tmp/betty-working-directory/betty-resources', sut.resources_directory_path)
示例#22
0
 async def test(self):
     with TemporaryDirectory() as output_directory_path:
         configuration = Configuration(output_directory_path, 'https://ancestry.example.com')
         configuration.extensions[ReDoc] = None
         async with App(configuration) as app:
             await generate(app)
         self.assertTrue(path.isfile(path.join(output_directory_path, 'www', 'api', 'index.html')))
         self.assertTrue(path.isfile(path.join(output_directory_path, 'www', 'redoc.js')))
示例#23
0
 async def test_assets_with_assets_directory_path(self) -> None:
     assets_directory_path = Path('/tmp/betty')
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.assets_directory_path = assets_directory_path
     async with App(configuration) as sut:
         self.assertEquals(2, len(sut.assets.paths))
         self.assertEquals((assets_directory_path, None),
                           sut.assets.paths[0])
示例#24
0
 def setUp(self):
     GenerateTestCase.setUp(self)
     configuration = Configuration(
         self._outputDirectory.name, 'https://ancestry.example.com')
     configuration.locales.clear()
     configuration.locales['nl'] = LocaleConfiguration('nl')
     configuration.locales['en'] = LocaleConfiguration('en')
     self.site = Site(configuration)
示例#25
0
 async def test_load_gramps(self):
     with TemporaryDirectory() as output_directory_path:
         configuration = Configuration(output_directory_path,
                                       'https://example.com')
         async with App(configuration) as app:
             gramps_file_path = Path(
                 __file__).parent / 'assets' / 'minimal.gramps'
             load_gramps(app.ancestry, gramps_file_path)
示例#26
0
 async def test_places(self):
     configuration = Configuration(self._output_directory.name,
                                   'https://ancestry.example.com')
     app = App(configuration)
     async with app:
         await generate(app)
     self.assert_betty_html(app, '/place/index.html')
     self.assert_betty_json(app, '/place/index.json', 'placeCollection')
示例#27
0
 def test_with_disabled_plugin(self):
     with TemporaryDirectory() as www_directory_path:
         environment = create_environment(
             Site(Configuration(www_directory_path, 'https://example.com')))
         template = '{% if "' + TestPlugin.__module__ + \
             '.TestPlugin" in plugins %}true{% else %}false{% endif %}'
         self.assertEquals('false',
                           environment.from_string(template).render())
示例#28
0
 def test_with_comes_after_without_other_plugin(self):
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.plugins[ComesAfterNonConfigurablePluginPlugin] = {}
     sut = Site(configuration)
     event = TrackingEvent()
     sut.event_dispatcher.dispatch(event)
     self.assertEquals(1, len(event.tracker))
     self.assertEquals(ComesAfterNonConfigurablePluginPlugin,
                       type(event.tracker[0]))
示例#29
0
 async def test_extensions_addition_to_configuration(self) -> None:
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     async with App(configuration) as sut:
         # Get the extensions before making configuration changes to warm the cache.
         sut.extensions
         configuration.extensions.add(
             ExtensionConfiguration(NonConfigurableExtension))
         self.assertIsInstance(sut.extensions[NonConfigurableExtension],
                               NonConfigurableExtension)
示例#30
0
 async def test_extensions_removal_from_configuration(self) -> None:
     configuration = Configuration(**self._MINIMAL_CONFIGURATION_ARGS)
     configuration.extensions.add(
         ExtensionConfiguration(NonConfigurableExtension))
     async with App(configuration) as sut:
         # Get the extensions before making configuration changes to warm the cache.
         sut.extensions
         del configuration.extensions[NonConfigurableExtension]
         self.assertNotIn(NonConfigurableExtension, sut.extensions)