def setUp(self): self.request = mock.MagicMock() self.request.site.hostname = 'localhost:8000' self.limit = 10 self.sublanding_page = SublandingPage(title='title') helpers.publish_page(child=self.sublanding_page) self.post1 = BrowseFilterablePage(title='post 1') self.post2 = BrowseFilterablePage(title='post 2') # the content of this post has both a full_width_text # and a filter_controls self.post1.content = StreamValue(self.post1.content.stream_block, [atomic.full_width_text, atomic.filter_controls], True) # this one only has a filter_controls self.post2.content = StreamValue(self.post1.content.stream_block, [atomic.filter_controls], True) helpers.save_new_page(self.post1, self.sublanding_page) helpers.save_new_page(self.post2, self.sublanding_page) # manually set the publication date of the posts to ensure consistent # order of retrieval in test situations, otherwise the `date_published` # can vary due to commit order self.child1_of_post1 = AbstractFilterPage(title='child 1 of post 1', date_published=dt.date(2016, 9, 1)) self.child2_of_post1 = AbstractFilterPage(title='child 2 of post 1', date_published=dt.date(2016, 9, 2)) self.child1_of_post2 = AbstractFilterPage(title='child 1 of post 2', date_published=dt.date(2016, 9, 3)) helpers.save_new_page(self.child1_of_post1, self.post1) helpers.save_new_page(self.child2_of_post1, self.post1) helpers.save_new_page(self.child1_of_post2, self.post2)
def migrate_menu(): MenuItem.objects.all().delete() for item in menu_items: menu_item = MenuItem( link_text=item['link_text'], order=item['order'], ) wagtail_page = get_wagtail_page(item) if wagtail_page: menu_item.page_link = wagtail_page for i, group in enumerate(item['nav_groups']): replace_external_links(group['value']) column_block = getattr(menu_item, 'column_{}'.format(i + 1)) stream_block = getattr(column_block, 'stream_block') setattr(menu_item, 'column_{}'.format(i + 1), StreamValue( stream_block, [group], True, )) if item.get('footer'): menu_item.nav_footer = StreamValue( menu_item.nav_footer.stream_block, [item['footer']], True, ) if item.get('featured_content'): featured_content = item['featured_content'] if featured_content['value']['link']: set_page_link(featured_content['value']['link']) menu_item.column_4 = StreamValue( menu_item.column_4.stream_block, [featured_content], True, ) menu_item.save()
def to_python(self, value): if value is None or value == '': return StreamValue(self.stream_block, []) elif isinstance(value, StreamValue): return value elif isinstance(value, string_types): try: unpacked_value = json.loads(value) except ValueError: # value is not valid JSON; most likely, this field was previously a # rich text field before being migrated to StreamField, and the data # was left intact in the migration. Return an empty stream instead # (but keep the raw text available as an attribute, so that it can be # used to migrate that data to StreamField) return StreamValue(self.stream_block, [], raw_text=value) if unpacked_value is None: # we get here if value is the literal string 'null'. This should probably # never happen if the rest of the (de)serialization code is working properly, # but better to handle it just in case... return StreamValue(self.stream_block, []) return self.stream_block.to_python(unpacked_value) else: # See if it looks like the standard non-smart representation of a # StreamField value: a list of (block_name, value) tuples try: [None for (x, y) in value] except (TypeError, ValueError): # Give up trying to make sense of the value raise TypeError("Cannot handle %r (type %r) as a value of StreamField" % (value, type(value))) # Test succeeded, so return as a StreamValue-ified version of that value return StreamValue(self.stream_block, value)
def test_custom_page_streamfield_data_complex(): assert Image.objects.count() == 0 root_page = wagtail_factories.PageFactory(parent=None) page = MyTestPageWithStreamFieldFactory( parent=root_page, body__0__char_array__0='foo', body__0__char_array__1='bar', body__2__int_array__0=100, body__1__struct__title='My Title', body__1__struct__item__value=100, body__1__struct__image__image=None, body__3__image__image__title='Blub', body__4__stream__0__title="Stream title", body__4__stream__1__subtitle="Stream subtitle", body__5__char="A char", body__6__stream__0__item__label="A deeply nested item", ) assert Image.objects.count() == 1 image = Image.objects.first() assert page.body.stream_data == [ ('char_array', ['foo', 'bar']), ('struct', StructValue(None, [ ('title', 'My Title'), ('item', StructValue(None, [ ('label', 'my-label'), ('value', 100), ])), ('items', []), ('image', None), ])), ('int_array', [100]), ('image', image), ('stream', StreamValue(None, [ ('title', 'Stream title'), ('subtitle', 'Stream subtitle'), ])), ('char', 'A char'), ('stream', StreamValue(None, [('item', StructValue(None, [ ('label', 'A deeply nested item'), ('value', 100), ]))])), ] content = str(page.body) assert 'block-image' in content
def test_featured_content(self): """Featured content value correctly displays on a Browse Page""" bp = BrowsePage( title='Browse Page', slug='browse-page', ) bp.header = StreamValue(bp.header.stream_block, [atomic.featured_content], True) bp.content = StreamValue(bp.content.stream_block, [atomic.expandable, atomic.expandable_group], True) publish_page(child=bp) response = django_client.get('/browse-page/') self.assertContains(response, 'this is a featured content body')
def test_data_snapshot(self): """ Management command correctly updates data snapshot values""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) # Adds a AUT market to a browse page browse_page.content = StreamValue(browse_page.content.stream_block, [atomic.data_snapshot], True) publish_page(child=browse_page) # Call management command to update values filename = os.path.join(settings.PROJECT_ROOT, 'v1/tests/fixtures/data_snapshots.json') call_command('update_data_snapshot_values', '--snapshot_file={}'.format(filename)) response = self.client.get('/browse/') self.assertContains(response, '2.1 million') self.assertContains(response, '$46.4 billion') self.assertContains(response, '5.8% increase') self.assertContains(response, 'March 2017') self.assertContains(response, 'Auto loans originated') self.assertContains(response, 'Dollar value of new loans') self.assertContains(response, 'In year-over-year originations')
def test_data_snapshot(self): """ Management command correctly updates data snapshot values""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) # Adds a STU market to a browse page browse_page.content = StreamValue(browse_page.content.stream_block, [atomic.data_snapshot], True) publish_page(child=browse_page) # Call management command to update values filename = os.path.join(settings.PROJECT_ROOT, 'v1/tests/fixtures/data_snapshots.json') call_command('update_data_snapshot_values', '--snapshot_file={}'.format(filename)) response = self.client.get('/browse/') self.assertContains(response, '458,407') self.assertContains(response, '$8.0 billion') self.assertContains(response, '32.6% increase') self.assertContains(response, 'March 2017') self.assertContains(response, 'Loans originated') self.assertContains(response, 'Dollar value of new loans') self.assertContains(response, 'In year-over-year originations') # Should not contain inquiry and tightness values self.assertNotContains(response, '3.2% increase') self.assertNotContains(response, '7.0% increase') self.assertNotContains(response, 'In year-over-year inquiries') self.assertNotContains(response, 'In year-over-year credit tightness')
def test_regulations_full_width_text(self): self.landing_page.content = StreamValue( self.landing_page.content.stream_block, [{ 'type': 'full_width_text', 'value': [ { 'type': 'content', 'value': 'Full width text content' }, { 'type': 'regulations_list', 'value': { 'body': 'this is a quote', 'citation': 'a citation', 'more_regs_page': self.more_regs_page.pk, } }, ] }], True ) self.landing_page.save_revision().publish() response = self.client.get('/regulations/') self.assertContains(response, 'Full width text content') self.assertContains(response, 'Reg B')
def test_data_snapshot_with_optional_fields(self): """ Data Snapshot with inquiry and tightness information correctly renders fields on a Browse Page""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) # Adds a AUT market to a browse page browse_page.content = StreamValue( browse_page.content.stream_block, [atomic.data_snapshot_with_optional_fields], True) publish_page(child=browse_page) response = self.client.get('/browse/') self.assertContains(response, '5 million') self.assertContains(response, '$64 billion') self.assertContains(response, '5% increase') self.assertContains(response, 'January 2015') self.assertContains(response, 'Loans originated') self.assertContains(response, 'Dollar value of new loans') self.assertContains(response, 'In year-over-year originations') # Should include inquiry or tightness information self.assertContains(response, '7.4% decrease') self.assertContains(response, 'In year-over-year inquiries') self.assertContains(response, '2.8% increase') self.assertContains(response, 'In year-over-year credit tightness')
def add_reusable_text_snippet(slug, cls): snippet_with_heading = ReusableText( title='Test reusable text snippet with sidefoot heading', sidefoot_heading='Test sidefoot heading', text='A reusable snippet with a sidefoot heading', ) snippet_without_heading = ReusableText( title='Test reusable text snippet without a sidefoot heading', text='A reusable snippet without a sidefoot heading.', ) snippet_with_heading.save() snippet_without_heading.save() full_width_text = { 'type': 'full_width_text', 'value': [{ 'type': 'reusable_text', 'value': snippet_with_heading.id }, { 'type': 'reusable_text', 'value': snippet_without_heading.id }] } page = cls( title=slug, slug=slug, ) page.content = StreamValue( page.content.stream_block, [full_width_text], True, ) publish_page(page)
def get_contact(self): contact = Contact(heading='Test User') contact.contact_info = StreamValue(contact.contact_info.stream_block, [ atomic.contact_email, atomic.contact_phone, atomic.contact_address ], True) contact.save() return contact
def test_chart_block_inquiry_activity(self): """ Management command correctly updates chart block dates for inquiry index charts""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) # Adds a Chart Block to a browse page browse_page.content = StreamValue( browse_page.content.stream_block, [atomic.chart_block_inquiry_activity], True ) publish_page(child=browse_page) # Call management command to update values filename = os.path.join( settings.PROJECT_ROOT, 'v1/tests/fixtures/data_snapshot.json' ) call_command( 'update_chart_block_dates', '--snapshot_file={}'.format(filename) ) response = self.client.get('/browse/') # Tests last_updated_projected_data is correct self.assertContains( response, 'The most recent data available in this visualization are for June 2018' ) # Tests date_published is correct self.assertContains(response, 'October 2018')
def test_cache_gets_called_when_visiting_filterable_page(self): # Create a filterable page page = BrowseFilterablePage( title='test browse filterable page', slug='test-browse-filterable-page' ) page.content = StreamValue( page.content.stream_block, [atomic.filter_controls], True ) publish_page(page) # Add a child to that filterable page so that there are results # with a post preview child_page = BlogPage( title='test blog page', slug='test-blog-page' ) page.add_child(instance=child_page) cache = caches['post_preview'] with patch.object(cache, 'add') as add_to_cache: # Navigate to the filterable page so that `post-preview.html` loads self.client.get('/test-browse-filterable-page/') self.assertTrue(add_to_cache.called)
def test_data_snapshot_with_inquiry_and_tightness(self): """ Management command correctly updates data snapshot values for market that contains inquiry and tightness data""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) # Adds a AUT market to a browse page browse_page.content = StreamValue( browse_page.content.stream_block, [atomic.data_snapshot_with_optional_fields], True) publish_page(child=browse_page) # Call management command to update values filename = os.path.join(settings.PROJECT_ROOT, 'v1/tests/fixtures/data_snapshot.json') call_command('update_data_snapshot_values', '--snapshot_file={}'.format(filename)) # July 2018 response = self.client.get('/browse/') self.assertContains(response, '2.5 million') # Auto loans originated self.assertContains(response, '$54.6 billion') # Dollar volume of new loans self.assertContains(response, '7.3% increase') # In year-over-year originations self.assertContains(response, 'July 2018') self.assertContains(response, 'Loans originated') self.assertContains(response, 'Dollar value of new loans') self.assertContains(response, 'In year-over-year originations') # Inquiry and tightness values self.assertContains(response, '7.9% increase') self.assertContains(response, '2.8% increase') self.assertContains(response, 'In year-over-year inquiries') self.assertContains(response, 'In year-over-year credit tightness')
def convert_articles(apps, schema_editor): ''' Derived from https://github.com/wagtail/wagtail/issues/2110 ''' articles = ArticlePage.objects.all().exact_type(ArticlePage) for article in articles: stream_data = [] linked_articles = [] for block in article.body.stream_data: if block['type'] == 'page': if ArticlePage.objects.filter(id=block['value']): linked_articles.append( ArticlePage.objects.get(id=block['value'])) else: # add block to new stream_data stream_data.append(block) if linked_articles: create_recomended_articles(article, linked_articles) stream_block = article.body.stream_block article.body = StreamValue(stream_block, stream_data, is_lazy=True) article.save() section = article.get_parent().specific section.enable_recommended_section = True section.enable_next_section = True section.save()
def add_menu_item_snippet(): nav_group_block = { 'type': 'nav_group', 'value': { 'hide_group_title': False, 'draft': False, 'group_title': 'Menu Section Title', 'nav_items': [{ 'link': { 'state': 'both', 'link_text': 'One', 'external_link': '#', 'nav_groups': [] } }] } } for i in range(1, 6): menu_item = MenuItem(link_text='Menu Item {}'.format(i)) menu_item.column_1 = StreamValue( menu_item.column_1.stream_block, [nav_group_block], True, ) menu_item.save()
def test_quote(self): """Quote value correctly displays on a Learn Page""" learn_page = LearnPage(title='Learn', slug='learn') learn_page.content = StreamValue(learn_page.content.stream_block, [atomic.full_width_text], True) publish_page(child=learn_page) response = django_client.get('/learn/') self.assertContains(response, 'this is a quote') self.assertContains(response, 'a citation')
def test_content_with_anchor(self): """Content with anchor value correctly displays on a Learn Page""" learn_page = LearnPage(title='Learn', slug='learn') learn_page.content = StreamValue(learn_page.content.stream_block, [atomic.full_width_text], True) publish_page(child=learn_page) response = django_client.get('/learn/') self.assertContains(response, 'full width text block') self.assertContains(response, 'this is an anchor link')
def test_has_changed_richtext(self): field = StreamPage._meta.get_field('body') comparison = self.comparison_class( field, StreamPage(body=StreamValue(field.stream_block, [ ('rich_text', "<b>Original</b> content"), ])), StreamPage(body=StreamValue(field.stream_block, [ ('rich_text', "Modified <i>content</i>"), ])), ) self.assertEqual( comparison.htmldiff(), '<span class="deletion">Original</span><span class="addition">Modified</span> content' ) self.assertIsInstance(comparison.htmldiff(), SafeText) self.assertTrue(comparison.has_changed())
def test_hero(self): """Hero heading correctly displays on a Sublanding Filterable Page""" sfp = SublandingFilterablePage( title='Sublanding Filterable Page', slug='sfp', ) sfp.header = StreamValue(sfp.header.stream_block, [atomic.hero], True) publish_page(child=sfp) response = django_client.get('/sfp/') self.assertContains(response, 'this is a hero heading')
def test_htmldiff_escapes_value_richtext(self): field = StreamPage._meta.get_field('body') comparison = self.comparison_class( field, StreamPage(body=StreamValue(field.stream_block, [ ('rich_text', "Original content"), ])), StreamPage(body=StreamValue(field.stream_block, [ ('rich_text', '<script type="text/javascript">doSomethingBad();</script>'), ])), ) self.assertEqual( comparison.htmldiff(), '<span class="deletion">Original content</span><span class="addition">doSomethingBad();</span>' ) self.assertIsInstance(comparison.htmldiff(), SafeText)
def test_hasnt_changed(self): field = StreamPage._meta.get_field('body') comparison = self.comparison_class( field, StreamPage(body=StreamValue(field.stream_block, [ ('text', "Content"), ])), StreamPage(body=StreamValue(field.stream_block, [ ('text', "Content"), ])), ) self.assertTrue(comparison.is_field) self.assertFalse(comparison.is_child_relation) self.assertEqual(comparison.field_label(), "Body") self.assertEqual(comparison.htmldiff(), 'Content') self.assertIsInstance(comparison.htmldiff(), SafeText) self.assertFalse(comparison.has_changed())
def __getitem__(self, i): if i not in self._bound_blocks: if self.is_lazy: raw_value = self.stream_data[i] type_name = raw_value['type'] child_block = self.stream_block.child_blocks[type_name] value = child_block.to_python(raw_value['value']) child_block.rendition = self.rendition self._bound_blocks[i] = StreamValue.StreamChild(child_block, value) return self._bound_blocks[i]
def test_html_block(self): """ HTML Block correctly renders HTML on a Browse Page""" browse_page = BrowsePage( title='Browse Page', slug='browse', ) browse_page.content = StreamValue(browse_page.content.stream_block, [atomic.html_block], True) publish_page(child=browse_page) response = self.client.get('/browse/') self.assertContains(response, 'Age 30 to 44')
def test_well(self): """Well content correctly displays on a Landing Page""" landing_page = LandingPage( title='Landing Page', slug='landing', ) landing_page.content = StreamValue(landing_page.content.stream_block, [atomic.well], True) publish_page(child=landing_page) response = django_client.get('/landing/') self.assertContains(response, 'this is well content')
def test_reg_comment(self): """RegComment correctly displays on a Sublanding Page""" sublanding_page = SublandingPage( title='Sublanding Page', slug='sublanding', ) sublanding_page.content = StreamValue( sublanding_page.content.stream_block, [atomic.reg_comment], True) publish_page(child=sublanding_page) response = django_client.get('/sublanding/') self.assertContains(response, 'Enter your comments')
def test_info_unit_group(self): """Info Unit Group correctly displays on a Landing Page""" landing_page = LandingPage( title='Landing Page', slug='landing', ) landing_page.content = StreamValue(landing_page.content.stream_block, [atomic.info_unit_group], True) publish_page(child=landing_page) response = django_client.get('/landing/') self.assertContains(response, 'Info Unit Group')
def test_full_width_text(self): """Full width text content correctly displays on a Learn Page""" learn_page = LearnPage( title='Learn Page', slug='learn', ) learn_page.content = StreamValue(learn_page.content.stream_block, [atomic.full_width_text], True) publish_page(child=learn_page) response = django_client.get('/learn/') self.assertContains(response, 'Full width text content')
def test_call_to_action(self): """Call to action value correctly displays on a Learn Page""" learn_page = LearnPage( title='Learn', slug='learn', ) learn_page.content = StreamValue(learn_page.content.stream_block, [atomic.call_to_action], True) publish_page(child=learn_page) response = django_client.get('/learn/') self.assertContains(response, 'this is a call to action')
def test_related_links(self): """Related links value correctly displays on a Landing Page""" landing_page = LandingPage( title='Landing Page', slug='landing', ) landing_page.sidefoot = StreamValue(landing_page.sidefoot.stream_block, [atomic.related_links], True) publish_page(child=landing_page) response = django_client.get('/landing/') self.assertContains(response, 'this is a related link')