Esempio n. 1
0
    def do_import(self, workbook: IngestWorkbook, is_update, project_uuid=None, update_project=False,
                  worksheet_titles: List[str] = None):
        registry = _ImportRegistry(self.template_mgr)

        if worksheet_titles:
            importable_worksheets = workbook.select_importable_worksheets(worksheet_titles)
        else:
            importable_worksheets = workbook.importable_worksheets()

        workbook_errors = self.validate_worksheets(is_update, importable_worksheets)

        importable_worksheets = [ws for ws in importable_worksheets]

        for worksheet in importable_worksheets:
            try:
                self._import_worksheet(project_uuid, registry, update_project, workbook_errors, worksheet)
            except Exception as e:
                workbook_errors.append(
                    {"location": f'sheet={worksheet.title}', "type": e.__class__.__name__, "detail": str(e)})

        if not registry.has_project() and not project_uuid:
            e = NoProjectFound()
            workbook_errors.append({"location": "File", "type": e.__class__.__name__, "detail": str(e)})

        if project_uuid and update_project and not registry.has_project():
            workbook_errors.append({"location": "File", "type": "NoProjectWorksheet",
                                    "detail": "The option to update the project was specified but there is no project "
                                              "worksheet found."})

        if project_uuid and not registry.has_project():
            registry.add_project_reference(project_uuid)

        self._import_modules(registry, workbook_errors)

        return registry.flatten(), workbook_errors
Esempio n. 2
0
    def test_get_schemas(self):
        # given:
        workbook = Workbook()

        # and:
        schemas_sheet = workbook.create_sheet('Schemas')
        schemas_sheet['A1'] = 'schema'

        # and:
        base_url = 'https://schema.humancellatlas.org'
        expected_schemas = [
            f'{base_url}/type/biomaterial/cell_suspension',
            f'{base_url}type/biomaterial/organ_from_donor',
            f'{base_url}/type/process/library_preparation'
        ]
        header_offset = 2
        for index, schema in enumerate(expected_schemas):
            schemas_sheet[f'A{index + header_offset}'] = schema

        # and:
        ingest_workbook = IngestWorkbook(workbook)

        # when:
        actual_schemas = ingest_workbook.get_schemas()

        # then:
        self.assertEqual(expected_schemas, actual_schemas)
    def test_add_schemas_worksheet(self):
        # given
        sheets = ['A', 'B', 'C', 'X']
        workbook = create_test_workbook(*sheets)
        wb = IngestWorkbook(workbook)

        # when
        wb.add_schemas_worksheet(['schema1', 'schema2', 'schema3'])

        # then
        self.assertEqual(wb.workbook['Schemas'].cell(1, 1).value, 'Schemas')
        self.assertEqual(wb.workbook['Schemas'].cell(2, 1).value, 'schema1')
        self.assertEqual(wb.workbook['Schemas'].cell(3, 1).value, 'schema2')
        self.assertEqual(wb.workbook['Schemas'].cell(4, 1).value, 'schema3')
    def test_add_entity_uuids(self):
        # given:
        entities = [Entity('type', 'AA', 'content', concrete_type='a', ingest_json={'uuid': {'uuid': 'A-1-uuid'}},
                           spreadsheet_location={'row_index': 5, 'worksheet_title': 'A'}),
                    Entity('type', 'AA', 'content', concrete_type='a', ingest_json={'uuid': {'uuid': 'A-2-uuid'}},
                           spreadsheet_location={'row_index': 6, 'worksheet_title': 'A'}),
                    Entity('type', 'AA', 'content', concrete_type='a', ingest_json={'uuid': {'uuid': 'A-3-uuid'}},
                           spreadsheet_location={'row_index': 7, 'worksheet_title': 'A'}),
                    Entity('type', 'BB', 'content', concrete_type='b', ingest_json={'uuid': {'uuid': 'B-1-uuid'}},
                           spreadsheet_location={'row_index': 5, 'worksheet_title': 'B'}),
                    Entity('type', 'BB', 'content', concrete_type='b', ingest_json={'uuid': {'uuid': 'B-2-uuid'}},
                           spreadsheet_location={'row_index': 6, 'worksheet_title': 'B'}),
                    Entity('type', 'BB', 'content', concrete_type='b', ingest_json={'uuid': {'uuid': 'B-3-uuid'}},
                           spreadsheet_location={'row_index': 7, 'worksheet_title': 'B'}),
                    Entity('type', 'CC', 'content', concrete_type='c', ingest_json={'uuid': {'uuid': 'C-1-uuid'}},
                           spreadsheet_location={'row_index': 5, 'worksheet_title': 'C'}),
                    Entity('type', 'CC', 'content', concrete_type='c', ingest_json={'uuid': {'uuid': 'C-2-uuid'}},
                           spreadsheet_location={'row_index': 6, 'worksheet_title': 'C'}),
                    Entity('type', 'CC', 'content', concrete_type='c', ingest_json={'uuid': {'uuid': 'C-3-uuid'}},
                           spreadsheet_location={'row_index': 7, 'worksheet_title': 'C'}),
                    Entity('type', 'XX', 'content', concrete_type='x', ingest_json={'uuid': {'uuid': 'X-3-uuid'}})]

        mock_submission = Mock('submission')
        mock_submission.get_entities = Mock(return_value=entities)

        sheets = ['A', 'B', 'C', 'X']
        workbook = create_test_workbook(*sheets)
        wb = IngestWorkbook(workbook)

        # when
        wb.add_entity_uuids(mock_submission)

        # then
        self.assertEqual(wb.workbook['A'].cell(4, 1).value, 'a.uuid')
        self.assertEqual(wb.workbook['A'].cell(5, 1).value, 'A-1-uuid')
        self.assertEqual(wb.workbook['A'].cell(6, 1).value, 'A-2-uuid')
        self.assertEqual(wb.workbook['A'].cell(7, 1).value, 'A-3-uuid')

        self.assertEqual(wb.workbook['B'].cell(4, 1).value, 'b.uuid')
        self.assertEqual(wb.workbook['B'].cell(5, 1).value, 'B-1-uuid')
        self.assertEqual(wb.workbook['B'].cell(6, 1).value, 'B-2-uuid')
        self.assertEqual(wb.workbook['B'].cell(7, 1).value, 'B-3-uuid')

        self.assertEqual(wb.workbook['C'].cell(4, 1).value, 'c.uuid')
        self.assertEqual(wb.workbook['C'].cell(5, 1).value, 'C-1-uuid')
        self.assertEqual(wb.workbook['C'].cell(6, 1).value, 'C-2-uuid')
        self.assertEqual(wb.workbook['C'].cell(7, 1).value, 'C-3-uuid')

        self.assertFalse(wb.workbook['X'].cell(5, 1).value, None)
Esempio n. 5
0
    def test_importable_worksheets(self):
        # given:
        importable_names = ['Organ From Donor', 'Cell Suspension', 'Project']
        workbook = create_test_workbook(*importable_names)
        workbook.create_sheet('Schemas')

        # and:
        ingest_workbook = IngestWorkbook(workbook)

        # when:
        actual_worksheets = ingest_workbook.importable_worksheets()

        # then:
        actual_titles = [ingest_worksheet.title for ingest_worksheet in actual_worksheets]
        self.assertEqual(importable_names, actual_titles)
Esempio n. 6
0
 def update_spreadsheet_with_uuids(submission: Submission, template_mgr: TemplateManager, file_path):
     if not submission:
         return
     wb = IngestWorkbook.from_file(file_path, read_only=False)
     wb.add_entity_uuids(submission)
     wb.add_schemas_worksheet(template_mgr.get_schemas())
     return wb.save(file_path)
    def test_do_import_no_project(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer
        no_errors = []
        expected_error = {
            'location': 'File',
            'type': 'NoProjectFound',
            'detail': 'The spreadsheet should be associated to a project.'
        }

        # and:
        item = MetadataEntity(concrete_type='product',
                              domain_type='product',
                              object_id=910)
        worksheet_importer.do_import = MagicMock(side_effect=[([item],
                                                               no_errors)])

        # and:
        workbook = create_test_workbook('Item')
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        spreadsheet_json, errors = workbook_importer.do_import(
            IngestWorkbook(workbook), is_update=False)

        # then:
        self.assertIn(
            expected_error, errors,
            f'Errors expected to contain {NoProjectFound.__name__}.')
 def setup_workbook_with_project_worksheets(self,
                                            worksheet_importer_constructor):
     self.template_mgr.get_concrete_type = MagicMock(return_value='project')
     worksheet_importer = WorkbookImporter(self.template_mgr)
     worksheet_importer_constructor.return_value = worksheet_importer
     no_errors = []
     # and:
     project = MetadataEntity(domain_type='project',
                              concrete_type='project',
                              content={'description': 'test project'})
     jsmith = MetadataEntity(domain_type='project',
                             concrete_type='contact',
                             content={
                                 'contributors': {
                                     'name': 'John',
                                     'email': '*****@*****.**'
                                 }
                             })
     ppan = MetadataEntity(domain_type='project',
                           concrete_type='contact',
                           content={
                               'contributors': {
                                   'name': 'Peter',
                                   'email': '*****@*****.**'
                               }
                           })
     worksheet_importer.do_import = MagicMock(
         side_effect=[([project], no_errors), ([jsmith, ppan], no_errors)])
     # and:
     workbook = create_test_workbook('Project', 'Project - Contributors')
     ingest_workbook = IngestWorkbook(workbook)
     return ingest_workbook
Esempio n. 9
0
    def test_do_import_multiple_projects(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer

        # and:
        project_1 = MetadataEntity(concrete_type='project',
                                   domain_type='project',
                                   object_id=1)
        project_2 = MetadataEntity(concrete_type='project',
                                   domain_type='project',
                                   object_id=2)
        worksheet_importer.do_import = MagicMock(
            side_effect=[[project_1, project_2]])

        # and:
        workbook = create_test_workbook('Project')
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        exception_thrown = False
        try:
            workbook_importer.do_import(IngestWorkbook(workbook))
        except MultipleProjectsFound:
            exception_thrown = True

        # then:
        self.assertTrue(
            exception_thrown,
            f'Expected to throw {MultipleProjectsFound.__name__}.')
Esempio n. 10
0
    def test_do_import_no_projects(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer

        # and:
        item = MetadataEntity(concrete_type='product',
                              domain_type='product',
                              object_id=910)
        worksheet_importer.do_import = MagicMock(side_effect=[[item]])

        # and:
        workbook = create_test_workbook('Item')
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        thrown_exception = False
        try:
            workbook_importer.do_import(IngestWorkbook(workbook))
        except NoProjectFound:
            thrown_exception = True

        # then:
        self.assertTrue(thrown_exception,
                        f'Expected to throw {NoProjectFound.__name__}.')
 def setUp(self, worksheet_importer_constructor) -> None:
     self.template_mgr = MagicMock(name='template_manager')
     self.template_mgr.template.json_schemas = self.mock_json_schemas
     self.concrete_type_map = {'Project': 'project', 'Users': 'users'}
     self.template_mgr.get_concrete_type = lambda key: self.concrete_type_map.get(
         key)
     self.worksheet_importer = WorksheetImporter(self.template_mgr)
     worksheet_importer_constructor.return_value = self.worksheet_importer
     self.workbook_importer = WorkbookImporter(self.template_mgr)
     self.workbook = create_test_workbook('Project', 'Users')
     self.ingest_workbook = IngestWorkbook(self.workbook)
    def test_add_schemas_worksheet_existing_schemas(self):
        # given
        sheets = ['A', 'B', 'C']
        workbook = create_test_workbook(*sheets)
        wb = IngestWorkbook(workbook)

        wb.workbook.create_sheet('Schemas')
        wb.workbook['Schemas'].cell(1, 1).value = 'X'
        wb.workbook['Schemas'].cell(2, 1).value = 'x'
        wb.workbook['Schemas'].cell(3, 1).value = 'y'
        wb.workbook['Schemas'].cell(4, 1).value = 'z'

        # when
        wb.add_schemas_worksheet(['schema1', 'schema2', 'schema3'])

        # then
        self.assertEqual(wb.workbook['Schemas'].cell(1, 1).value, 'X')
        self.assertEqual(wb.workbook['Schemas'].cell(2, 1).value, 'x')
        self.assertEqual(wb.workbook['Schemas'].cell(3, 1).value, 'y')
        self.assertEqual(wb.workbook['Schemas'].cell(4, 1).value, 'z')
Esempio n. 13
0
    def test_do_import_project_worksheet(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorkbookImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer

        # and:
        project = MetadataEntity(domain_type='project',
                                 concrete_type='project',
                                 content={'description': 'test project'})
        jsmith = MetadataEntity(domain_type='project',
                                concrete_type='contact',
                                content={
                                    'contributors': {
                                        'name': 'John',
                                        'email': '*****@*****.**'
                                    }
                                })
        ppan = MetadataEntity(domain_type='project',
                              concrete_type='contact',
                              content={
                                  'contributors': {
                                      'name': 'Peter',
                                      'email': '*****@*****.**'
                                  }
                              })
        worksheet_importer.do_import = MagicMock(
            side_effect=[[project], [jsmith, ppan]])

        # and:
        workbook = create_test_workbook('Project', 'Project - Contributors')
        ingest_workbook = IngestWorkbook(workbook)
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        spreadsheet_json = workbook_importer.do_import(ingest_workbook)

        # then:
        project_map = spreadsheet_json.get('project')
        self.assertEqual(1, len(project_map))
        project_content = list(project_map.values())[0].get('content')
        self.assertEqual('test project', project_content.get('description'))

        # and:
        contributors = project_content.get('contributors')
        self.assertEqual(2, len(contributors))
        self.assertIn({
            'name': 'John',
            'email': '*****@*****.**'
        }, contributors)
        self.assertIn({
            'name': 'Peter',
            'email': '*****@*****.**'
        }, contributors)
Esempio n. 14
0
    def _generate_project_json_from_workbook(self, workbook):
        ingest_workbook = IngestWorkbook(workbook)
        template_mgr = self._setup_template_manager_for_project_import()
        workbook_importer = WorkbookImporter(template_mgr)
        spreadsheet_json, errors = workbook_importer.do_import(ingest_workbook, False, worksheet_titles=['Project'])

        if errors:
            return None, errors
        else:
            projects = list(spreadsheet_json.get('project').values())
            project = projects[0] if projects else None
            project_metadata = project.get('content')
            return project_metadata, []
Esempio n. 15
0
    def generate_json(self, file_path, is_update, project_uuid=None, update_project=False):
        ingest_workbook = IngestWorkbook.from_file(file_path)

        try:
            template_mgr = template_manager.build(ingest_workbook.get_schemas(), self.ingest_api)
        except Exception as e:
            raise SchemaRetrievalError(
                f'There was an error retrieving the schema information to process the spreadsheet. {str(e)}')

        workbook_importer = WorkbookImporter(template_mgr)
        spreadsheet_json, errors = workbook_importer.do_import(ingest_workbook, is_update, project_uuid, update_project)

        return spreadsheet_json, template_mgr, errors
Esempio n. 16
0
def create_ingest_workbook(sheet_names,
                           column_names,
                           include_default_sheet=False) -> IngestWorkbook:
    header_row_idx = 4

    workbook = Workbook()
    for sheet_name in sheet_names:
        worksheet = workbook.create_sheet(sheet_name)
        worksheet[f'A{header_row_idx}'] = f'{sheet_name}.{column_names[0]}'
        worksheet[f'B{header_row_idx}'] = f'{sheet_name}.{column_names[1]}'

    check_default_sheet_inclusion(include_default_sheet, workbook)

    return IngestWorkbook(workbook)
Esempio n. 17
0
    def test_importable_worksheets(self):
        # given:
        workbook = Workbook()

        # and:
        importable_names = ['Organ From Donor', 'Cell Suspension']
        expected_worksheets = [
            workbook.create_sheet(name) for name in importable_names
        ]
        workbook.create_sheet('Schemas')

        # and:
        default_worksheet = workbook.get_sheet_by_name('Sheet')
        workbook.remove_sheet(default_worksheet)

        # and:
        ingest_workbook = IngestWorkbook(workbook)

        # when:
        actual_worksheets = ingest_workbook.importable_worksheets()

        # then:
        self.assertEqual(expected_worksheets, actual_worksheets)
    def test_do_import_update_project_but_no_project_worksheet(self):
        # given:
        workbook = create_test_workbook('Users')

        # when:
        spreadsheet_json, errors = self.workbook_importer.do_import(
            IngestWorkbook(workbook),
            project_uuid='project-uuid',
            update_project=True,
            is_update=False)

        # then:
        self.assertEqual(len(errors), 1)
        self.assertEqual('NoProjectWorksheet', errors[0].get('type'))
    def test_do_import_do_not_update_project_and_no_project_worksheet(self):
        # given:
        workbook = create_test_workbook('Users')

        # when:
        spreadsheet_json, errors = self.workbook_importer.do_import(
            IngestWorkbook(workbook),
            project_uuid='project-uuid',
            update_project=False,
            is_update=False)

        # then:
        self.assertEqual(len(errors), 0)
        self.assertEqual(len(spreadsheet_json.get('project', {}).keys()), 1)
        self.assertFalse(
            spreadsheet_json['project']['project-uuid']['is_reference'])
        self.assertTrue(spreadsheet_json['project']['project-uuid']
                        ['is_linking_reference'])
Esempio n. 20
0
    def do_import(self, workbook: IngestWorkbook, project_uuid=None):
        registry = _ImportRegistry()

        for worksheet in workbook.importable_worksheets():
            metadata_entities = self.worksheet_importer.do_import(worksheet)
            module_field_name = worksheet.get_module_field_name()
            for entity in metadata_entities:
                if worksheet.is_module_tab():
                    entity.retain_content_fields(module_field_name)
                    registry.add_module(entity)
                else:
                    registry.add_submittable(entity)

        if registry.has_project():
            registry.import_modules()
        else:
            raise NoProjectFound()
        return registry.flatten()
Esempio n. 21
0
    def test_do_import(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer

        # and:
        project = MetadataEntity(concrete_type='project',
                                 domain_type='project')
        jdelacruz = MetadataEntity(concrete_type='user',
                                   domain_type='user',
                                   object_id=1,
                                   content={'user_name': 'jdelacruz'})
        setsuna_f_seiei = MetadataEntity(concrete_type='user',
                                         domain_type='user',
                                         object_id=96,
                                         content={'user_name': 'sayyeah'})
        worksheet_importer.do_import = MagicMock(
            side_effect=[[project], [jdelacruz, setsuna_f_seiei]])

        # and:
        workbook = create_test_workbook('Project', 'Users')
        ingest_workbook = IngestWorkbook(workbook)
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        workbook_json = workbook_importer.do_import(ingest_workbook)

        # then:
        self.assertIsNotNone(workbook_json)

        # and:
        user_map = workbook_json.get('user')
        self.assertIsNotNone(user_map)
        self.assertEqual(2, len(user_map))
        self.assertEqual([jdelacruz.object_id, setsuna_f_seiei.object_id],
                         list(user_map.keys()))

        # and:
        self.assertEqual({'user_name': 'jdelacruz'},
                         user_map.get(1)['content'])
        self.assertEqual({'user_name': 'sayyeah'}, user_map.get(96)['content'])
Esempio n. 22
0
    def do_import(self, workbook: IngestWorkbook, project_uuid=None):
        spreadsheet_json = {}

        self.import_or_reference_project(project_uuid, spreadsheet_json,
                                         workbook)

        for worksheet in workbook.importable_worksheets():
            concrete_entity = self.template_mgr.get_concrete_entity_of_tab(
                worksheet.title)
            domain_entity = self.template_mgr.get_domain_entity(
                concrete_entity)

            entities_dict = self.worksheet_importer.do_import(
                worksheet, self.template_mgr)
            if spreadsheet_json.get(domain_entity) is None:
                spreadsheet_json[domain_entity] = {}

            spreadsheet_json[domain_entity].update(entities_dict)

        return spreadsheet_json
Esempio n. 23
0
    def test_do_import(self, worksheet_importer_constructor):
        # given: set up template manager
        key_label_map = {
            'Project': 'project',
            'Cell Suspension': 'cell_suspension'
        }

        domain_entity_map = {
            'project': 'project',
            'cell_suspension': 'biomaterial'
        }

        mock_template_manager = MagicMock()
        mock_template_manager.get_concrete_entity_of_tab = lambda key: key_label_map.get(key)
        mock_template_manager.get_domain_entity = lambda key: domain_entity_map.get(key)

        # and: set up worksheet importer
        worksheet_importer = IdentifiableWorksheetImporter()
        expected_json = self._fake_worksheet_import(worksheet_importer, mock_template_manager)

        # and: set up workbook
        workbook = Workbook()
        ingest_workbook = IngestWorkbook(workbook)
        schema_list = self._mock_get_schemas(ingest_workbook)
        self._mock_importable_worksheets(ingest_workbook, workbook)

        # and: mock WorksheetImporter constructor
        worksheet_importer_constructor.return_value = worksheet_importer
        workbook_importer = WorkbookImporter(mock_template_manager)
        workbook_importer.import_or_reference_project = MagicMock()

        # when:
        workbook_output = workbook_importer.do_import(ingest_workbook)

        # then:
        self.assertEqual(2, len(list(workbook_output.keys())))
        self.assertEqual(['project', 'biomaterial'], list(workbook_output.keys()))
        self.assertEqual(2, len(list(workbook_output['project'].keys())))
        self.assertEqual(expected_json['project'], workbook_output['project'])
        self.assertEqual(expected_json['biomaterial'], workbook_output['biomaterial'])
    def test_do_import_multiple_projects(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        template_mgr.template.json_schemas = self.mock_json_schemas
        template_mgr.get_concrete_type = MagicMock(return_value='project')

        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer
        no_errors = []
        expected_error = {
            'location':
            'sheet=Project',
            'type':
            'MultipleProjectsFound',
            'detail':
            'The spreadsheet should only be associated to a single project.'
        }

        # and:
        project_1 = MetadataEntity(concrete_type='project',
                                   domain_type='project',
                                   object_id=1)
        project_2 = MetadataEntity(concrete_type='project',
                                   domain_type='project',
                                   object_id=2)
        worksheet_importer.do_import = MagicMock(
            side_effect=[([project_1, project_2], no_errors)])

        # and:
        workbook = create_test_workbook('Project')
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        spreadsheet_json, errors = workbook_importer.do_import(
            IngestWorkbook(workbook), is_update=False)

        # then:
        self.assertIn(
            expected_error, errors,
            f'Errors expected to contain {MultipleProjectsFound.__name__}.')
Esempio n. 25
0
 def _create_ingest_workbook(file_path):
     workbook = openpyxl.load_workbook(filename=file_path, read_only=True)
     return IngestWorkbook(workbook)
Esempio n. 26
0
    def test_do_import_with_module_tab(self, worksheet_importer_constructor):
        # given:
        template_mgr = MagicMock(name='template_manager')
        worksheet_importer = WorksheetImporter(template_mgr)
        worksheet_importer_constructor.return_value = worksheet_importer

        # and: stub worksheet importer
        project = MetadataEntity(concrete_type='Project',
                                 domain_type='Project')
        user = MetadataEntity(concrete_type='user',
                              domain_type='user',
                              object_id=773,
                              content={'user_name': 'janedoe'})
        fb_profile = MetadataEntity(concrete_type='sn_profile',
                                    domain_type='user',
                                    object_id=773,
                                    content={
                                        'sn_profiles': {
                                            'name': 'facebook',
                                            'id': '392'
                                        },
                                        'description': 'extra field'
                                    })
        ig_profile = MetadataEntity(concrete_type='sn_profile',
                                    domain_type='user',
                                    object_id=773,
                                    content={
                                        'sn_profiles': {
                                            'name': 'instagram',
                                            'id': 'a92'
                                        },
                                        'description': 'extra field'
                                    })
        worksheet_importer.do_import = MagicMock(
            side_effect=[[project], [user], [fb_profile, ig_profile]])

        # and: create test workbook
        workbook = create_test_workbook('Project', 'User',
                                        'User - SN Profiles')
        ingest_workbook = IngestWorkbook(workbook)
        workbook_importer = WorkbookImporter(template_mgr)

        # when:
        spreadsheet_json = workbook_importer.do_import(ingest_workbook)

        # then:
        self.assertIsNotNone(spreadsheet_json)
        self.assertEqual(2, len(spreadsheet_json))

        # and:
        user_map = spreadsheet_json.get('user')
        self.assertIsNotNone(user_map)

        # and:
        janedoe = user_map.get(773)
        self.assertIsNotNone(janedoe)
        content = janedoe.get('content')
        self.assertEqual('janedoe', content.get('user_name'))
        self.assertEqual(['user_name', 'sn_profiles'], list(content.keys()))

        # and:
        sn_profiles = content.get('sn_profiles')
        self.assertIsNotNone(sn_profiles)
        self.assertEqual(2, len(sn_profiles))

        # and:
        self.assertEqual({'name': 'facebook', 'id': '392'}, sn_profiles[0])
        self.assertEqual({'name': 'instagram', 'id': 'a92'}, sn_profiles[1])
    def test_do_import_with_module_tab(self, worksheet_importer_constructor):
        # given:
        concrete_type_map = {
            'Project': 'project',
            'User': '******',
            'User - SN Profiles': 'users'
        }
        self.template_mgr.get_concrete_type = lambda key: concrete_type_map.get(
            key)

        project = MetadataEntity(concrete_type='Project',
                                 domain_type='Project')
        user = MetadataEntity(concrete_type='user',
                              domain_type='user',
                              object_id=773,
                              content={'user_name': 'janedoe'})
        fb_profile = MetadataEntity(concrete_type='sn_profile',
                                    domain_type='user',
                                    object_id=773,
                                    content={
                                        'sn_profiles': {
                                            'name': 'facebook',
                                            'id': '392'
                                        },
                                        'description': 'extra fb field'
                                    })
        ig_profile = MetadataEntity(concrete_type='sn_profile',
                                    domain_type='user',
                                    object_id=773,
                                    content={
                                        'sn_profiles': {
                                            'name': 'instagram',
                                            'id': 'a92'
                                        },
                                        'description': 'extra ig field'
                                    })

        no_errors = []
        self.worksheet_importer.do_import = MagicMock(side_effect=[(
            [project],
            no_errors), ([user],
                         no_errors), ([fb_profile, ig_profile], no_errors)])

        self.workbook = create_test_workbook('Project', 'User',
                                             'User - SN Profiles')
        self.ingest_workbook = IngestWorkbook(self.workbook)

        # when:
        spreadsheet_json, errors = self.workbook_importer.do_import(
            self.ingest_workbook, is_update=False)

        # then:
        expected_errors = [{
            'key': 'description',
            'value': 'extra fb field'
        }, {
            'key': 'description',
            'value': 'extra ig field'
        }]

        self.assertIsNotNone(spreadsheet_json)
        self.assertEqual(
            errors,
            self.workbook_importer.list_data_removal_errors(
                'User - SN Profiles', expected_errors))
        self.assertEqual(2, len(spreadsheet_json))

        # and:
        user_map = spreadsheet_json.get('user')
        self.assertIsNotNone(user_map)

        # and:
        janedoe = user_map.get(773)
        self.assertIsNotNone(janedoe)
        content = janedoe.get('content')
        self.assertEqual('janedoe', content.get('user_name'))
        self.assertEqual(['user_name', 'sn_profiles'], list(content.keys()))

        # and:
        sn_profiles = content.get('sn_profiles')
        self.assertIsNotNone(sn_profiles)
        self.assertEqual(2, len(sn_profiles))

        # and:
        self.assertEqual({'name': 'facebook', 'id': '392'}, sn_profiles[0])
        self.assertEqual({'name': 'instagram', 'id': 'a92'}, sn_profiles[1])