def testImage(self): self.folder.invokeFactory('Image', id='image') portal_repository = self.portal_repository img1 = open(os.path.join(PACKAGE_HOME, 'tests/images/img1.png'), 'rb').read() img2 = open(os.path.join(PACKAGE_HOME, 'tests/images/img2.png'), 'rb').read() content = self.folder.image content.image = NamedBlobImage(img1, u'img1.png', u'image/png') content.title = u'content' content.subject = [u'content'] content.description = u'content' content.contributors = [u'content'] content.language = 'content' content.rights = u'content' portal_repository.applyVersionControl(content, comment='save no 1') content.image = NamedBlobImage(img2, u'img2.png', u'image/png') content.title = u'contentOK' content.subject = [u'contentOK'] content.description = u'contentOK' content.contributors = [u'contentOK'] content.language = 'contentOK' content.rights = u'contentOK' portal_repository.save(content, comment='save no 2') obj = portal_repository.retrieve(content, 0).object self.assertEqual(obj.image.data, img1) self.metadata_test_one(obj) obj = portal_repository.retrieve(content, 1).object self.assertEqual(obj.image.data, img2) self.metadata_test_two(obj) portal_repository.revert(content, 0) self.assertEqual(content.image.data, img1) self.metadata_test_one(content)
def testPublishUpdatesLogo(self): # Test for http://code.simplon.biz/tracker/tno-euphorie/ticket/136 white_gif = ( b"GIF89a\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\xff\xff\xff," b"\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;" ) black_gif = ( b"GIF89a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00\xff\xff\xff," b"\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;" ) self.createSurvey() self.sector.logo = NamedBlobImage( data=white_gif, contentType="image/gif", filename="white.gif" ) view = self.survey.restrictedTraverse("@@publish") view.publish() client_sector = self.client.nl["dining"] self.assertEqual(client_sector.logo.data, white_gif) images = client_sector.restrictedTraverse("@@images") white_scale = images.scale("logo", height=100, direction="up").data.data self.sector.logo = NamedBlobImage( data=black_gif, contentType="image/gif", filename="black.gif" ) view.publish() self.assertEqual(client_sector.logo.data, black_gif) images = client_sector.restrictedTraverse("@@images") black_scale = images.scale("logo", height=100, direction="up").data.data self.assertNotEqual(white_scale, black_scale)
def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) image_file = os.path.join(os.path.dirname(__file__), u"image.png") with open(image_file, "rb") as f: image_data = f.read() self.folder = api.content.create(container=self.portal, type="Folder", title="Normal folder") self.subsite = api.content.create( container=self.portal, type="Subsite", title="Subsite", subsite_header=RichTextValue( raw="<p>header</p>", mimeType="text/html", outputMimeType="text/html", encoding="utf-8", ), subsite_footer=RichTextValue( raw="<p>footer</p>", mimeType="text/html", outputMimeType="text/html", encoding="utf-8", ), subsite_css_class="red", image=NamedBlobImage(data=image_data, contentType="image/png", filename=u"image.png"), subsite_logo=NamedBlobImage(data=image_data, contentType="image/png", filename=u"image.png"), ) self.document_in_subsite = api.content.create( container=self.subsite, type="Document", title="Document in subsite", ) self.document_outside_subsite = api.content.create( container=self.folder, type="Document", title="Document outside subsite", ) commit()
def test_lead_image_render(self): from collective.geo.kml.browser import kmldocument from plone.namedfile.file import NamedBlobImage, NamedImage from plone.namedfile.tests.test_blobfile import registerUtilities from mock import Mock # get NamedBlobImage/NamedImage to work in this test registerUtilities() # so we don't need collective.contentleadimage for the test kmldocument.HAS_LEADIMAGE = True # we could use ATImage, but since that is deprecated, we just mock it class ATImage(object): def get_size(self, obj): return 1 def tag(self, obj, scale, css_class): return '<img>' placemark = kmldocument.Placemark(self.portal, self.request) placemark.context.getField = Mock(return_value=ATImage()) self.assertEqual(placemark.lead_image(), '<img>') # now let's try with NamedBlobImage and NamedImage placemark.context.getField = Mock(return_value=NamedImage()) self.assertEqual(placemark.lead_image(), None) placemark.context.getField = Mock(return_value=NamedBlobImage()) self.assertEqual(placemark.lead_image(), None) # or anything else really placemark.context.getField = Mock(return_value=object()) self.assertEqual(placemark.lead_image(), None)
def prefill_image_types_dexterity(kwargs): import random import string image = random_image() filename = u'{}.png'.format(''.join( random.choice(string.ascii_lowercase) for _ in range(6))) kwargs['image'] = NamedBlobImage(data=image, filename=filename)
def create_entry(self, folder, dictNews): ''' Cria news item, realiza transição ''' oId = str(dictNews.get('id')) if not oId in folder.objectIds(): api.content.create(folder, 'News Item', oId, title=dictNews.get('title'), description=dictNews.get('description')) else: return folder[oId] log.info(' - Cria item %s' % (oId)) o = folder[oId] if not o: return for k, v in dictNews.items(): if k in ['title', 'id', 'anexos']: continue if k in ['text']: v = RichTextValue(v, 'text/html', 'text/html') o.text = v if k in ['image']: data = v[0] content_type = v[1] filename = u'image.%s' % (content_type.split('/')[1]) v = NamedBlobImage(data, content_type, filename) o.image = v if v and hasattr(o, k): setattr(o, k, v) o.exclude_from_nav = True api.content.transition(o, 'publish') o.reindexObject() return o
def test_basic_tile_purge_cache(self): provideHandler(queuePurge) request = self.request alsoProvides(request, IAttributeAnnotatable) setRequest(request) registry = queryUtility(IRegistry) registry.registerInterface(ICachePurgingSettings) provideUtility(registry, IRegistry) settings = registry.forInterface(ICachePurgingSettings) settings.enabled = True settings.cachingProxies = ('http://*****:*****@@collective.cover.basic/test', '/c1/@@collective.cover.basic/test/@@images/image', '/c1/@@collective.cover.basic/test/@@images/icon', '/c1/@@collective.cover.basic/test/@@images/mini', '/c1/@@collective.cover.basic/test/@@images/large', '/c1/@@collective.cover.basic/test/@@images/listing', '/c1/@@collective.cover.basic/test/@@images/thumb', '/c1/@@collective.cover.basic/test/@@images/preview', '/c1/@@collective.cover.basic/test/@@images/tile']), IAnnotations(request)['plone.cachepurging.urls'])
def updatePDF(context, normalizedTitle, pt): """ :param context: an object with a ``pdfscore`` field :type context: usualy a ABC object :param normalizedTitle: used for the blob filename :type normalizedTitle: string :param pt: tool :type pt: portal_tranform tool :returns: nothing, update the ``pdfscore`` field of the object """ try: pdfData = pt.convertTo( 'application/pdf', context.abc, context=context, annotate=True, ) pdfFilename = normalizedTitle + u'.pdf' pdfContenType = 'application/pdf' context.pdfscore = NamedBlobImage() context.pdfscore.data = pdfData.getData() context.pdfscore.filename = pdfFilename context.pdfscore.contentType = pdfContenType except Exception: msg = u'Failed to create PDF score' logger.info(msg) annotateObject(context, msg=msg, key='ABC_ERRORS')
def updateOGG(context, normalizedTitle, pt): """ :param context: an object with a ``ogg`` field :type context: usualy a ABC object :param normalizedTitle: used for the blob filename :type normalizedTitle: string :param pt: tool :type pt: portal_tranform tool :returns: nothing, update the ``ogg`` field of the object """ try: oggData = pt.convertTo( 'audio/ogg', context.abc, context=context, annotate=True, ) oggFilename = normalizedTitle + u'.ogg' oggContenType = 'audio/ogg' context.ogg = NamedBlobImage() context.ogg.data = oggData.getData() context.ogg.filename = oggFilename context.ogg.contentType = oggContenType except Exception: msg = u'Failed to create OGG sound' logger.info(msg) annotateObject(context, msg=msg, key='ABC_ERRORS')
def dummy_file(): from plone.namedfile.file import NamedBlobImage path = os.path.join(os.path.dirname(__file__), FILENAME) return NamedBlobImage( data=open(path, 'r').read(), filename=FILENAME )
def populate_with_object(self, obj): # check permissions super(ImageTile, self).populate_with_object(obj) data_mgr = ITileDataManager(self) data_mgr.set({'image': NamedBlobImage(obj.getImage().data)})
def handle_storage(self): gsettings = self.gsettings storage_dir = self.storage_dir settings = self.settings context = self.context # save lead image if available if ILeadImage.providedBy(self.context): path = os.path.join(storage_dir, 'large') filename = None for dump_filename in os.listdir(path): if dump_filename.startswith('dump_1.'): filename = dump_filename break filepath = os.path.join(path, filename) tmppath = '%s.tmp' % (filepath) # NamedBlobImage eventually calls blob.consume, # destroying the image, so we need to make a temporary copy. shutil.copyfile(filepath, tmppath) fi = open(tmppath) self.context.image = NamedBlobImage( fi, filename=filename.decode('utf8')) fi.close() if self.gsettings.storage_type == 'Blob': logger.info('setting blob data for %s' % repr(context)) # go through temp folder and move items into blob storage files = OOBTree() for size in ('large', 'normal', 'small'): path = os.path.join(storage_dir, size) for filename in os.listdir(path): filepath = os.path.join(path, filename) filename = '%s/%s' % (size, filename) files[filename] = saveFileToBlob(filepath) if self.settings.enable_indexation: textfilespath = os.path.join(storage_dir, TEXT_REL_PATHNAME) for filename in os.listdir(textfilespath): filepath = os.path.join(textfilespath, filename) filename = '%s/%s' % (TEXT_REL_PATHNAME, filename) files[filename] = saveFileToBlob(filepath) # Store converted PDF dump_pdf_path = os.path.join(storage_dir, DUMP_FILENAME) filename = 'pdf/%s' % DUMP_FILENAME files[filename] = saveFileToBlob(dump_pdf_path) settings.blob_files = files shutil.rmtree(storage_dir) # check for old storage to remove... Just in case. old_storage_dir = os.path.join(gsettings.storage_location, context.UID()) if os.path.exists(old_storage_dir): shutil.rmtree(old_storage_dir) else: # if settings used to be blob, delete file data if settings.storage_type == 'Blob' and settings.blob_files: del settings._metadata['blob_files']
def setUp(self): self.app = self.layer["app"] self.portal = self.layer["portal"] self.portal_url = self.portal.absolute_url() setRoles(self.portal, TEST_USER_ID, ["Manager"]) self.api_session = RelativeSession(self.portal_url) self.api_session.headers.update({"Accept": "application/json"}) self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD) self.news_with_image = api.content.create( container=self.portal, type="News Item", title="News with image", description="", ) self.news_without_image = api.content.create( container=self.portal, type="News Item", title="News without image", description="", ) filename = os.path.join(os.path.dirname(__file__), u"logo.png") self.news_with_image.image = NamedBlobImage( data=open(filename, "rb").read(), filename="logo.png", contentType="image/png", ) self.news_with_image.reindexObject() transaction.commit()
def _deserialize(cls, data): realdata = data['data'] if len(realdata) < 10: # arbitrary print("short data found in NamedBlobImageSerializer _deserialize") return NamedBlobImage(base64.b64decode(realdata), filename=data['filename'], contentType=data['content_type'])
def test_namedblobimage_field_serialization_returns_dict(self): image_data = ( 'GIF89a\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00,\x00' '\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;') value = self.serialize( 'test_namedblobimage_field', NamedBlobImage(data=image_data, contentType=u'image/gif', filename=u'test.gif')) self.assertTrue(isinstance(value, dict), 'Not a <dict>') obj_url = self.doc1.absolute_url() self.assertEqual( { u'icon': u'{}/@@images/image/icon'.format(obj_url), u'large': u'{}/@@images/image/large'.format(obj_url), u'listing': u'{}/@@images/image/listing'.format(obj_url), u'mini': u'{}/@@images/image/mini'.format(obj_url), u'original': u'{}/@@images/test_namedblobimage_field'.format(obj_url), u'preview': u'{}/@@images/image/preview'.format(obj_url), u'thumb': u'{}/@@images/image/thumb'.format(obj_url), u'tile': u'{}/@@images/image/tile'.format(obj_url) }, value)
def migrate_schema_fields(self): old_image = self.old.getField('image').get(self.old) if old_image == '': return filename = safe_unicode(old_image.filename) namedblobimage = NamedBlobImage(data=old_image.data, filename=filename) self.new.image = namedblobimage
def migrate_imagefield(src_obj, dst_obj, src_fieldname, dst_fieldname): """ migrate an image field. This field needs to be migrated with an NamedBlobImage instance. """ # get old image data and filename old_image = src_obj.getField(src_fieldname).get(src_obj) if old_image == '': return filename = safe_unicode(old_image.filename) old_image_data = old_image.data if safe_hasattr(old_image_data, 'data'): old_image_data = old_image_data.data # create the new image field namedblobimage = NamedBlobImage(data=old_image_data, filename=filename) # set new field on destination object setattr(dst_obj, dst_fieldname, namedblobimage) # handle a possible image caption field # postulate is the old caption field name is ending by 'Caption' # and the new field name is ending by '_caption' # is this postulate correct ? # should this field not be handle by itself because it will appear in the # old field list ? caption_field = src_obj.getField('%sCaption' % src_fieldname, None) if caption_field: setattr(dst_obj, ('%s_caption' % dst_fieldname), safe_unicode(caption_field.get(src_obj))) logger.info("Migrating image %s" % filename)
def test_namedblobimage_field_serialization_returns_dict(self): image_file = os.path.join(os.path.dirname(__file__), u'1024x768.gif') with open(image_file, 'rb') as f: image_data = f.read() fn = 'test_namedblobimage_field' with patch.object(storage, 'uuid4', return_value='uuid_1'): value = self.serialize( fn, NamedBlobImage( data=image_data, contentType=u'image/gif', filename=u'1024x768.gif' ) ) self.assertTrue(isinstance(value, dict), 'Not a <dict>') scale_url_uuid = 'uuid_1' obj_url = self.doc1.absolute_url() download_url = u'{}/@@images/{}.{}'.format( obj_url, scale_url_uuid, GIF_SCALE_FORMAT ) scales = { u'listing': { u'download': download_url, u'width': 16, u'height': 12}, u'icon': { u'download': download_url, u'width': 32, u'height': 24}, u'tile': { u'download': download_url, u'width': 64, u'height': 48}, u'thumb': { u'download': download_url, u'width': 128, u'height': 96}, u'mini': { u'download': download_url, u'width': 200, u'height': 150}, u'preview': { u'download': download_url, u'width': 400, u'height': 300}, u'large': { u'download': download_url, u'width': 768, u'height': 576}, } self.assertEqual({ u'filename': u'1024x768.gif', u'content-type': u'image/gif', u'size': 1514, u'download': download_url, u'width': 1024, u'height': 768, u'scales': scales}, value)
def dummy_image(): from plone.namedfile.file import NamedBlobImage filename = os.path.join(os.path.dirname(__file__), u'image.jpg') return NamedBlobImage( data=open(filename, 'r').read(), filename=filename )
def test_namedblobimage_field_serialization_doesnt_choke_on_corrupt_image( self): """ In Plone >= 5.2 the original image file is not a "scale", so its url is returned as is and we need to check it, but the scales should be empty""" image_data = b"INVALID IMAGE DATA" fn = "test_namedblobimage_field" with patch.object(storage, "uuid4", return_value="uuid_1"): value = self.serialize( fn, NamedBlobImage(data=image_data, contentType=u"image/gif", filename=u"1024x768.gif"), ) obj_url = self.doc1.absolute_url() scale_url_uuid = "uuid_1" self.assertEqual( { u"content-type": u"image/gif", u"download": u"{}/@@images/{}.{}".format(obj_url, scale_url_uuid, "gif"), u"filename": u"1024x768.gif", u"height": -1, u"scales": {}, u"size": 18, u"width": -1, }, value, )
def updateSVG(context, normalizedTitle, pt): """ :param context: an object with ``abc`` and ``svgscore`` fields :type context: usualy a ABC object :param normalizedTitle: used for the blob filename :type normalizedTitle: string :param pt: tool :type pt: portal_tranform tool :returns: nothing, update the ``svgscore`` field of the object """ try: svgData = pt.convertTo( 'image/svg+xml', context.abc, context=context, annotate=True ) svgFilename = normalizedTitle + u'.svg' svgContenType = 'image/svg+xml' context.svgscore = NamedBlobImage() context.svgscore.data = svgData.getData() context.svgscore.filename = svgFilename context.svgscore.contentType = svgContenType except Exception: msg = u'Failed to create SVG score' logger.info(msg) annotateObject(context, msg=msg, key='ABC_ERRORS')
def test_namedblobimage_field_serialization_doesnt_choke_on_corrupt_image( self): """ Original image url will be None because the original image is corrupted and the created url should be an image scale """ image_data = b"INVALID IMAGE DATA" fn = "test_namedblobimage_field" with patch.object(storage, "uuid4", return_value="uuid_1"): value = self.serialize( fn, NamedBlobImage(data=image_data, contentType=u"image/gif", filename=u"1024x768.gif"), ) self.assertEqual( { u"content-type": u"image/gif", u"download": None, u"filename": u"1024x768.gif", u"height": -1, u"scales": {}, u"size": 18, u"width": -1, }, value, )
def test_get_content_related_items_without_workflow(self): intids = getUtility(IIntIds) self.portal.invokeFactory("Image", id="imagewf") self.portal.imagewf.title = "Image without workflow" self.portal.imagewf.description = "This is an image" image_file = os.path.join(os.path.dirname(__file__), "image.png") with open(image_file, "rb") as f: image_data = f.read() self.portal.imagewf.image = NamedBlobImage(data=image_data, contentType="image/png", filename="image.png") transaction.commit() self.portal.folder1.doc1.relatedItems = [ RelationValue(intids.getId(self.portal.imagewf)) ] transaction.commit() response = requests.get( self.portal.folder1.doc1.absolute_url(), headers={"Accept": "application/json"}, auth=(SITE_OWNER_NAME, SITE_OWNER_PASSWORD), ) self.assertEqual(response.status_code, 200) self.assertEqual(1, len(response.json()["relatedItems"])) self.assertEqual( [{ "@id": self.portal_url + "/imagewf", "@type": "Image", "description": "This is an image", "review_state": None, "title": "Image without workflow", }], response.json()["relatedItems"], )
def migrate_blobimagefield(src_obj, dst_obj, src_fieldname, dst_fieldname): """ migrate an image field. Actually this field needs only to copy the existing NamedBlobImage instance to the new dst_obj, but we do some more in detail and create new fields. """ old_image = getattr(src_obj, src_fieldname) if old_image == '': return filename = safe_unicode(old_image.filename) old_image_data = old_image.data if safe_hasattr(old_image_data, 'data'): old_image_data = old_image_data.data namedblobimage = NamedBlobImage(data=old_image_data, filename=filename) # set new field on destination object setattr(dst_obj, dst_fieldname, namedblobimage) # handle a possible image caption field field = '{0}_caption'.format(src_fieldname) old_image_caption = getattr(src_obj, field, None) if old_image_caption: setattr(dst_obj, ('{0}_caption'.format(dst_fieldname)), safe_unicode(old_image_caption)) logger.info(u'Migrating image {0}'.format(filename))
def _create_file(self, item, files, title, description, rights): namechooser = INameChooser(self.context) content_type = item.headers.get('Content-Type') filename = safe_unicode(item.filename) data = item.read() id_name = '' title = title and title[0] or filename id_name = namechooser.chooseName(title, self.context) if content_type in IMAGE_MIMETYPES: portal_type = 'Image' wrapped_data = NamedBlobImage(data=data, filename=filename) else: portal_type = 'File' wrapped_data = NamedBlobFile(data=data, filename=filename) self.context.invokeFactory(portal_type, id=id_name, title=title, description=description[0], rights=rights[0]) newfile = self.context[id_name] if portal_type == 'File': if IATFile.providedBy(newfile): newfile.setFile(data, filename=filename) else: newfile.file = wrapped_data elif portal_type == 'Image': if IATImage.providedBy(newfile): newfile.setImage(data, filename=filename) else: newfile.image = wrapped_data newfile.reindexObject() notify(ObjectModifiedEvent(newfile)) return newfile
def test_dexterity_news_item_get(self): self.portal.invokeFactory("News Item", id="newsitem") self.portal.newsitem.title = "My News Item" self.portal.newsitem.description = u"This is a news item" self.portal.newsitem.text = RichTextValue( u"Lorem ipsum", "text/plain", "text/html" ) image_file = os.path.join(os.path.dirname(__file__), u"image.png") fd = open(image_file, "rb") self.portal.newsitem.image = NamedBlobImage( data=fd.read(), contentType="image/png", filename=u"image.png" ) fd.close() self.portal.newsitem.image_caption = u"This is an image caption." import transaction transaction.commit() response = requests.get( self.portal.newsitem.absolute_url(), headers={"Accept": "application/json"}, auth=(SITE_OWNER_NAME, SITE_OWNER_PASSWORD), ) self.assertEqual(200, response.status_code) self.assertEqual(u"newsitem", response.json().get("id")) self.assertEqual(u"GET", response.json().get("method"))
def test_get_news_item(self): self.portal.invokeFactory('News Item', id='news1', title='News Item 1') image_file = os.path.join(os.path.dirname(__file__), u'image.png') self.portal.news1.image = NamedBlobImage(data=open(image_file, 'r').read(), contentType='image/png', filename=u'image.png') self.portal.news1.image_caption = u'This is an image caption.' transaction.commit() with patch.object(storage, 'uuid4', return_value='uuid1'): response = self.api_session.get(self.portal.news1.absolute_url()) self.assertEqual(response.status_code, 200) self.assertEqual( response.headers.get('Content-Type'), 'application/json', 'When sending a GET request with Content-Type: application/json ' + # noqa 'the server should respond with sending back application/json.' ) self.assertEqual( 'News Item', response.json().get('@type'), "Response should be @type 'News Item', not '{}'".format( response.json().get('@type'))) self.assertEqual(response.json().get('@id'), self.portal.news1.absolute_url()) self.assertEqual('News Item 1', response.json().get('title')) self.assertEqual(u'This is an image caption.', response.json()['image_caption']) self.assertDictContainsSubset( {'download': self.portal_url + u'/news1/@@images/uuid1.png' }, # noqa response.json()['image'])
def get_image(self, item): image_url = None if 'has_lead_image' in item: if item['has_lead_image']: image_url = 'https://%s%s/@@images/image' % (AGSCI_DOMAIN, item.get('path')) else: links = item.get('links', []) image_links = [ x.get('href', '') for x in links if x.get('rel', None) in ('enclosure', ) ] if image_links: image_url = image_links[0] if image_url: image_data = self.download_image(image_url) filename = image_url.split('/')[-1].split('?')[0] if filename: filename = safe_unicode(filename) else: filename = u'image' if image_data: return NamedBlobImage(filename=filename, data=image_data)
def update_file_content(self, info): type_, location = self.get_type_and_location(info) obj = uuidToObject(info['existing_id']) success = False msg = None if obj: if self.sm.checkPermission(ModifyPortalContent, obj): try: if info['field_name'].startswith('tmp_'): self.add_tmp_upload(obj, info) else: fi = open(info['tmp_file'], 'r') filename = ploneutils.safe_unicode(info['name']) if 'Image' in type_: blob = NamedBlobImage(data=fi, filename=filename) else: blob = NamedBlobFile(data=fi, filename=filename) setattr(obj, info['field_name'], blob) success = True except Exception: # could not update content logger.warning('Error updating content', exc_info=True) msg = 'Unknown error' else: msg = 'Invalid permissions' else: success = False msg = 'Object not found' return obj, success, msg
def test_lead_image(self): from plone.namedfile.file import NamedBlobImage filename = u'logo-plone-ok.png' self.newsitem.image = NamedBlobImage(data=get_file(filename), filename=filename) self.newsitem.image_caption = u'Mais amor, por favor!' amp = etree.HTML(self.view()) lead_image = amp.find('.//figure/amp-img') self.assertIsNotNone(lead_image) self.assertTrue(lead_image.attrib['src'].endswith(filename)) self.assertEqual(lead_image.attrib['layout'], 'responsive') self.assertEqual(lead_image.attrib['width'], '231') self.assertEqual(lead_image.attrib['height'], '60') self.assertEqual( amp.find('.//figure/figcaption').text, 'Mais amor, por favor!') # lead image information in metadata metadata = self._get_metadata_as_json(amp) self.assertIn('image', metadata) metadata = metadata['image'] # shortcut self.assertEqual(metadata['@type'], u'ImageObject') url = u'lorem-ipsum/@@download/image/{0}'.format(filename) self.assertTrue(metadata['url'].endswith(url)) self.assertEqual(metadata['width'], 231) self.assertEqual(metadata['height'], 60)