def test_pixel_size_units(self): # Create image iid = self.create_test_image(size_c=2, session=self.sf).id.val # show right panel for image request_url = reverse('load_metadata_details', args=['image', iid]) data = {} rsp = get(self.django_client, request_url, data, status_code=200) html = rsp.content.decode("utf-8") # Units are µm by default value = "Pixels Size (XYZ) (" + u"µm):" assert value in html # Now save units as PIXELs and view again conn = omero.gateway.BlitzGateway(client_obj=self.client) i = conn.getObject("Image", iid) u = omero.model.LengthI(1.2, UnitsLength.PIXEL) p = i.getPrimaryPixels()._obj p.setPhysicalSizeX(u) p.setPhysicalSizeY(u) conn.getUpdateService().saveObject(p) # Should now be showing pixels rsp = get(self.django_client, request_url, data, status_code=200) html = rsp.content.decode("utf-8") assert "Pixels Size (XYZ):" in html assert "1.20 (pixel)" in html
def test_new_group_form(self, privileges): """Form should show correct fields for editing Group / Membership.""" exp = self.new_user(privileges=privileges) ome_name = exp.omeName.val django_client = self.new_django_client(ome_name, ome_name) # Only users with "ModifyGroup" see "Create Group" btn on groups page can_modify = 'ModifyGroup' in privileges request_url = reverse('wagroups') rsp = get(django_client, request_url) groups_html = rsp.content assert ('<span>Add new Group</span>' in groups_html) == can_modify # Check new group form has correct fields for privileges request_url = reverse('wamanagegroupid', args=["new"]) rsp = get(django_client, request_url) form_html = rsp.content assert ('name="name"' in form_html) == can_modify assert ('name="description"' in form_html) == can_modify assert ('name="permissions"' in form_html) == can_modify can_add_members = 'ModifyGroupMembership' in privileges assert ('name="owners"' in form_html) == can_add_members assert ('name="members"' in form_html) == can_add_members
def test_base64_thumb_set(self): """ Test base64 encoded retrival of thumbnails in a batch """ # Create a square image images = [] for i in range(2, 5): iid = self.create_test_image(size_x=64 * i, size_y=64 * i, session=self.sf).id.val images.append(iid) expected_thumbs = {} for i in images: request_url = reverse('webgateway_render_thumbnail', args=[i]) rsp = get(self.django_client, request_url) expected_thumbs[i] = \ "data:image/jpeg;base64,%s" % \ base64.b64encode(rsp.content).decode("utf-8") iids = {'id': images} request_url = reverse('webgateway_get_thumbnails_json') b64rsp = get(self.django_client, request_url, iids).content json_data = json.loads(b64rsp) for i in images: assert json_data[str(i)] == expected_thumbs[i]
def test_base64_thumb_set(self): """ Test base64 encoded retrival of thumbnails in a batch """ # Create a square image images = [] for i in range(2, 5): iid = self.create_test_image(size_x=64 * i, size_y=64 * i, session=self.sf).id.val images.append(iid) expected_thumbs = {} for i in images: request_url = reverse('webgateway.views.render_thumbnail', args=[i]) rsp = get(self.django_client, request_url) expected_thumbs[i] = \ "data:image/jpeg;base64,%s" % base64.b64encode(rsp.content) iids = {'id': images} request_url = reverse('webgateway.views.get_thumbnails_json') b64rsp = get(self.django_client, request_url, iids).content assert cmp(json.loads(b64rsp), json.loads(json.dumps(expected_thumbs))) == 0 assert json.dumps(expected_thumbs) == b64rsp
def test_render_image_region_tile_params_big_image(self, tmpdir): """ Tests the retrieval of pyramid image at different resolution. Resolution changes is supported in that case. """ image_id = self.import_pyramid(tmpdir, client=self.client) request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image_id), 'z': '0', 't': '0' }) django_client = self.new_django_client_from_session_id( self.client.getSessionId()) data = {} try: data['tile'] = '0,0,0,512,512' response = get(django_client, request_url, data) tile_content = response.content tile = Image.open(BytesIO(tile_content)) assert tile.size == (512, 512) digest = self.calculate_sha1(tile_content) # request another resolution. It should default to 0 data['tile'] = '1,0,0,512,512' response = get(django_client, request_url, data) tile_res_content = response.content tile = Image.open(BytesIO(tile_res_content)) assert tile.size == (512, 512) digest_res = self.calculate_sha1(tile_res_content) assert digest != digest_res finally: self.assert_no_leaked_rendering_engines()
def test_bad_settings(self, settings, menu): assert menu not in settings.MAPR_CONFIG.keys() with pytest.raises(NoReverseMatch) as excinfo: request_url = reverse("maprindex_%s" % menu) get(self.django_client, request_url, {}, status_code=200) regx = r"Reverse for 'maprindex_%s'.*" % menu assert excinfo.match(regx)
def test_render_image_region_tile_params_invalid_resolution(self): """ Tests the retrieval of image at an invalid resolution. """ image_id = self.create_test_image(size_x=512, size_y=512, session=self.sf).id.val conn = omero.gateway.BlitzGateway(client_obj=self.client) image = conn.getObject("Image", image_id) image._prepareRenderingEngine() image._re.close() request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image.getId()), 'z': '0', 't': '0' }) django_client = self.new_django_client_from_session_id( self.client.getSessionId()) data = {} try: data['tile'] = '1,0,0,200,200' get(django_client, request_url, data, status_code=400) finally: self.assert_no_leaked_rendering_engines()
def test_render_image_region_region_params_big_image(self, tmpdir): """ Tests the retrieval of pyramid image at different resolution. Resolution changes is supported in that case. """ image_id = self.import_pyramid(tmpdir, client=self.client) request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image_id), 'z': '0', 't': '0' }) django_client = self.new_django_client_from_session_id( self.client.getSessionId()) data = {} try: data['region'] = '0,0,512,512' response = get(django_client, request_url, data) region = Image.open(BytesIO(response.content)) assert region.size == (512, 512) data['region'] = '0,0,2000,2000' response = get(django_client, request_url, data) region = Image.open(BytesIO(response.content)) assert region.size == (2000, 2000) finally: self.assert_no_leaked_rendering_engines()
def test_render_image_region_big_image_resolution(self, tmpdir): """ Tests the retrieval of pyramid image at different resolution. Resolution changes is supported in that case. """ image_id = self.import_pyramid(tmpdir, client=self.client) conn = omero.gateway.BlitzGateway(client_obj=self.client) image = conn.getObject("Image", image_id) image._prepareRenderingEngine() levels = image._re.getResolutionLevels() image._re.close() request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image_id), 'z': '0', 't': '0' }) django_client = self.new_django_client_from_session_id( self.client.getSessionId()) data = {} try: data['tile'] = '%s,0,0,512,512' % levels get(django_client, request_url, data, status_code=400) finally: self.assert_no_leaked_rendering_engines()
def test_batch_annotate_tag(self): # Create User in a Read-Annotate group client1, user1 = self.new_client_and_user(perms='rwrw--') omeName = client1.sf.getAdminService().getEventContext().userName django_client = self.new_django_client(omeName, omeName) # User1 creates Tag and 2 Datasets ds1 = self.make_dataset("batch_Dataset1", client=client1) ds2 = self.make_dataset("batch_Dataset2", client=client1) tag1 = self.make_tag("test_batch_annotate1", client=client1) tag2 = self.make_tag("test_batch_annotate2", client=client1) # Batch Annotate panel should have 'Tags' request_url = reverse('batch_annotate') request_url += '?dataset=%s&dataset=%s' % (ds1.id.val, ds2.id.val) rsp = get(django_client, request_url) assert b'2 objects' in rsp.content # can't check for 'Tags 0' since html splits these up assert b'<span class="annotationCount">0</span>' in rsp.content assert b'<span class="annotationCount">1</span>' not in rsp.content # Add 1 Tag to 1 Dataset annotate_tags_dataset(django_client, ds1.id.val, [tag1.id.val]) rsp = get(django_client, request_url) assert b'<span class="annotationCount">1</span>' in rsp.content # Add 2 Tags to other Dataset annotate_tags_dataset(django_client, ds2.id.val, [tag1.id.val, tag2.id.val]) rsp = get(django_client, request_url) assert b'<span class="annotationCount">2</span>' in rsp.content
def test_bad_settings(self, settings, menu): assert menu not in list(settings.MAPR_CONFIG.keys()) with pytest.raises(NoReverseMatch) as excinfo: request_url = reverse("maprindex_%s" % menu) get(self.django_client, request_url, {}, status_code=200) regx = r"Reverse for 'maprindex_%s'.*" % menu assert excinfo.match(regx)
def test_batch_add_fileannotations(self, link_count): """Test adding file annotation to Project(s).""" client, user = self.new_client_and_user(perms='rwrw--') omeName = client.sf.getAdminService().getEventContext().userName django_client1 = self.new_django_client(omeName, omeName) # User creates 2 Projects pr1 = self.make_project("test_batch_file_ann1", client=client) pr2 = self.make_project("test_batch_file_ann2", client=client) pr_ids = [pr1.id.val, pr2.id.val] # Create File and FileAnnotation fname = "fname_%s" % client.getSessionId() update = client.sf.getUpdateService() f = omero.model.OriginalFileI() f.name = omero.rtypes.rstring(fname) f.path = omero.rtypes.rstring("") f = update.saveAndReturnObject(f) fa = omero.model.FileAnnotationI() fa.setFile(f) fa = update.saveAndReturnObject(fa) # get form for annotating both Projects request_url = reverse('annotate_file') data = {"project": pr_ids} rsp = get(django_client1, request_url, data) html = rsp.content.decode('utf-8') assert fname in html # Link File Annotation to 1 or 2 Projects post_data = {"project": pr_ids[0:link_count], "files": [fa.id.val]} post(django_client1, request_url, post_data) # Check for link to first Project api_ann_url = reverse('api_annotations') rsp = get_json(django_client1, api_ann_url, {"project": pr1.id.val}) assert fa.id.val in [a['id'] for a in rsp['annotations']] # Annotation Form should NOT show file if linked to BOTH projects show_file = link_count == 1 rsp = get(django_client1, request_url, data) html = rsp.content.decode('utf-8') assert (fname in html) == show_file # Remove file from both Projects remove_url = reverse('manage_action_containers', kwargs={ 'action': 'remove', 'o_type': 'file', 'o_id': fa.id.val }) remove_data = { 'parent': 'project-%s|project-%s' % (pr1.id.val, pr2.id.val) } post(django_client1, remove_url, remove_data) # Check for NO link rsp = get_json(django_client1, api_ann_url, {"project": pr1.id.val}) assert fa.id.val not in [a['id'] for a in rsp['annotations']]
def test_orphaned_image_direct_download(self): """ Download of archived files for a non-SPW orphaned Image. """ images = self.import_fake_file() image = images[0] # download archived files request_url = reverse('archived_files', args=[image.id.val]) get(self.django_client, request_url)
def test_well_download(self, image_well_plate): """ Download of archived files for a SPW Well. """ plate, well, image = image_well_plate # download archived files request_url = reverse('webgateway.views.archived_files') data = {"well": well.id.val} get(self.django_client, request_url, data, status_code=404)
def test_edit_channel_names(self): """ CSRF protection does not check `GET` requests so we need to be sure that this request results in an HTTP 405 (method not allowed) status code. """ img = self.image_with_channels() data = {'channel0': 'foobar'} request_url = reverse('edit_channel_names', args=[img.id.val]) get(self.django_client, request_url, data, status_code=405, csrf=True) post(self.django_client, request_url, data)
def test_spw_download(self, image_well_plate): """ Download of an Image that is part of a plate should be disabled, and return a 404 response. """ plate, well, image = image_well_plate # download archived files request_url = reverse('webgateway.views.archived_files') data = {"image": image.id.val} get(self.django_client, request_url, data, status_code=404)
def test_orphaned_image_download(self): """ Download of archived files for a non-SPW orphaned Image. """ images = self.import_fake_file() image = images[0] # download archived files request_url = reverse('webgateway.views.archived_files') data = {"image": image.id.val} get(self.django_client, request_url, data)
def test_attachment_download(self): """ Download of attachment. """ images = self.import_fake_file() image = images[0] fa = self.make_file_annotation() self.link(image, fa) # download archived files request_url = reverse('download_annotation', args=[fa.id.val]) get(self.django_client, request_url)
def test_ome_tiff_script(self): """ CSRF protection does not check `GET` requests so we need to be sure that this request results in an HTTP 405 (method not allowed) status code. """ img = self.create_test_image(session=self.sf) request_url = reverse('ome_tiff_script', args=[img.id.val]) post(self.django_client, request_url, {}) get(self.django_client, request_url, status_code=405)
def test_su(self): """ CSRF protection does not check `GET` requests so we need to be sure that this request results in an HTTP 405 (method not allowed) status code. """ user = self.new_user() request_url = reverse('webgateway_su', args=[user.omeName.val]) get(self.django_root_client, request_url, {}, csrf=True) post(self.django_root_client, request_url)
def test_table_html(self, omero_table_file, django_client, table_data): """Do a GET request to query table data.""" file_id = omero_table_file # expected table data col_types, col_names, rows = table_data col_types = [cls.__name__ for cls in col_types] # GET json request_url = reverse("omero_table", args=[file_id, 'json']) rsp = get_json(django_client, request_url) assert rsp['data']['rows'] == rows assert rsp['data']['columns'] == col_names assert rsp['data']['column_types'] == col_types assert rsp['data']['name'].startswith('omero_table_test') assert rsp['data']['id'] == file_id # GET html request_url = reverse("omero_table", args=[file_id]) rsp = get(django_client, request_url) html = rsp.content.decode("utf-8") for col_type, col in zip(col_types, col_names): assert ('<th title="%s">%s</th>' % (col_type, col)) in html well_col_index = col_types.index('WellColumn') for row in rows: for idx, td in enumerate(row): if idx != well_col_index: assert ('<td>%s</td>' % td) in html else: # link to webclient link = reverse('webindex') link_html = ('<a target="_blank" href="%s?show=well-%s">' % (link, td)) assert link_html in html # GET csv request_url = reverse("omero_table", args=[file_id, 'csv']) rsp = get(django_client, request_url) chunks = [c.decode("utf-8") for c in rsp.streaming_content] csv_data = "".join(chunks) cols_csv = ','.join(col_names) rows.append(['']) # add empty row (as found in exported csv) def wrap_commas(value): return str(value) if "," not in str(value) else '"%s"' % value rows_csv = '\r\n'.join( [','.join([wrap_commas(td) for td in row]) for row in rows]) assert csv_data == '%s\r\n%s' % (cols_csv, rows_csv)
def test_image_in_dataset_download(self): """ Download of archived files for a non-SPW Image in Dataset. """ images = self.import_fake_file() image = images[0] ds = self.make_dataset() self.link(ds, image) # download archived files request_url = reverse('webgateway.views.archived_files') data = {"image": image.id.val} get(self.django_client, request_url, data)
def test_download_images_as_zip(self, format): """Test we can download a zip with multiple images.""" name1 = "test_downloadA_zip" name2 = "test_downloadB_zip" xy = 50 image1 = self.create_test_image(name=name1, size_x=xy, size_y=xy, session=self.sf) image2 = self.create_test_image(name=name2, size_x=xy, size_y=xy, session=self.sf) # test download placeholder html request_url = reverse('download_placeholder') data = { 'ids': 'image-%s|image-%s' % (image1.id.val, image2.id.val), 'format': format } rsp = get(self.django_client, request_url, data) html = rsp.content.decode('utf-8') assert "You have chosen to export 2 images" in html assert ("Export_as_%s.zip" % format) in html # download zip zipName = 'Export_as_%s.zip' % format request_url = reverse('download_as') data = { 'image': [image1.id.val, image2.id.val], 'zipname': zipName, 'format': format } rsp = get(self.django_client, request_url, data) assert rsp.get('Content-Disposition') == \ "attachment; filename=%s" % zipName data = b"".join(rsp.streaming_content) assert len(data) > 0 filenames = [] with ZipFile(BytesIO(data)) as zip: for info in zip.infolist(): filenames.append(info.filename) img_data = zip.read(info.filename) img = Image.open(BytesIO(img_data)) assert img.size == (xy, xy) assert len(filenames) == 2 assert "%s.%s" % (name1, format) in filenames assert "%s.%s" % (name2, format) in filenames
def test_table_bitmask(self, omero_table_file, django_client, query_result): """ Test query of table data as bitmask. Resulting IDs are represented as a bit mask where the index of each ID in the bit mask is shown as 1. E.g. 1,3 & 6 => "0101001" (maybe extra 0 added) """ file_id = omero_table_file request_url = reverse("webgateway_table_obj_id_bitmask", args=[file_id]) query, expected = query_result url = request_url + '?%s' % query rsp = get(django_client, url) bitmask = rsp.content # convert string into byte array and unpack numbers = [int(by) for by in bitmask] bits = np.unpackbits(np.array(numbers, dtype=np.uint8)) # convert bits to string for comparison bitStr = ''.join([str(b) for b in bits]) assert bitStr.startswith(expected) # Any extra 0 padding should contain no "1" assert "1" not in bitStr.replace(expected, "")
def test_render_image_region_region_params(self): """ Tests the retrieval of the image using the region parameter """ image = self.import_fake_file(name='fake')[0] conn = omero.gateway.BlitzGateway(client_obj=self.client) image = conn.getObject("Image", image.id.val) image._prepareRenderingEngine() image._re.close() request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image.getId()), 'z': '0', 't': '0' }) data = {'region': '0,0,10,10'} django_client = self.new_django_client_from_session_id( self.client.getSessionId()) try: response = get(django_client, request_url, data) tile = Image.open(BytesIO(response.content)) assert tile.size == (10, 10) finally: self.assert_no_leaked_rendering_engines()
def test_render_image_region_tile_params_large_image(self): """ Tests the retrieval of large non pyramid image. """ image_id = self.create_test_image(size_x=3000, size_y=3000, session=self.sf).id.val conn = omero.gateway.BlitzGateway(client_obj=self.client) image = conn.getObject("Image", image_id) image._prepareRenderingEngine() image._re.close() request_url = reverse('webgateway_render_image_region', kwargs={ 'iid': str(image.getId()), 'z': '0', 't': '0' }) django_client = self.new_django_client_from_session_id( self.client.getSessionId()) data = {} try: data['tile'] = '0,0,0,512,512' response = get(django_client, request_url, data) tile_content = response.content tile = Image.open(BytesIO(tile_content)) assert tile.size == (512, 512) finally: self.assert_no_leaked_rendering_engines()
def test_add_fileannotations_form(self): # Create User in a Read-Annotate group client, user = self.new_client_and_user(perms='rwrw--') # conn = omero.gateway.BlitzGateway(client_obj=client) omeName = client.sf.getAdminService().getEventContext().userName django_client1 = self.new_django_client(omeName, omeName) # User creates Dataset ds = self.make_dataset("user1_Dataset", client=client) # Create File and FileAnnotation update = client.sf.getUpdateService() f = omero.model.OriginalFileI() f.name = omero.rtypes.rstring("") f.path = omero.rtypes.rstring("") f = update.saveAndReturnObject(f) fa = omero.model.FileAnnotationI() fa.setFile(f) fa = update.saveAndReturnObject(fa) # get form for annotating Dataset request_url = reverse('annotate_file') data = {"dataset": ds.id.val} rsp = get(django_client1, request_url, data) html = rsp.content expected_name = b"No name. ID %d" % fa.id.val assert expected_name in html
def test_avatar(self): photo_url = reverse('wamyphoto') # first get the placeholder photo old_photo = get(self.django_client, photo_url) try: temp = tempfile.NamedTemporaryFile(suffix='.png') img = Image.new("RGB", (200, 200), "#FFFFFF") draw = ImageDraw.Draw(img) r, g, b = rint(0, 255), rint(0, 255), rint(0, 255) for i in range(200): draw.line((i, 0, i, 200), fill=(int(r), int(g), int(b))) img.save(temp, "PNG") temp.seek(0) img_data = temp.read() temp.seek(0) request_url = reverse('wamanageavatar', kwargs={"action": "upload"}) data = {'filename': 'avatar.png', "photo": temp} csrf_response(self.django_client, request_url, 'post', data, status_code=302, test_csrf_required=False) finally: temp.close() # check photo has changed and matches what we uploaded rsp = get(self.django_client, photo_url) assert old_photo.content != rsp.content assert rsp.content == img_data # Delete photo request_url = reverse('wamanageavatar', kwargs={"action": "deletephoto"}) csrf_response(self.django_client, request_url, 'post', {}, status_code=302, test_csrf_required=False) # Should get placeholder photo again rsp = get(self.django_client, photo_url) assert rsp.content == old_photo.content
def test_get_login_page(self): """ Simply test if a GET of the login url returns login page """ django_client = Client() request_url = reverse('weblogin') rsp = get(django_client, request_url, {}, status_code=200) assert 'OMERO.web - Login' in rsp.content
def test_reset_rendering_settings(self): """ CSRF protection does not check `GET` requests so we need to be sure that this request results in an HTTP 405 (method not allowed) status code. """ img = self.create_test_image(session=self.sf) # Reset through webclient as it is calling directly # webgateway.reset_image_rdef_json request_url = reverse('reset_rdef_json') data = {'toids': img.id.val, 'to_type': 'image'} post(self.django_client, request_url, data) get(self.django_client, request_url, data, status_code=405) get(self.django_client, request_url, data, status_code=405, csrf=True)
def test_copy_past_rendering_settings_from_image(self): # Create 2 images with 2 channels each iid1 = self.create_test_image(size_c=2, session=self.sf).id.val iid2 = self.create_test_image(size_c=2, session=self.sf).id.val conn = omero.gateway.BlitzGateway(client_obj=self.client) # image1 set color model image1 = conn.getObject("Image", iid1) image1.resetDefaults() image1.setColorRenderingModel() image1.setQuantizationMap(0, "logarithmic", 0.5) image1.saveDefaults() image1 = conn.getObject("Image", iid1) # image2 set greyscale model image2 = conn.getObject("Image", iid2) image2.setGreyscaleRenderingModel() image2.saveDefaults() image2 = conn.getObject("Image", iid2) assert image1.isGreyscaleRenderingModel() is False assert image2.isGreyscaleRenderingModel() is True img1_chan = image1.getChannels()[0] assert img1_chan.getFamily().getValue() == 'logarithmic' assert img1_chan.getCoefficient() == 0.5 img2_chan = image2.getChannels()[0] assert img2_chan.getFamily().getValue() == 'linear' assert img2_chan.getCoefficient() == 1.0 # copy rendering settings from image1 via ID request_url = reverse('copy_image_rdef_json') data = {"fromid": iid1} get(self.django_client, request_url, data) # paste rendering settings to image2 data = {'toids': iid2} post(self.django_client, request_url, data) image2 = conn.getObject("Image", iid2) assert image2.isGreyscaleRenderingModel() is False img2_chan = image2.getChannels()[0] assert img2_chan.getFamily().getValue() == 'logarithmic' assert img2_chan.getCoefficient() == 0.5
def test_settings(self, settings): assert len(settings.MAPR_CONFIG.keys()) > 0 for menu in settings.MAPR_CONFIG.keys(): request_url = reverse("maprindex_%s" % menu) get(self.django_client, request_url, {}, status_code=200)