def test_edit_entity(self): sess = mock.MagicMock() e = Entity( sess, self='https://host.com/something', name='entity name' ) e.edit(name='new entity name') call = sess.patch.call_args_list[0] assert call[0][0] == 'https://host.com/something' pl = json.loads(call[0][1]) assert pl == { 'element': 'shoji:entity', 'body': { 'name': 'new entity name' } } assert call[1] == { 'headers': { 'Content-Type': 'application/json' } } assert e.body['name'] == 'new entity name'
def test_detect_correct_handler(self): session = Mock(feature_flags={'old_projects_order': True}) dataset_order = Order(session, **{'graph': []}) datasets_catalog = Catalog(session, **{ 'index': {}, 'order': dataset_order }) shoji_resource = Entity( session, **{ 'self': '/project/url/', 'body': {}, 'index': {}, 'datasets': datasets_catalog }) project = Project(shoji_resource) self.assertTrue(isinstance(project.order, ProjectDatasetsOrder)) session = Mock(feature_flags={'old_projects_order': False}) shoji_resource = Entity( session, **{ 'self': '/project/url/', 'body': {}, 'index': {}, 'graph': [] }) project = Project(shoji_resource) self.assertTrue(isinstance(project.order, Project))
def test_create_does_post_entity(self): sess = mock.MagicMock() e = Entity(self='/entity/url/', session=sess) e.create({'somedata': 1}) sess.post.assert_called_once_with( '/entity/url/', json.dumps({"somedata": 1, "body": {}, "element": "shoji:entity"}, indent=4), headers={'Content-Type': 'application/json'} )
def test_create_does_post_entity(self): sess = mock.MagicMock() e = Entity(self='/entity/url/', session=sess) e.create({'somedata': 1}) sess.post.assert_called_once_with( '/entity/url/', json.dumps({"somedata": 1, "body": {}, "element": "shoji:entity"}, indent=None, separators=(',', ':')), headers={'Content-Type': 'application/json'} )
def test_unique_folders_no_secure(): session = MockSession() dataset_url = 'http://host/api/datasets/abc/' folders_url = 'http://host/api/datasets/abc/folders/' hidden_url = 'http://host/api/datasets/abc/folders/hidden/' trash_url = 'http://host/api/datasets/abc/folders/trash/' dataset_resource = Entity(session, **{ "element": "shoji:entity", "self": dataset_url, "body": { "name": "test_dataset_project" }, "catalogs": { "folders": folders_url, } }) dataset_resource.variables = MagicMock() dataset_resource.settings = MagicMock() folders_resource = Catalog(session, **{ "element": "shoji:catalog", "self": folders_url, "index": {}, "body": { "name": "Root" }, "catalogs": { "hidden": hidden_url, # Viewer users don't have the secure folder available # "secure": secure_url, "trash": trash_url, } }) hidden_resource = Catalog(session, **{ "element": "shoji:catalog", "self": hidden_url, "index": {}, "body": { "name": "Hidden" }, }) trash_resource = Catalog(session, **{ "element": "shoji:catalog", "self": trash_url, "index": {}, "body": { "name": "Trash" }, }) session.add_fixture(folders_url, folders_resource) session.add_fixture(hidden_url, hidden_resource) session.add_fixture(trash_url, trash_resource) dataset = MutableDataset(dataset_resource) assert dataset.folders.root.name == "Root" assert dataset.folders.hidden.name == "Hidden" assert dataset.folders.trash.name == "Trash" assert not hasattr(dataset.folders, "secure")
def test_replace_entity(self): sess = mock.MagicMock() e = Entity(sess, self='https://host.com/something', name='entity name') e.replace() call = sess.put.call_args_list[0] assert call[0][0] == 'https://host.com/something' assert json.loads(call[0][1]) == { "self": "https://host.com/something", "name": "entity name", "element": "shoji:entity", "body": {} } assert call[1] == {'headers': {'Content-Type': 'application/json'}}
def test_edit_entity(self): sess = mock.MagicMock() e = Entity(sess, self='https://host.com/something', name='entity name') e.edit(name='new entity name') call = sess.patch.call_args_list[0] assert call[0][0] == 'https://host.com/something' pl = json.loads(call[0][1]) assert pl == { 'element': 'shoji:entity', 'body': { 'name': 'new entity name' } } assert call[1] == {'headers': {'Content-Type': 'application/json'}} assert e.body['name'] == 'new entity name'
def test_entities_can_have_index(self): ent_url = '/entity/url/' session = mock.Mock() body = { 'attr': 'val' } index = { 'url1/': {'key': 'val1'}, 'url2/': {'key': 'val2'} } ent = Entity(session, **{ 'self': ent_url, 'body': body, 'index': index }) self.assertTrue(isinstance(ent.index, Index)) self.assertEqual(ent.by('key')['val1'].entity_url, 'url1/')
def test_unique_folders_no_hidden(): session = MockSession() dataset_url = 'http://host/api/datasets/abc/' folders_url = 'http://host/api/datasets/abc/folders/' dataset_resource = Entity(session, **{ "element": "shoji:entity", "self": dataset_url, "body": { "name": "test_dataset_project" }, "catalogs": { "folders": folders_url, } }) dataset_resource.variables = MagicMock() dataset_resource.settings = MagicMock() folders_resource = Catalog(session, **{ "element": "shoji:catalog", "self": folders_url, "index": {}, "body": { "name": "Root" }, "catalogs": { # Standard exposed catalogs "personal": "./personal/", "parents": "./parents/", # Viewer users don't have the secure folder available # "secure": secure_url, # Viewers also don't get the hidden folder exposed # "hidden": hidden_url, # Nor the trash # "trash": trash_url, } }) session.add_fixture(folders_url, folders_resource) dataset = MutableDataset(dataset_resource) assert dataset.folders.root.name == "Root" assert not hasattr(dataset.folders, "secure") assert not hasattr(dataset.folders, "hidden") assert not hasattr(dataset.folders, "trash")
def test_replace_entity(self): sess = mock.MagicMock() e = Entity( sess, self='https://host.com/something', name='entity name' ) e.replace() call = sess.put.call_args_list[0] assert call[0][0] == 'https://host.com/something' assert json.loads(call[0][1]) == { "self": "https://host.com/something", "name": "entity name", "element": "shoji:entity", "body": {} } assert call[1] == { 'headers': { 'Content-Type': 'application/json' } }
def test_combine_categories_from_entity(self): ds = mock.MagicMock() ds.__class__ = Dataset ds.combine_categories = Dataset.combine_categories var_url = 'http://test.crunch.io/api/datasets/123/variables/0001/' ds.entity.self = 'http://test.crunch.io/api/datasets/123/' entity_mock = mock.MagicMock() entity_mock.entity.self = var_url ds.variables.by.return_value = {'test': entity_mock} entity = Entity(mock.MagicMock(), self=var_url, body={}) ds.combine_categories(ds, entity, CATEGORY_MAP, 'name', 'alias') call = ds.variables.create.call_args_list[0][0][0] assert call == RECODES_PAYLOAD
def test_variable_as_attribute(self): session = mock.MagicMock() test_variable = mock.MagicMock() test_variable.entity = Entity(session=session) variables = { 'test_variable': test_variable } dataset = Dataset({}) dataset.variables = mock.MagicMock() dataset.variables.by.return_value = variables assert isinstance(dataset.test_variable, Entity) with pytest.raises(AttributeError) as err: dataset.another_variable assert str(err.value) == 'Dataset has no attribute another_variable'
def test_create_subproject(self): session = MockSession() session.feature_flags = {'old_projects_order': False} shoji_resource = Entity(session, **{ 'self': 'http://example.com/project/url/', 'body': {}, 'index': {}, 'graph': [], }) # Setup the POST request and the fixture for the GET that happens after # the .refresh() created_project_url = 'http://example.com/project/2/' response = Response() response.status_code = 201 response.headers = { 'Location': created_project_url } session.add_post_response(response) session.add_fixture(created_project_url, { 'self': created_project_url, 'body': {}, 'index': {}, 'graph': [], }) project = Project(shoji_resource) # Create a new project pa = project.order.create_project("Project A") self.assertTrue(isinstance(pa, Project)) # Check that we sent the correct payload to the server self.assertEqual(pa.url, created_project_url) post_request = session.requests[-2] refresh_request = session.requests[-1] self.assertEqual(refresh_request.method, 'GET') self.assertEqual(post_request.method, 'POST') self.assertEqual(post_request.url, project.url) self.assertEqual(json.loads(post_request.body), { 'element': 'shoji:entity', 'body': { 'name': 'Project A' } })
def test_create_script(self): session = MockSession() scripts_url = "https://example.com/dataset/url/scripts/" shoji_resource = Entity( session, **{ 'self': 'https://example.com/dataset/url/', 'body': {}, "catalogs": { "scripts": scripts_url } }) created_script_url = 'https://example.com/script/2/' response = Response() response.status_code = 201 response.headers = {'Location': created_script_url} session.add_fixture(scripts_url, { "element": "shoji:catalog", "self": scripts_url, "index": {} }) session.add_post_response(response) session.add_fixture(created_script_url, { 'self': created_script_url, 'body': {}, }) scripts = DatasetScripts(shoji_resource) scripts.execute("<script body>") post_request = session.requests[-1] self.assertEqual(post_request.method, 'POST') self.assertEqual(post_request.url, scripts_url) self.assertEqual(json.loads(post_request.body), { 'element': 'shoji:entity', 'body': { 'body': "<script body>" } })
def test_collapse_scripts(self): session = MockSession() scripts_url = "https://example.com/dataset/url/scripts/" collapse_url = "https://example.com/dataset/url/scripts/collapse/" shoji_resource = Entity( session, **{ 'self': 'https://example.com/dataset/url/', 'body': {}, "catalogs": { "scripts": scripts_url } }) response = Response() response.status_code = 204 session.add_fixture( scripts_url, { "element": "shoji:catalog", "self": scripts_url, "index": {}, "views": { "collapse": collapse_url } }) session.add_fixture(collapse_url, { "element": "shoji:view", "self": collapse_url, "value": {}, }) session.add_post_response(response) scripts = DatasetScripts(shoji_resource) scripts.collapse() post_request = session.requests[-1] self.assertEqual(post_request.method, 'POST') self.assertEqual(post_request.url, collapse_url) self.assertEqual(json.loads(post_request.body), {})
def test_combine_responses_by_entity(self): ds = mock.MagicMock() ds.__class__ = Dataset ds.combine_responses = Dataset.combine_responses var_url = 'http://test.crunch.io/api/datasets/123/variables/0001/' subvar1_url = 'http://test.crunch.io/api/datasets/123/variables/0001/subvariables/00001/' subvar2_url = 'http://test.crunch.io/api/datasets/123/variables/0001/subvariables/00002/' ds.entity.self = 'http://test.crunch.io/api/datasets/123/' # mock subvariables subvar_mock = mock.MagicMock() subvar_mock.entity.self = subvar1_url subvar2_mock = mock.MagicMock() subvar2_mock.entity.self = subvar2_url # mock parent variable entity_mock = mock.MagicMock() entity_mock.entity.self = var_url # add dictionaries return to by functions entity_mock.entity.subvariables.by.return_value = { 'sub1': subvar_mock, 'sub2': subvar2_mock } ds.variables.by.return_value = {'test': entity_mock} # mock response from ds.session.get(variable_url) var_response = mock.MagicMock() var_response.payload = entity_mock.entity ds.session.get.return_value = var_response entity = Entity(mock.MagicMock(), self=var_url, body={}) # make the actual response call ds.combine_responses(ds, entity, RESPONSE_MAP, 'name', 'alias') call = ds.variables.create.call_args_list[0][0][0] assert call == COMBINE_RESPONSES_PAYLOAD
def test_recode_multiple_responses(self, get_dataset_mock): dataset_id = '123' categories = [{ 'numeric_value': 1, 'selected': True, 'id': 1, 'name': 'selected', 'missing': False }, { 'numeric_value': 2, 'selected': False, 'id': 2, 'name': 'not selected', 'missing': False }, { 'numeric_value': 9, 'missing': True, 'id': 9, 'name': 'not asked' }, { 'numeric_value': 8, 'missing': True, 'id': 8, 'name': 'skipped' }] var_res = Entity( mock.MagicMock(), **{ 'element': 'shoji:entity', 'self': 'http://test.crunch.io/api/datasets/%s/variables/0001/' % dataset_id, # needed in order to simulate a Tuple, now Variable is inited with Tuple 'entity_url': 'http://test.crunch.io/api/datasets/%s/variables/0001/' % dataset_id, 'body': { 'name': 'Q1', 'subreferences': [{ 'alias': 'Q1_1', 'is_subvar': True, 'name': 'One' }, { 'alias': 'Q1_2', 'is_subvar': True, 'name': 'Two' }, { 'alias': 'Q1_3', 'is_subvar': True, 'name': 'Three' }], 'missing_reasons': { 'skipped': 8, 'not asked': 9 }, 'alias': 'Q1', 'subvariables': [ 'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000a/' % dataset_id, 'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000b/' % dataset_id, 'http://test.crunch.io/api/datasets/%s/variables/0001/subvariables/000c/' % dataset_id ], 'dataset_id': dataset_id, 'type': 'multiple_response', 'id': '0001', 'categories': categories, 'description': 'Multiple Response Example' } }) table_mock = mock.MagicMock( metadata={ '00001': { 'id': '00001', 'alias': 'sexuality', 'type': 'categorical', 'categories': categories } }) ds_res = mock.MagicMock() Variable(var_res, ds_res) ds_res.self = dataset_url ds_res.follow.return_value = table_mock dataset = Dataset(ds_res) subvar_mock = mock.MagicMock() subvar_mock.self = var_url subvar_mock.id = 'subvar' subvariables = { 'Q1_1': subvar_mock, 'Q1_2': subvar_mock, 'Q1_3': subvar_mock, } dataset.create_categorical( [{ 'id': 1, 'name': 'Q1_recoded_1', 'case': mr_in(var_url, 'Q1', [1, 2], subvariables) }, { 'id': 2, 'name': 'Q1_recoded_2', 'case': mr_in(var_url, 'Q1', [3], subvariables) }], alias='Q1_recoded', name='Q1_recoded', multiple=True) # Test how the recoded var was created. ds_res.variables.create.assert_called_with({ 'element': 'shoji:entity', 'body': { 'name': 'Q1_recoded', 'description': '', 'alias': 'Q1_recoded', 'derivation': { 'function': 'array', 'args': [{ 'function': 'select', 'args': [{ 'map': { '0001': { 'function': 'case', 'args': [{ 'column': [1, 2], 'type': { 'value': { 'class': 'categorical', 'categories': [{ 'selected': True, 'numeric_value': None, 'missing': False, 'id': 1, 'name': 'Selected' }, { 'selected': False, 'numeric_value': None, 'missing': False, 'id': 2, 'name': 'Not selected' }] } } }, { 'function': 'any', 'args': [{ 'variable': 'http://test.crunch.io/api/datasets/123/variables/0001/' }, { 'column': ['subvar', 'subvar'] }] }], 'references': { 'alias': 'Q1_recoded_1', 'name': 'Q1_recoded_1' } }, '0002': { 'function': 'case', 'args': [{ 'column': [1, 2], 'type': { 'value': { 'class': 'categorical', 'categories': [{ 'selected': True, 'numeric_value': None, 'missing': False, 'id': 1, 'name': 'Selected' }, { 'selected': False, 'numeric_value': None, 'missing': False, 'id': 2, 'name': 'Not selected' }] } } }, { 'function': 'any', 'args': [{ 'variable': 'http://test.crunch.io/api/datasets/123/variables/0001/' }, { 'column': ['subvar'] }] }], 'references': { 'alias': 'Q1_recoded_2', 'name': 'Q1_recoded_2' } } } }] }] } } })