def test_update_compound_hets_variant_tags(self): variant_tags = VariantTag.objects.filter(saved_variants__guid__in=[COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID]) self.assertEqual(len(variant_tags), 0) update_variant_tags_url = reverse( update_variant_tags_handler, args=[','.join([COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID])]) _check_login(self, update_variant_tags_url) response = self.client.post(update_variant_tags_url, content_type='application/json', data=json.dumps({ 'tags': [{'name': 'Review'}, {'name': 'Excluded'}], 'familyGuid': 'F000001_1' })) self.assertEqual(response.status_code, 200) response_json = response.json() compound_het_1_tag_guids = response_json['savedVariantsByGuid'][COMPOUND_HET_1_GUID]['tagGuids'] compound_het_2_tag_guids = response_json['savedVariantsByGuid'][COMPOUND_HET_2_GUID]['tagGuids'] self.assertEqual(len(compound_het_1_tag_guids), 2) self.assertEqual(len(compound_het_2_tag_guids), 2) self.assertSetEqual({"Review", "Excluded"}, { vt['name'] for vt in response_json['variantTagsByGuid'].values() if vt['tagGuid'] in compound_het_1_tag_guids }) self.assertSetEqual({"Review", "Excluded"}, { vt['name'] for vt in response_json['variantTagsByGuid'].values() if vt['tagGuid'] in compound_het_2_tag_guids }) self.assertSetEqual( {"Review", "Excluded"}, {vt.variant_tag_type.name for vt in VariantTag.objects.filter( saved_variants__guid__in=[COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID])})
def test_saved_variant_data(self, mock_reference): mock_reference.return_value.get_genes.side_effect = lambda gene_ids: {gene_id: {'geneId': gene_id} for gene_id in gene_ids} url = reverse(saved_variant_data, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) variants = response.json()['savedVariants'] self.assertSetEqual(set(variants.keys()), {'SV0000002_1248367227_r0390_100', 'SV0000001_2103343353_r0390_100'}) variant = variants['SV0000001_2103343353_r0390_100'] self.assertSetEqual( set(variant.keys()), {'variantId', 'xpos', 'ref', 'alt', 'chrom', 'pos', 'genomeVersion', 'liftedOverGenomeVersion', 'liftedOverChrom', 'liftedOverPos', 'familyGuid', 'tags', 'functionalData', 'notes', 'clinvar', 'origAltAlleles', 'geneIds', 'genotypes', 'hgmd', 'annotation', 'transcripts', 'locusLists'} ) # filter by family response = self.client.get('{}?family=F000002_2'.format(url)) self.assertEqual(response.status_code, 200) self.assertSetEqual(set(response.json()['savedVariants'].keys()), {'SV0000002_1248367227_r0390_100'}) # filter by variant guid response = self.client.get('{}{}'.format(url, VARIANT_GUID)) self.assertEqual(response.status_code, 200) self.assertSetEqual(set(response.json()['savedVariants'].keys()), {VARIANT_GUID}) # filter by invalid variant guid response = self.client.get('{}foo'.format(url)) self.assertEqual(response.status_code, 404)
def test_gene_info(self, mock_reference): mock_reference.return_value.get_gene.return_value = deepcopy(MOCK_GENE) mock_reference.return_value.get_tissue_expression_display_values.return_value = [] url = reverse(gene_info, args=[GENE_ID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) gene = response.json()[GENE_ID] self.assertDictEqual( gene, { 'geneId': GENE_ID, 'geneName': 'TTN', 'phenotypeInfo': {}, 'expression': [], 'notes': [], 'constraints': { 'lof': { 'constraint': None, 'rank': None, 'totalGenes': None }, 'missense': { 'constraint': None, 'rank': None, 'totalGenes': None }, } })
def test_add_and_remove_project_locus_lists(self): project = Project.objects.get(guid=PROJECT_GUID) self.assertListEqual(list(get_project_locus_list_models(project)), []) # add a locus list url = reverse(add_project_locus_lists, args=[PROJECT_GUID]) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps( {'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], [LOCUS_LIST_GUID]) self.assertListEqual(list(get_project_locus_list_models(project)), [LocusList.objects.get(guid=LOCUS_LIST_GUID)]) # remove a locus list url = reverse(delete_project_locus_lists, args=[PROJECT_GUID]) response = self.client.post(url, content_type='application/json', data=json.dumps( {'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], []) self.assertListEqual(list(get_project_locus_list_models(project)), [])
def test_update_mme_result_status(self): url = reverse(update_mme_result_status, args=[RESULT_STATUS_GUID]) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({ 'matchmakerResultGuid': RESULT_STATUS_GUID, 'comments': 'test comment', 'deemedIrrelevant': False, 'flagForAnalysis': True, })) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertDictEqual(response_json, {'mmeResultsByGuid': {RESULT_STATUS_GUID: { 'matchStatus': { 'matchmakerResultGuid': RESULT_STATUS_GUID, 'comments': 'test comment', 'weContacted': False, 'hostContacted': True, 'deemedIrrelevant': False, 'flagForAnalysis': True, 'createdDate': '2019-02-12T18:43:56.358Z', }, }}}) result_model = MatchmakerResult.objects.get(guid=RESULT_STATUS_GUID) self.assertEqual(result_model.comments, 'test comment')
def test_create_update_and_delete_project(self): create_project_url = reverse(create_project_handler) _check_login(self, create_project_url) # check validation of bad requests response = self.client.post(create_project_url, content_type='application/json', data=json.dumps({'bad_json': None})) self.assertEqual(response.status_code, 400) response = self.client.post(create_project_url, content_type='application/json', data=json.dumps({'form': {'missing_name': True}})) self.assertEqual(response.status_code, 400) # send valid request to create project response = self.client.post(create_project_url, content_type='application/json', data=json.dumps( {'name': 'new_project', 'description': 'new project description'} )) self.assertEqual(response.status_code, 200) # check that project was created new_project = Project.objects.filter(name='new_project') self.assertEqual(len(new_project), 1) self.assertEqual(new_project[0].description, 'new project description') # delete the project delete_project_url = reverse(delete_project_handler, args=[new_project[0].guid]) response = self.client.post(delete_project_url, content_type='application/json') self.assertEqual(response.status_code, 200) # check that project was deleted new_project = Project.objects.filter(name='new_project') self.assertEqual(len(new_project), 0)
def test_update_variant_functional_data(self): variant_functional_data = VariantFunctionalData.objects.filter(saved_variants__guid__contains=VARIANT_GUID) self.assertSetEqual( {"Biochemical Function", "Genome-wide Linkage"}, {vt.functional_data_tag for vt in variant_functional_data}) self.assertSetEqual({"A note", "2"}, {vt.metadata for vt in variant_functional_data}) update_variant_tags_url = reverse(update_variant_functional_data_handler, args=[VARIANT_GUID]) _check_login(self, update_variant_tags_url) response = self.client.post(update_variant_tags_url, content_type='application/json', data=json.dumps({ 'functionalData': [ {'tagGuid': 'VFD0000023_1248367227_r0390_10', 'name': 'Biochemical Function', 'metadata': 'An updated note'}, {'name': 'Bonferroni corrected p-value', 'metadata': 0.05} ], 'familyGuid': 'F000001_1' })) self.assertEqual(response.status_code, 200) functional_data_guids = response.json()['savedVariantsByGuid'][VARIANT_GUID]['functionalDataGuids'] self.assertEqual(len(functional_data_guids), 2) new_guid = next(guid for guid in functional_data_guids if guid != 'VFD0000023_1248367227_r0390_10') functional_data = response.json()['variantFunctionalDataByGuid'] self.assertIsNone(functional_data['VFD0000024_1248367227_r0390_10']) self.assertEqual(functional_data['VFD0000023_1248367227_r0390_10']['name'], 'Biochemical Function') self.assertEqual(functional_data['VFD0000023_1248367227_r0390_10']['metadata'], 'An updated note') self.assertEqual(functional_data[new_guid]['name'], 'Bonferroni corrected p-value') self.assertEqual(functional_data[new_guid]['metadata'], 0.05) variant_functional_data = VariantFunctionalData.objects.filter(saved_variants__guid__contains=VARIANT_GUID) self.assertSetEqual( {"Biochemical Function", "Bonferroni corrected p-value"}, {vt.functional_data_tag for vt in variant_functional_data}) self.assertSetEqual({"An updated note", "0.05"}, {vt.metadata for vt in variant_functional_data})
def test_search_context(self): search_context_url = reverse(search_context_handler) _check_login(self, search_context_url) response = self.client.get('{}?foo=bar'.format(search_context_url)) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Invalid query params: {"foo": "bar"}') response = self.client.get('{}?projectGuid={}'.format(search_context_url, PROJECT_GUID)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) response = self.client.get('{}?familyGuid=F000001_1'.format(search_context_url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) response = self.client.get('{}?analysisGroupGuid=AG0000183_test_group'.format(search_context_url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) response = self.client.get('{}?projectCategoryGuid=PC000003_test_category_name'.format(search_context_url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', 'projectCategoriesByGuid'} ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) self.assertListEqual(response_json['projectCategoriesByGuid'].keys(), ['PC000003_test_category_name'])
def test_update_mme_contact_note(self): url = reverse(update_mme_contact_note, args=['GeneDx']) _check_login(self, url) # Test create response = self.client.post(url, content_type='application/json', data=json.dumps({ 'institution': 'GeneDx', 'comments': 'test comment', })) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {'mmeContactNotes': {'genedx': { 'institution': 'genedx', 'comments': 'test comment', }}}) models = MatchmakerContactNotes.objects.filter(institution='genedx') self.assertEqual(models.count(), 1) self.assertEqual(models.first().comments, 'test comment') # Test update response = self.client.post(url, content_type='application/json', data=json.dumps({ 'institution': 'GeneDx', 'comments': 'test comment update', })) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {'mmeContactNotes': {'genedx': { 'institution': 'genedx', 'comments': 'test comment update', }}}) models = MatchmakerContactNotes.objects.filter(institution='genedx') self.assertEqual(models.count(), 1) self.assertEqual(models.first().comments, 'test comment update')
def test_update_variant_tags(self): variant_tags = VariantTag.objects.filter(saved_variant__guid=VARIANT_GUID) self.assertSetEqual({"Review", "Tier 1 - Novel gene and phenotype"}, {vt.variant_tag_type.name for vt in variant_tags}) variant_functional_data = VariantFunctionalData.objects.filter(saved_variant__guid=VARIANT_GUID) self.assertSetEqual({"Biochemical Function", "Genome-wide Linkage"}, {vt.functional_data_tag for vt in variant_functional_data}) self.assertSetEqual({"A note", "2"}, {vt.metadata for vt in variant_functional_data}) update_variant_tags_url = reverse(update_variant_tags_handler, args=[VARIANT_GUID]) _check_login(self, update_variant_tags_url) response = self.client.post(update_variant_tags_url, content_type='application/json', data=json.dumps({ 'tags': [{'tagGuid': 'VT1708633_2103343353_r0390_100', 'name': 'Review'}, {'name': 'Excluded'}], 'functionalData': [ {'tagGuid': 'VFD0000023_1248367227_r0390_10', 'name': 'Biochemical Function', 'metadata': 'An updated note'}, {'name': 'Bonferroni corrected p-value', 'metadata': 0.05} ] })) self.assertEqual(response.status_code, 200) tags = response.json()['savedVariantsByGuid'][VARIANT_GUID]['tags'] self.assertEqual(len(tags), 2) self.assertSetEqual({"Review", "Excluded"}, {vt['name'] for vt in tags}) self.assertSetEqual({"Review", "Excluded"}, {vt.variant_tag_type.name for vt in VariantTag.objects.filter(saved_variant__guid=VARIANT_GUID)}) functionalData = response.json()['savedVariantsByGuid'][VARIANT_GUID]['functionalData'] self.assertEqual(len(functionalData), 2) self.assertSetEqual({"Biochemical Function", "Bonferroni corrected p-value"}, {vt['name'] for vt in functionalData}) self.assertSetEqual({"An updated note", "0.05"}, {vt['metadata'] for vt in functionalData}) variant_functional_data = VariantFunctionalData.objects.filter(saved_variant__guid=VARIANT_GUID) self.assertSetEqual({"Biochemical Function", "Bonferroni corrected p-value"}, {vt.functional_data_tag for vt in variant_functional_data}) self.assertSetEqual({"An updated note", "0.05"}, {vt.metadata for vt in variant_functional_data})
def test_add_and_remove_project_locus_lists(self): existing_guid = 'LL00005_retina_proteome' # add a locus list url = reverse(add_project_locus_lists, args=[PROJECT_GUID]) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps( {'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], [LOCUS_LIST_GUID, existing_guid]) ll_projects = LocusList.objects.get( guid=LOCUS_LIST_GUID).projects.all() self.assertEqual(ll_projects.count(), 2) self.assertTrue(PROJECT_GUID in {p.guid for p in ll_projects}) # remove a locus list url = reverse(delete_project_locus_lists, args=[PROJECT_GUID]) response = self.client.post(url, content_type='application/json', data=json.dumps( {'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], [existing_guid]) ll_projects = LocusList.objects.get( guid=LOCUS_LIST_GUID).projects.all() self.assertEqual(ll_projects.count(), 1) self.assertFalse(PROJECT_GUID in {p.guid for p in ll_projects})
def test_individuals_table_handler(self): individuals_url = reverse(receive_individuals_table_handler, args=[PROJECT_GUID]) _check_login(self, individuals_url) data = 'Family ID Individual ID Paternal ID Maternal ID Sex Affected Status Notes\n\ "1" "NA19675" "NA19678" "NA19679" "Female" "Affected" "A affected individual, test1-zsf"\n\ "1" "NA19678" "" "" "Male" "Unaffected" "a individual note"\n\ "2" "HG00733" "" "" "Female" "Unaffected" ""' f = SimpleUploadedFile("1000_genomes demo_individuals.tsv", data) response = self.client.post(individuals_url, {'f': f}) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['info', 'errors', 'warnings', 'uploadedFileId']) url = reverse(save_individuals_table_handler, args=[PROJECT_GUID, response_json['uploadedFileId']]) response = self.client.post(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['individualsByGuid', 'familiesByGuid'])
def test_saved_variant_data(self): url = reverse(saved_variant_data, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) variants = response.json()['savedVariantsByGuid'] self.assertSetEqual(set(variants.keys()), {'SV0000002_1248367227_r0390_100', 'SV0000001_2103343353_r0390_100'}) variant = variants['SV0000001_2103343353_r0390_100'] self.assertSetEqual( set(variant.keys()), {'variantId', 'variantGuid', 'xpos', 'ref', 'alt', 'chrom', 'pos', 'genomeVersion', 'liftedOverGenomeVersion', 'liftedOverChrom', 'liftedOverPos', 'familyGuids', 'tags', 'functionalData', 'notes', 'clinvar', 'originalAltAlleles', 'mainTranscript', 'genotypes', 'hgmd', 'transcripts', 'locusListGuids', 'populations', 'predictions', 'rsid', 'genotypeFilters'} ) self.assertSetEqual(set(variant['genotypes'].keys()), {'I000003_na19679', 'I000001_na19675', 'I000002_na19678'}) # filter by family response = self.client.get('{}?families=F000002_2'.format(url)) self.assertEqual(response.status_code, 200) self.assertSetEqual(set(response.json()['savedVariantsByGuid'].keys()), {'SV0000002_1248367227_r0390_100'}) # filter by variant guid response = self.client.get('{}{}'.format(url, VARIANT_GUID)) self.assertEqual(response.status_code, 200) self.assertSetEqual(set(response.json()['savedVariantsByGuid'].keys()), {VARIANT_GUID}) # filter by invalid variant guid response = self.client.get('{}foo'.format(url)) self.assertEqual(response.status_code, 404)
def test_get_hpo_terms(self): url = reverse(get_hpo_terms, args=['HP:0011458']) _check_login(self, url) response = self.client.get(url, content_type='application/json') self.assertEqual(response.status_code, 200) self.assertDictEqual( response.json(), { 'HP:0011458': { 'HP:0002017': { 'id': 'HP:0002017', 'category': 'HP:0025031', 'label': 'Nausea and vomiting' }, 'HP:0001252': { 'id': 'HP:0001252', 'category': 'HP:0025031', 'label': 'Muscular hypotonia' }, } }) url = reverse(get_hpo_terms, args=['HP:0002017']) response = self.client.get(url, content_type='application/json') self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), {'HP:0002017': {}})
def test_update_mme_result_status(self): url = reverse(update_mme_result_status, args=[RESULT_STATUS_GUID]) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({ 'matchmakerResultGuid': RESULT_STATUS_GUID, 'comments': 'test comment', 'deemedIrrelevant': False, 'flagForAnalysis': True, })) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertDictEqual(response_json, {'mmeResultsByGuid': {RESULT_STATUS_GUID: { 'matchStatus': { 'matchmakerResultGuid': RESULT_STATUS_GUID, 'comments': 'test comment', 'weContacted': False, 'hostContacted': True, 'deemedIrrelevant': False, 'flagForAnalysis': True, 'matchRemoved': False, 'createdDate': '2019-02-12T18:43:56.358Z', }, }}}) result_model = MatchmakerResult.objects.get(guid=RESULT_STATUS_GUID) self.assertEqual(result_model.comments, 'test comment')
def test_receive_alignment_table_handler(self): url = reverse(receive_alignment_table_handler, args=[PROJECT_GUID]) _check_login(self, url) # Send invalid requests f = SimpleUploadedFile('samples.csv', b"NA19675\nNA19679,gs://readviz/NA19679.bam") response = self.client.post(url, data={'f': f}) self.assertEqual(response.status_code, 400) self.assertDictEqual(response.json(), {'errors': ['Must contain 2 columns: NA19675']}) f = SimpleUploadedFile('samples.csv', b"NA19675, /readviz/NA19675.cram\nNA19679,gs://readviz/NA19679.bam") response = self.client.post(url, data={'f': f}) self.assertEqual(response.status_code, 400) self.assertDictEqual(response.json(), {'errors': ['The following Individual IDs do not exist: NA19675']}) # Send valid request f = SimpleUploadedFile('samples.csv', b"NA19675_1,/readviz/NA19675.cram\nNA19679,gs://readviz/NA19679.bam") response = self.client.post(url, data={'f': f}) self.assertEqual(response.status_code, 200) self.assertDictEqual(response.json(), { 'uploadedFileId': mock.ANY, 'errors': [], 'info': ['Parsed 2 rows from samples.csv', 'No change detected for 1 individuals'], 'updatesByIndividualGuid': {'I000003_na19679': 'gs://readviz/NA19679.bam'}, })
def test_delete_mme_submission(self): url = reverse(delete_mme_submission, args=[INDIVIDUAL_GUID]) _check_login(self, url) responses.add(responses.DELETE, 'http://localhost:9020/patient/delete', body='Failed request', status=400) responses.add(responses.DELETE, 'http://localhost:9020/patient/delete', status=200) response = self.client.post(url) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Failed request') response = self.client.post(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertEqual( response_json['individualsByGuid'][INDIVIDUAL_GUID]['mmeDeletedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) # Test proxy calls self.assertEqual(len(responses.calls), 2) self.assertEqual(responses.calls[1].request.url, 'http://localhost:9020/patient/delete') self.assertEqual(responses.calls[1].request.headers['X-Auth-Token'], 'abcd') self.assertEqual(responses.calls[1].request.headers['Accept'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.headers['Content-Type'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.body, json.dumps({'id': 'NA19675_1_01'})) # Test do not delete if already deleted response = self.client.post(url) self.assertEqual(response.status_code, 402) self.assertEqual(response.reason_phrase, 'Matchmaker submission has already been deleted for NA19675_1')
def test_gene_info(self): url = reverse(gene_info, args=[GENE_ID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) gene = response.json()[GENE_ID] self.assertSetEqual( set(gene.keys()), { 'chromGrch37', 'chromGrch38', 'codingRegionSizeGrch37', 'codingRegionSizeGrch38', 'constraints', 'diseaseDesc', 'endGrch37', 'endGrch38', 'functionDesc', 'gencodeGeneType', 'geneId', 'geneSymbol', 'omimPhenotypes', 'startGrch37', 'startGrch38', 'notes', 'expression', })
def test_update_family_pedigree_image(self): url = reverse(update_family_pedigree_image, args=[FAMILY_GUID]) _check_login(self, url) f = SimpleUploadedFile("new_ped_image_123.png", b"file_content") # send invalid request response = self.client.post(url, {'f1': f, 'f2': f}) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Received 2 files') # send valid add/update request response = self.client.post(url, {'f': f}) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['F000001_1']) self.assertRegex(response_json['F000001_1']['pedigreeImage'], '/media/pedigree_images/new_ped_image_.+\.png') # send valid delete request response = self.client.post(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['F000001_1']) self.assertIsNone(response_json['F000001_1']['pedigreeImage'])
def test_update_family_assigned_analyst(self): url = reverse(update_family_assigned_analyst, args=[FAMILY_GUID]) _check_login(self, url) # send invalid username (without permission) response = self.client.post(url, content_type='application/json', data=json.dumps({'assigned_analyst_username': '******'})) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'specified user does not exist') # send valid request response = self.client.post(url, content_type='application/json', data=json.dumps({'assigned_analyst_username': '******'})) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), [FAMILY_GUID]) self.assertEqual(response_json[FAMILY_GUID]['assignedAnalyst']['email'], '*****@*****.**') self.assertEqual(response_json[FAMILY_GUID]['assignedAnalyst']['fullName'], 'Test User') # unassign analyst response = self.client.post(url, content_type='application/json', data=json.dumps({})) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), [FAMILY_GUID]) self.assertIsNone(response_json[FAMILY_GUID]['assignedAnalyst'])
def test_saved_search(self): get_saved_search_url = reverse(get_saved_search_handler) _check_login(self, get_saved_search_url) response = self.client.get(get_saved_search_url) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()['savedSearchesByGuid']), 3) create_saved_search_url = reverse(create_saved_search_handler) response = self.client.post(create_saved_search_url, content_type='application/json', data='{}') self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, '"Name" is required') body = {'name': 'Test Search'} body.update(SEARCH) response = self.client.post(create_saved_search_url, content_type='application/json', data=json.dumps(body)) self.assertEqual(response.status_code, 200) saved_searches = response.json()['savedSearchesByGuid'] self.assertEqual(len(saved_searches), 1) search_guid = saved_searches.keys()[0] self.assertDictEqual( saved_searches[search_guid], { 'savedSearchGuid': search_guid, 'name': 'Test Search', 'search': SEARCH, }) response = self.client.get(get_saved_search_url) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()['savedSearchesByGuid']), 4)
def test_receive_families_table_handler(self): url = reverse(receive_families_table_handler, args=[PROJECT_GUID]) _check_login(self, url) # send request with a "families" attribute data = b'Family ID Display Name Description Coded Phenotype\n\ "1" "1" "family one description" ""\n\ "2" "2" "family two description" ""' f = SimpleUploadedFile("1000_genomes demo_families.tsv", data) response = self.client.post(url, {'f': f}) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['info', 'errors', 'warnings', 'uploadedFileId']) url = reverse(edit_families_handler, args=[PROJECT_GUID]) response = self.client.post(url, content_type='application/json', data=json.dumps({'uploadedFileId': response_json['uploadedFileId']})) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), ['familiesByGuid']) self.assertListEqual(response_json['familiesByGuid'].keys(), [FAMILY_GUID2, FAMILY_GUID]) self.assertEqual(response_json['familiesByGuid'][FAMILY_GUID]['description'], 'family one description') self.assertEqual(response_json['familiesByGuid'][FAMILY_GUID2]['description'], 'family two description')
def test_delete_mme_submission(self): url = reverse(delete_mme_submission, args=[INDIVIDUAL_GUID]) _check_login(self, url) responses.add(responses.DELETE, 'http://localhost:9020/patient/delete', body='Failed request', status=400) responses.add(responses.DELETE, 'http://localhost:9020/patient/delete', status=200) response = self.client.post(url) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Failed request') response = self.client.post(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertEqual( response_json['individualsByGuid'][INDIVIDUAL_GUID]['mmeDeletedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) self.assertEqual(MatchmakerResult.objects.filter(individual__guid=INDIVIDUAL_GUID).count(), 2) # Test proxy calls self.assertEqual(len(responses.calls), 2) self.assertEqual(responses.calls[1].request.url, 'http://localhost:9020/patient/delete') self.assertEqual(responses.calls[1].request.headers['X-Auth-Token'], 'abcd') self.assertEqual(responses.calls[1].request.headers['Accept'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.headers['Content-Type'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.body, json.dumps({'id': 'NA19675_1_01'})) # Test do not delete if already deleted response = self.client.post(url) self.assertEqual(response.status_code, 402) self.assertEqual(response.reason_phrase, 'Matchmaker submission has already been deleted for NA19675_1')
def test_query_single_variant(self, mock_get_variant): mock_get_variant.return_value = VARIANTS[0] url = reverse(query_single_variant_handler, args=['21-3343353-GAGA-G']) _check_login(self, url) response = self.client.get('{}?familyGuid=F000001_1'.format(url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json.keys()), { 'searchedVariants', 'savedVariantsByGuid', 'genesById', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', 'variantTagsByGuid', 'variantNotesByGuid', 'variantFunctionalDataByGuid' }) self.assertListEqual(response_json['searchedVariants'], EXPECTED_VARIANTS[:1]) self.assertSetEqual(set(response_json['savedVariantsByGuid'].keys()), {'SV0000001_2103343353_r0390_100'}) self.assertSetEqual(set(response_json['genesById'].keys()), {'ENSG00000227232', 'ENSG00000268903'}) self.assertTrue('F000001_1' in response_json['familiesByGuid'])
def test_phenotips_edit_patient(self): url = reverse(phenotips_edit_patient, args=['R0001_1kg', 'P0000001']) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({'some_json': 'test'})) self.assertEqual(response.status_code, 200)
def test_project_categories_api(self): url = reverse(update_project_categories_handler, args=['R0001_1kg']) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({ 'categories': [] })) self.assertEqual(response.status_code, 200)
def test_create_partially_saved_compound_het_variant_note(self): # compound het 5 is not saved, whereas compound het 1 is saved create_saved_variant_url = reverse(create_saved_variant_handler) _check_login(self, create_saved_variant_url) request_body = { 'variant': [ COMPOUND_HET_5_JSON, { 'variantId': 'abc123', 'xpos': 21003343353, 'ref': 'GAGA', 'alt': 'G' } ], 'note': 'one_saved_one_not_saved_compount_hets_note', 'submitToClinvar': True, 'familyGuid': 'F000001_1', } response = self.client.post(create_saved_variant_url, content_type='application/json', data=json.dumps(request_body)) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()['savedVariantsByGuid']), 2) compound_het_guids = response.json()['savedVariantsByGuid'].keys() compound_het_guids.remove(VARIANT_GUID) compound_het_5_guid = compound_het_guids[0] saved_compound_het_5 = SavedVariant.objects.get( guid=compound_het_5_guid, family__guid='F000001_1') self.assertDictEqual(COMPOUND_HET_5_JSON, saved_compound_het_5.saved_variant_json) expected_compound_het_5_json = { 'variantGuid': compound_het_5_guid, 'selectedMainTranscriptId': None, 'tagGuids': [], 'functionalDataGuids': [], } expected_compound_het_5_json.update(COMPOUND_HET_5_JSON) response_json = response.json() response_compound_het_5_json = response_json['savedVariantsByGuid'][ compound_het_5_guid] note_guids = response_compound_het_5_json.pop('noteGuids') self.assertDictEqual(expected_compound_het_5_json, response_compound_het_5_json) self.assertListEqual( note_guids, response_json['savedVariantsByGuid'][VARIANT_GUID]['noteGuids']) self.assertEqual(len(note_guids), 1) self.assertEqual( 'one_saved_one_not_saved_compount_hets_note', response_json['variantNotesByGuid'][note_guids[0]]['note'], )
def test_update_compound_hets_variant_functional_data(self): variant_functional_data = VariantFunctionalData.objects.filter( saved_variants__guid__in=[ COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID ]) self.assertEqual(len(variant_functional_data), 0) # send valid request to creat variant_tag for compound hets update_variant_tags_url = reverse( update_variant_functional_data_handler, args=[','.join([COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID])]) _check_login(self, update_variant_tags_url) response = self.client.post(update_variant_tags_url, content_type='application/json', data=json.dumps({ 'functionalData': [{ 'name': 'Biochemical Function', 'metadata': 'An updated note' }, { 'name': 'Bonferroni corrected p-value', 'metadata': 0.05 }], 'familyGuid': 'F000001_1' })) self.assertEqual(response.status_code, 200) compound_het_1_functional_data_guids = response.json( )['savedVariantsByGuid'][COMPOUND_HET_1_GUID]['functionalDataGuids'] compound_het_2_functional_data_guids = response.json( )['savedVariantsByGuid'][COMPOUND_HET_2_GUID]['functionalDataGuids'] self.assertEqual(len(compound_het_1_functional_data_guids), 2) self.assertEqual(len(compound_het_2_functional_data_guids), 2) self.assertSetEqual( {"Biochemical Function", "Bonferroni corrected p-value"}, { vt['name'] for vt in response.json() ['variantFunctionalDataByGuid'].values() }) self.assertSetEqual({"An updated note", 0.05}, { vt['metadata'] for vt in response.json()['variantFunctionalDataByGuid'].values() }) variant_functional_data = VariantFunctionalData.objects.filter( saved_variants__guid__in=[ COMPOUND_HET_1_GUID, COMPOUND_HET_2_GUID ]) self.assertSetEqual( {"Biochemical Function", "Bonferroni corrected p-value"}, {vt.functional_data_tag for vt in variant_functional_data}) self.assertSetEqual({"An updated note", "0.05"}, {vt.metadata for vt in variant_functional_data})
def test_update_individual_hpo_terms(self): edit_individuals_url = reverse(update_individual_hpo_terms, args=[INDIVIDUAL_UPDATE_GUID]) _check_login(self, edit_individuals_url) response = self.client.post(edit_individuals_url, content_type='application/json', data=json.dumps(INDIVIDUAL_UPDATE_DATA)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertListEqual(response_json.keys(), [INDIVIDUAL_UPDATE_GUID]) self.assertEqual(response_json[INDIVIDUAL_UPDATE_GUID]['displayName'], 'NA20870') self.assertListEqual( response_json[INDIVIDUAL_UPDATE_GUID]['features'], [ { 'id': 'HP:0002011', 'category': 'HP:0000707', 'label': 'Morphological abnormality of the central nervous system', 'qualifiers': [{ 'type': 'onset', 'label': 'congenital' }], }, { 'id': 'HP:0011675', 'category': 'HP:0001626', 'label': 'Arrhythmia', 'notes': 'A new term' }, ]) self.assertListEqual( response_json[INDIVIDUAL_UPDATE_GUID]['absentNonstandardFeatures'], [{ 'id': 'Some new feature', 'notes': 'No term for this' }]) self.assertIsNone( response_json[INDIVIDUAL_UPDATE_GUID]['absentFeatures']) self.assertIsNone( response_json[INDIVIDUAL_UPDATE_GUID]['nonstandardFeatures']) self.assertListEqual( Individual.objects.get(guid=INDIVIDUAL_UPDATE_GUID).features, [ { 'id': 'HP:0002011', 'qualifiers': [{ 'type': 'onset', 'label': 'congenital' }] }, { 'id': 'HP:0011675', 'notes': 'A new term' }, ])
def test_project_page_data(self): url = reverse(project_page_data, args=[PROJECT_GUID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json.keys()), {'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid'} ) self.assertSetEqual( set(response_json['projectsByGuid'][PROJECT_GUID]['variantTagTypes'][0].keys()), {'variantTagTypeGuid', 'name', 'category', 'description', 'color', 'order', 'is_built_in', 'numTags', 'numTagsPerFamily'} ) self.assertSetEqual( set(response_json['projectsByGuid'][PROJECT_GUID].keys()), {'collaborators', 'locusListGuids', 'variantTagTypes', 'variantFunctionalTagTypes', 'hasGeneSearch', 'detailsLoaded', 'projectGuid', 'projectCategoryGuids', 'canEdit', 'name', 'description', 'createdDate', 'lastModifiedDate', 'isPhenotipsEnabled', 'phenotipsUserId', 'deprecatedProjectId', 'hasNewSearch', 'lastAccessedDate', 'isMmeEnabled', 'mmePrimaryDataOwner', 'mmeContactInstitution', 'mmeContactUrl', 'genomeVersion', 'discoveryTags'} ) self.assertEqual( response_json['projectsByGuid'][PROJECT_GUID]['lastAccessedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) self.assertSetEqual( set(response_json['familiesByGuid'].values()[0].keys()), {'projectGuid', 'familyGuid', 'individualGuids', 'analysedBy', 'pedigreeImage', 'familyId', 'displayName', 'description', 'analysisNotes', 'analysisSummary', 'causalInheritanceMode', 'analysisStatus', 'pedigreeImage', 'internalAnalysisStatus', 'internalCaseReviewNotes', 'internalCaseReviewSummary', 'createdDate', 'codedPhenotype', 'postDiscoveryOmimNumber', 'pubmedIds'} ) self.assertSetEqual( set(response_json['individualsByGuid'].values()[0].keys()), {'projectGuid', 'familyGuid', 'individualGuid', 'sampleGuids', 'caseReviewStatusLastModifiedBy', 'phenotipsData', 'individualId', 'paternalId', 'maternalId', 'sex', 'affected', 'displayName', 'notes', 'phenotipsPatientId', 'phenotipsData', 'createdDate', 'lastModifiedDate', 'caseReviewStatus', 'caseReviewDiscussion', 'caseReviewStatusLastModifiedDate', 'caseReviewStatusLastModifiedBy', 'paternalGuid', 'maternalGuid', 'mmeSubmittedDate', 'mmeDeletedDate'} ) self.assertSetEqual( set(response_json['samplesByGuid'].values()[0].keys()), {'projectGuid', 'individualGuid', 'sampleGuid', 'createdDate', 'sampleType', 'datasetType', 'sampleId', 'sampleStatus', 'loadedDate', 'datasetFilePath', 'elasticsearchIndex'} ) self.assertSetEqual( set(response_json['locusListsByGuid'].values()[0].keys()), {'locusListGuid', 'description', 'lastModifiedDate', 'numEntries', 'isPublic', 'createdBy', 'createdDate', 'canEdit', 'name'} ) self.assertSetEqual( set(response_json['analysisGroupsByGuid'].values()[0].keys()), {'analysisGroupGuid', 'description', 'name', 'projectGuid', 'familyGuids'} )
def test_export_case_review_individuals(self): url = reverse(export_case_review_individuals, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url + "?file_format=tsv") self.assertEqual(response.status_code, 200) response = self.client.get(url + "?file_format=xls") self.assertEqual(response.status_code, 200)
def test_project_page_data(self): url = reverse(project_page_data, args=[PROJECT_GUID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json.keys()), {'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid'} ) self.assertSetEqual( set(response_json['projectsByGuid'][PROJECT_GUID]['variantTagTypes'][0].keys()), {'variantTagTypeGuid', 'name', 'category', 'description', 'color', 'order', 'numTags', 'numTagsPerFamily'} ) self.assertSetEqual( set(response_json['projectsByGuid'][PROJECT_GUID].keys()), {'collaborators', 'locusListGuids', 'variantTagTypes', 'variantFunctionalTagTypes', 'detailsLoaded', 'projectGuid', 'projectCategoryGuids', 'canEdit', 'name', 'description', 'createdDate', 'lastModifiedDate', 'isPhenotipsEnabled', 'phenotipsUserId', 'deprecatedProjectId', 'hasNewSearch', 'lastAccessedDate', 'isMmeEnabled', 'mmePrimaryDataOwner', 'mmeContactInstitution', 'mmeContactUrl', 'genomeVersion', 'discoveryTags'} ) self.assertEqual( response_json['projectsByGuid'][PROJECT_GUID]['lastAccessedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) self.assertSetEqual( set(response_json['familiesByGuid'].values()[0].keys()), {'projectGuid', 'familyGuid', 'individualGuids', 'analysedBy', 'pedigreeImage', 'familyId', 'displayName', 'description', 'analysisNotes', 'analysisSummary', 'causalInheritanceMode', 'analysisStatus', 'pedigreeImage', 'internalAnalysisStatus', 'internalCaseReviewNotes', 'internalCaseReviewSummary', 'createdDate', 'codedPhenotype', 'postDiscoveryOmimNumber', 'pubmedIds', 'assignedAnalyst'} ) self.assertSetEqual( set(response_json['individualsByGuid'].values()[0].keys()), {'projectGuid', 'familyGuid', 'individualGuid', 'sampleGuids', 'caseReviewStatusLastModifiedBy', 'phenotipsData', 'individualId', 'paternalId', 'maternalId', 'sex', 'affected', 'displayName', 'notes', 'phenotipsPatientId', 'phenotipsData', 'createdDate', 'lastModifiedDate', 'caseReviewStatus', 'caseReviewDiscussion', 'caseReviewStatusLastModifiedDate', 'caseReviewStatusLastModifiedBy', 'paternalGuid', 'maternalGuid', 'mmeSubmittedDate', 'mmeDeletedDate', 'popPlatformFilters', 'filterFlags', 'population'} ) self.assertSetEqual( set(response_json['samplesByGuid'].values()[0].keys()), {'projectGuid', 'individualGuid', 'sampleGuid', 'createdDate', 'sampleType', 'datasetType', 'sampleId', 'sampleStatus', 'loadedDate', 'datasetFilePath', 'elasticsearchIndex'} ) self.assertSetEqual( set(response_json['locusListsByGuid'].values()[0].keys()), {'locusListGuid', 'description', 'lastModifiedDate', 'numEntries', 'isPublic', 'createdBy', 'createdDate', 'canEdit', 'name'} ) self.assertSetEqual( set(response_json['analysisGroupsByGuid'].values()[0].keys()), {'analysisGroupGuid', 'description', 'name', 'projectGuid', 'familyGuids'} )
def test_export_tables(self): url = reverse(export_project_individuals_handler, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url+"?file_format=tsv") self.assertEqual(response.status_code, 200) response = self.client.get(url+"?file_format=xls") self.assertEqual(response.status_code, 200)
def test_export_tables(self): url = reverse(export_project_individuals_handler, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url + "?file_format=tsv") self.assertEqual(response.status_code, 200) response = self.client.get(url + "?file_format=xls") self.assertEqual(response.status_code, 200)
def test_export_projects_table(self): url = reverse(export_projects_table_handler) _check_login(self, url) response = self.client.get(url+"?file_format=tsv") self.assertEqual(response.status_code, 200) response = self.client.get(url+"?file_format=xls") self.assertEqual(response.status_code, 200)
def test_project_categories_api(self): url = reverse(awesomebar_autocomplete_handler) _check_login(self, url) #self.assertRaisesRegexp(ValueError, "missing", lambda: # self.client.get(url) #) response = self.client.get(url+"?q=T") self.assertEqual(response.status_code, 200)
def test_create_saved_variant(self): create_saved_variant_url = reverse(create_saved_variant_handler) _check_login(self, create_saved_variant_url) variant_json = { 'alt': 'A', 'chrom': '2', 'genotypes': {}, 'genomeVersion': '37', 'mainTranscript': {}, 'originalAltAlleles': ['A'], 'populations': {'callset': {'ac': 2, 'af': 0.063, 'an': 32}}, 'pos': 61413835, 'predictions': {'cadd': 21.9}, 'ref': 'AAAG', 'transcripts': {}, 'xpos': 2061413835, 'projectGuid': 'R0001_1kg', 'familyGuids': ['F000001_1'], 'variantId': '2-61413835-AAAG-A', } request_body = { 'searchHash': 'd380ed0fd28c3127d07a64ea2ba907d7', 'familyGuid': 'F000001_1', 'tags': [{'name': 'Review'}], 'notes': [], 'functionalData': [], } request_body.update(variant_json) response = self.client.post(create_saved_variant_url, content_type='application/json', data=json.dumps(request_body)) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()['savedVariantsByGuid']), 1) variant_guid = response.json()['savedVariantsByGuid'].keys()[0] saved_variant = SavedVariant.objects.get(guid=variant_guid, family__guid='F000001_1') self.assertDictEqual(variant_json, json.loads(saved_variant.saved_variant_json)) variant_json.update({ 'variantId': variant_guid, 'variantGuid': variant_guid, 'notes': [], 'functionalData': [], }) response_variant_json = response.json()['savedVariantsByGuid'][variant_guid] tags = response_variant_json.pop('tags') self.assertDictEqual(variant_json, response_variant_json) self.assertListEqual(["Review"], [vt['name'] for vt in tags]) self.assertListEqual(["Review"], [vt.variant_tag_type.name for vt in VariantTag.objects.filter(saved_variant__guid=variant_guid)])
def test_gene_info(self): url = reverse(gene_info, args=[GENE_ID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) gene = response.json()['genesById'][GENE_ID] self.assertSetEqual(set(gene.keys()), { 'chromGrch37', 'chromGrch38', 'codingRegionSizeGrch37', 'codingRegionSizeGrch38', 'constraints', 'diseaseDesc', 'endGrch37', 'endGrch38', 'functionDesc', 'gencodeGeneType', 'geneId', 'geneSymbol', 'omimPhenotypes', 'mimNumber', 'startGrch37', 'startGrch38', 'notes', 'expression', 'mgiMarkerId', })
def test_create_update_and_delete_project(self): create_project_url = reverse(create_project_handler) _check_login(self, create_project_url) # check validation of bad requests response = self.client.post(create_project_url, content_type='application/json', data=json.dumps({'bad_json': None})) self.assertEqual(response.status_code, 400) response = self.client.post(create_project_url, content_type='application/json', data=json.dumps({'form': {'missing_name': True}})) self.assertEqual(response.status_code, 400) # send valid request to create project response = self.client.post(create_project_url, content_type='application/json', data=json.dumps( {'name': 'new_project', 'description': 'new project description', 'genomeVersion': '38'} )) self.assertEqual(response.status_code, 200) # check that project was created new_project = Project.objects.filter(name='new_project') self.assertEqual(len(new_project), 1) self.assertEqual(new_project[0].description, 'new project description') self.assertEqual(new_project[0].genome_version, '38') project_guid = new_project[0].guid self.assertSetEqual(set(response.json()['projectsByGuid'].keys()), {project_guid}) # update the project update_project_url = reverse(update_project_handler, args=[project_guid]) response = self.client.post(update_project_url, content_type='application/json', data=json.dumps( {'description': 'updated project description'} )) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()['projectsByGuid'][project_guid]['description'], 'updated project description') self.assertEqual(Project.objects.get(guid=project_guid).description, 'updated project description') # genome version should not update response = self.client.post(update_project_url, content_type='application/json', data=json.dumps( {'genomeVersion': '37'} )) self.assertEqual(response.json()['projectsByGuid'][project_guid]['genomeVersion'], '38') self.assertEqual(Project.objects.get(guid=project_guid).genome_version, '38') # delete the project delete_project_url = reverse(delete_project_handler, args=[project_guid]) response = self.client.post(delete_project_url, content_type='application/json') self.assertEqual(response.status_code, 200) # check that project was deleted new_project = Project.objects.filter(name='new_project') self.assertEqual(len(new_project), 0)
def test_create_update_and_delete_gene_note(self): add_or_edit_url = reverse(add_or_edit_gene_note) delete_url = reverse(delete_gene_note, args=[1]) _check_login(self, add_or_edit_url) # check validation of bad requests response = self.client.get(add_or_edit_url) self.assertTrue(response.json()['is_error']) response = self.client.get(add_or_edit_url, {'gene_id': 'ENSG00000008735', 'note_text': 'test note', 'note_id': 1}) self.assertTrue(response.json()['is_error']) response = self.client.get(delete_url) self.assertTrue(response.json()['is_error']) # check that create works response = self.client.get(add_or_edit_url, {'gene_id': 'ENSG00000008735', 'note_text': 'test note'}) self.assertEqual(response.status_code, 200) self.assertFalse(response.json()['is_error']) gene_notes = GeneNote.objects.all() self.assertEqual(len(gene_notes), 1) self.assertEqual(gene_notes[0].note, 'test note') self.assertEqual(gene_notes[0].gene_id, 'ENSG00000008735') self.assertEqual(gene_notes[0].user.username, 'test_user') initial_date_saved = gene_notes[0].date_saved # check that edit works response = self.client.get(add_or_edit_url, {'gene_id': 'ENSG00000008735', 'note_text': 'edited test note', 'note_id': 1}) self.assertEqual(response.status_code, 200) self.assertFalse(response.json()['is_error']) gene_notes = GeneNote.objects.all() self.assertEqual(len(gene_notes), 1) self.assertEqual(gene_notes[0].note, 'edited test note') self.assertGreater(gene_notes[0].date_saved, initial_date_saved) # check that edit does not change the gene response = self.client.get(add_or_edit_url, {'gene_id': 'ENSG00000000001', 'note_text': 'test note', 'note_id': 1}) self.assertEqual(response.json()['note']['gene_id'], 'ENSG00000008735') # check that delete works response = self.client.get(delete_url) self.assertEqual(response.status_code, 200) self.assertFalse(response.json()['is_error']) gene_notes = GeneNote.objects.all() self.assertEqual(len(gene_notes), 0)
def test_update_saved_variant_json(self, mock_retrieve_variants): mock_retrieve_variants.side_effect = lambda project, variant_tuples: \ [{'xpos': var[0], 'ref': var[1], 'alt': var[2], 'familyGuids': [var[3].guid]} for var in variant_tuples] url = reverse(update_saved_variant_json, args=['R0001_1kg']) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertSetEqual( set(response.json().keys()), {'SV0000002_1248367227_r0390_100', 'SV0000001_2103343353_r0390_100', 'SV0000003_2246859832_r0390_100'} )
def test_locus_lists(self): url = reverse(locus_lists) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) locus_lists_dict = response.json()['locusListsByGuid'] self.assertSetEqual(set(locus_lists_dict.keys()), {'LL00049_pid_genes_autosomal_do', 'LL00005_retina_proteome'}) locus_list = locus_lists_dict[LOCUS_LIST_GUID] self.assertSetEqual( set(locus_list.keys()), {'locusListGuid', 'description', 'lastModifiedDate', 'numEntries', 'isPublic', 'createdBy', 'createdDate', 'canEdit', 'name'} )
def test_search_context(self): search_context_url = reverse(search_context_handler) _check_login(self, search_context_url) response = self.client.get('{}?foo=bar'.format(search_context_url)) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Invalid query params: {"foo": "bar"}') response = self.client.get('{}?projectGuid={}'.format(search_context_url, PROJECT_GUID)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) response = self.client.get('{}?familyGuid=F000001_1'.format(search_context_url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid']) response = self.client.get('{}?analysisGroupGuid=AG0000183_test_group'.format(search_context_url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json), {'savedSearchesByGuid', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid', } ) self.assertEqual(len(response_json['savedSearchesByGuid']), 3) self.assertTrue(PROJECT_GUID in response_json['projectsByGuid']) self.assertTrue('F000001_1' in response_json['familiesByGuid']) self.assertTrue('AG0000183_test_group' in response_json['analysisGroupsByGuid'])
def test_empty_project_page_data(self): url = reverse(project_page_data, args=[EMPTY_PROJECT_GUID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json.keys()), {'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid'} ) self.assertListEqual(response_json['projectsByGuid'].keys(), [EMPTY_PROJECT_GUID]) self.assertDictEqual(response_json['familiesByGuid'], {}) self.assertDictEqual(response_json['individualsByGuid'], {}) self.assertDictEqual(response_json['samplesByGuid'], {}) self.assertDictEqual(response_json['analysisGroupsByGuid'], {})
def test_create_update_and_delete_variant_note(self): create_variant_note_url = reverse(create_variant_note_handler, args=[VARIANT_GUID]) _check_login(self, create_variant_note_url) # send valid request to create variant_note response = self.client.post(create_variant_note_url, content_type='application/json', data=json.dumps( {'note': 'new_variant_note', 'submitToClinvar': True} )) self.assertEqual(response.status_code, 200) new_note_response = response.json()['savedVariantsByGuid'][VARIANT_GUID]['notes'][0] self.assertEqual(new_note_response['note'], 'new_variant_note') self.assertEqual(new_note_response['submitToClinvar'], True) new_variant_note = VariantNote.objects.filter(guid=new_note_response['noteGuid']).first() self.assertIsNotNone(new_variant_note) self.assertEqual(new_variant_note.note, new_note_response['note']) self.assertEqual(new_variant_note.submit_to_clinvar, new_note_response['submitToClinvar']) # update the variant_note update_variant_note_url = reverse(update_variant_note_handler, args=[VARIANT_GUID, new_variant_note.guid]) response = self.client.post(update_variant_note_url, content_type='application/json', data=json.dumps( {'note': 'updated_variant_note', 'submitToClinvar': False})) self.assertEqual(response.status_code, 200) updated_note_response = response.json()['savedVariantsByGuid'][VARIANT_GUID]['notes'][0] self.assertEqual(updated_note_response['note'], 'updated_variant_note') self.assertEqual(updated_note_response['submitToClinvar'], False) updated_variant_note = VariantNote.objects.filter(guid=updated_note_response['noteGuid']).first() self.assertIsNotNone(updated_variant_note) self.assertEqual(updated_variant_note.note, updated_note_response['note']) self.assertEqual(updated_variant_note.submit_to_clinvar, updated_note_response['submitToClinvar']) # delete the variant_note delete_variant_note_url = reverse(delete_variant_note_handler, args=[VARIANT_GUID, updated_variant_note.guid]) response = self.client.post(delete_variant_note_url, content_type='application/json') self.assertEqual(response.status_code, 200) # check that variant_note was deleted new_variant_note = VariantNote.objects.filter(guid=updated_note_response['noteGuid']) self.assertEqual(len(new_variant_note), 0)
def test_add_and_remove_project_locus_lists(self): project = Project.objects.get(guid=PROJECT_GUID) self.assertListEqual(list(get_project_locus_list_models(project)), []) # add a locus list url = reverse(add_project_locus_lists, args=[PROJECT_GUID]) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], [LOCUS_LIST_GUID]) self.assertListEqual(list(get_project_locus_list_models(project)), [LocusList.objects.get(guid=LOCUS_LIST_GUID)]) # remove a locus list url = reverse(delete_project_locus_lists, args=[PROJECT_GUID]) response = self.client.post(url, content_type='application/json', data=json.dumps({'locusListGuids': [LOCUS_LIST_GUID]})) self.assertEqual(response.status_code, 200) self.assertListEqual(response.json()['locusListGuids'], []) self.assertListEqual(list(get_project_locus_list_models(project)), [])
def test_query_single_variant(self, mock_get_variant): mock_get_variant.return_value = VARIANTS[0] url = reverse(query_single_variant_handler, args=['21-3343353-GAGA-G']) _check_login(self, url) response = self.client.get('{}?familyGuid=F000001_1'.format(url)) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual( set(response_json.keys()), {'searchedVariants', 'savedVariantsByGuid', 'genesById', 'projectsByGuid', 'familiesByGuid', 'individualsByGuid', 'samplesByGuid', 'locusListsByGuid', 'analysisGroupsByGuid',} ) self.assertListEqual(response_json['searchedVariants'], EXPECTED_VARIANTS[:1]) self.assertSetEqual(set(response_json['savedVariantsByGuid'].keys()), {'SV0000001_2103343353_r0390_100'}) self.assertSetEqual(set(response_json['genesById'].keys()), {'ENSG00000227232', 'ENSG00000268903'}) self.assertTrue('F000001_1' in response_json['familiesByGuid'])
def test_locus_list_info(self): url = reverse(locus_list_info, args=[LOCUS_LIST_GUID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) response_json = response.json() locus_lists_dict = response_json['locusListsByGuid'] self.assertListEqual(locus_lists_dict.keys(), [LOCUS_LIST_GUID]) locus_list = locus_lists_dict[LOCUS_LIST_GUID] self.assertSetEqual( set(locus_list.keys()), {'locusListGuid', 'description', 'lastModifiedDate', 'numEntries', 'isPublic', 'createdBy', 'createdDate', 'canEdit', 'name', 'items', 'intervalGenomeVersion'} ) self.assertSetEqual( {item['geneId'] for item in locus_list['items'] if item.get('geneId')}, set(response_json['genesById'].keys()) )
def test_create_update_and_delete_gene_note(self): create_gene_note_url = reverse(create_gene_note_handler, args=[GENE_ID]) _check_login(self, create_gene_note_url) # send valid request to create gene_note response = self.client.post(create_gene_note_url, content_type='application/json', data=json.dumps( {'note': 'new_gene_note'} )) self.assertEqual(response.status_code, 200) new_note_response = response.json()['genesById'][GENE_ID]['notes'][0] self.assertEqual(new_note_response['note'], 'new_gene_note') new_gene_note = GeneNote.objects.filter(guid=new_note_response['noteGuid']).first() self.assertIsNotNone(new_gene_note) self.assertEqual(new_gene_note.note, new_note_response['note']) # update the gene_note update_gene_note_url = reverse(update_gene_note_handler, args=[GENE_ID, new_gene_note.guid]) response = self.client.post(update_gene_note_url, content_type='application/json', data=json.dumps( {'note': 'updated_gene_note'})) self.assertEqual(response.status_code, 200) updated_note_response = response.json()['genesById'][GENE_ID]['notes'][0] self.assertEqual(updated_note_response['note'], 'updated_gene_note') updated_gene_note = GeneNote.objects.filter(guid=updated_note_response['noteGuid']).first() self.assertIsNotNone(updated_gene_note) self.assertEqual(updated_gene_note.note, updated_note_response['note']) # delete the gene_note delete_gene_note_url = reverse(delete_gene_note_handler, args=[GENE_ID, updated_gene_note.guid]) response = self.client.post(delete_gene_note_url, content_type='application/json') self.assertEqual(response.status_code, 200) # check that gene_note was deleted new_gene_note = GeneNote.objects.filter(guid=updated_note_response['noteGuid']) self.assertEqual(len(new_gene_note), 0)
def test_create_staff_user(self, mock_send_mail): create_url = reverse(create_staff_user) _check_login(self, create_url) # send invalid request response = self.client.post(create_url, content_type='application/json', data=json.dumps({})) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'Email is required') # create response = self.client.post(create_url, content_type='application/json', data=json.dumps({ 'email': '*****@*****.**', 'firstName': 'Test', 'lastName': 'Staff'})) self.assertEqual(response.status_code, 200) user = User.objects.get(email='*****@*****.**') self.assertTrue(user.is_staff) expected_email_content = """ Hi there Test Staff-- [email protected] has added you as a collaborator in seqr. Please click this link to set up your account: /users/set_password/{password_token} Thanks! """.format(password_token=user.password) mock_send_mail.assert_called_with( 'Set up your seqr account', expected_email_content, None, ['*****@*****.**'], fail_silently=False, ) # calling create again fails response = self.client.post(create_url, content_type='application/json', data=json.dumps({ 'email': '*****@*****.**'})) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'This user already exists')
def test_edit_individuals(self, mock_find_xbrowse_model): mock_find_xbrowse_model.return_value.has_elasticsearch_index.return_value = False edit_individuals_url = reverse(edit_individuals_handler, args=[PROJECT_GUID]) _check_login(self, edit_individuals_url) # send invalid requests response = self.client.post(edit_individuals_url, content_type='application/json', data=json.dumps({ 'individuals': [INDIVIDUAL_IDS_UPDATE_DATA] })) self.assertEqual(response.status_code, 400) self.assertListEqual(response.json()['errors'], ["NA20870 is the mother of NA19678_1 but doesn't have a separate record in the table"]) response = self.client.post(edit_individuals_url, content_type='application/json', data=json.dumps({ 'individuals': [INDIVIDUAL_IDS_UPDATE_DATA, INDIVIDUAL_FAMILY_UPDATE_DATA] })) self.assertEqual(response.status_code, 400) self.assertListEqual(response.json()['errors'], ['Editing individual_id is disabled for projects which still use the mongo datastore']) # send valid request mock_find_xbrowse_model.return_value.has_elasticsearch_index.return_value = True response = self.client.post(edit_individuals_url, content_type='application/json', data=json.dumps({ 'individuals': [INDIVIDUAL_IDS_UPDATE_DATA, INDIVIDUAL_FAMILY_UPDATE_DATA] })) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual({'F000001_1', 'F000003_3'}, set(response_json['familiesByGuid'])) self.assertSetEqual({ID_UPDATE_GUID, FAMILY_UPDATE_GUID, CHILD_UPDATE_GUID, "I000003_na19679"}, set(response_json['familiesByGuid']['F000001_1']['individualGuids'])) self.assertListEqual(response_json['familiesByGuid']['F000003_3']['individualGuids'], []) self.assertSetEqual({ID_UPDATE_GUID, FAMILY_UPDATE_GUID, CHILD_UPDATE_GUID}, set(response_json['individualsByGuid'])) self.assertEqual(response_json['individualsByGuid'][ID_UPDATE_GUID]['individualId'], UPDATED_ID) self.assertEqual(response_json['individualsByGuid'][ID_UPDATE_GUID]['maternalId'], UPDATED_MATERNAL_ID) self.assertEqual(response_json['individualsByGuid'][CHILD_UPDATE_GUID]['paternalId'], UPDATED_ID)
def test_phenotips_pdf(self): url = reverse(phenotips_pdf_handler, args=['R0001_1kg', 'I000001_na19675']) _check_login(self, url) response = self.client.post(url, content_type='application/json', data=json.dumps({'some_json': 'test'})) self.assertEqual(response.status_code, 200)
def test_react_page(self): url = reverse(main_app) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200)
def test_search_individual_mme_matches(self, mock_post_to_slack): url = reverse(search_individual_mme_matches, args=[INDIVIDUAL_GUID]) _check_login(self, url) responses.add(responses.POST, 'http://*****:*****@broadinstitute.org', 'name': 'Sam Baxter', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0001252', 'label': 'Muscular hypotonia', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'genomicFeatures': [{ 'gene': {'id': 'ENSG00000186092'}, 'variant': { 'end': 77027548, 'start': 77027549, 'assembly': 'GRCh38', 'referenceName': '14', 'alternateBases': 'C', 'referenceBases': 'CCACT' }, 'zygosity': 1 }], }, 'phenotypes': [ {'id': 'HP:0001252', 'label': 'Muscular hypotonia', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'geneVariants': [{ 'geneId': 'ENSG00000186092', 'alt': 'C', 'ref': 'CCACT', 'chrom': '14', 'pos': 77027549, 'genomeVersion': 'GRCh38', }], }, 'mmeSubmittedDate': '2018-05-23T09:07:49.719Z', 'mmeDeletedDate': None, }}) self.assertSetEqual( set(response_json['individualsByGuid'][INDIVIDUAL_GUID]['mmeResultGuids']), set(response_json['mmeResultsByGuid'].keys())) self.assertSetEqual( set(response_json['genesById'].keys()), {'ENSG00000186092', 'ENSG00000233750', 'ENSG00000223972'} ) # Test proxy calls self.assertEqual(len(responses.calls), 3) expected_body = json.dumps({ 'patient': { 'id': 'NA19675_1_01', 'label': 'NA19675_1', 'contact': {'href': 'mailto:[email protected]', 'name': 'Sam Baxter', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0001252', 'observed': 'yes'}, {'id': 'HP:0001263', 'observed': 'no'}, {'id': 'HP:0012469', 'observed': 'yes'} ], 'genomicFeatures': [{ 'gene': {'id': 'ENSG00000186092'}, 'variant': { 'end': 77027548, 'start': 77027549, 'assembly': 'GRCh38', 'referenceName': '14', 'alternateBases': 'C', 'referenceBases': 'CCACT', }, 'zygosity': 1 }], } }) self.assertEqual(responses.calls[1].request.url, 'http://localhost:9020/match') self.assertEqual(responses.calls[1].request.headers['X-Auth-Token'], 'abcd') self.assertEqual(responses.calls[1].request.headers['Accept'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.headers['Content-Type'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[1].request.body, expected_body) self.assertEqual(responses.calls[2].request.url, 'http://localhost:9020/match/external') self.assertEqual(responses.calls[2].request.headers['X-Auth-Token'], 'abcd') self.assertEqual(responses.calls[2].request.headers['Accept'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[2].request.headers['Content-Type'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[2].request.body, expected_body) # Test slack notification slack_message = u""" A search from a seqr user from project 1kg project n\xe5me with uni\xe7\xf8de individual NA19675_1 had the following new match(es): - From Reza Maroofian at institution St Georges, University of London with genes OR4F5 with phenotypes HP:0012469 (Infantile spasms). https://seqr.broadinstitute.org/project/R0001_1kg/family_page/F000001_1/matchmaker_exchange """ mock_post_to_slack.assert_called_with('matchmaker_seqr_match', slack_message) # Test new result model created result_model = MatchmakerResult.objects.get(guid=new_result_guid) self.assertDictEqual(result_model.result_data, NEW_MATCH_JSON)
def test_update_mme_submission(self): responses.add(responses.POST, 'http://*****:*****@broadinstitute.org', 'name': 'PI', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', }, 'phenotypes': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'geneVariants': [{ 'geneId': 'ENSG00000186092', 'alt': 'C', 'ref': 'CCACT', 'chrom': '14', 'pos': 77027549, 'genomeVersion': 'GRCh38', 'numAlt': 2, }], })) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual(set(response_json.keys()), {'mmeResultsByGuid', 'individualsByGuid', 'genesById'}) self.assertEqual(len(response_json['mmeResultsByGuid']), 1) self.assertDictEqual(response_json['mmeResultsByGuid'].values()[0], PARSED_NEW_MATCH_JSON) self.assertDictEqual(response_json['individualsByGuid'], {NO_SUBMISSION_INDIVIDUAL_GUID: { 'mmeResultGuids': response_json['mmeResultsByGuid'].keys(), 'mmeSubmittedData': { 'patient': { 'id': 'HG00733', 'label': 'HG00733', 'contact': {'href': 'mailto:[email protected]', 'name': 'PI', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'genomicFeatures': [{ 'gene': {'id': 'ENSG00000186092'}, 'variant': { 'start': 77027549, 'assembly': 'GRCh38', 'referenceName': '14', 'alternateBases': 'C', 'referenceBases': 'CCACT' }, 'zygosity': 0 }], }, 'phenotypes': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'geneVariants': [{ 'geneId': 'ENSG00000186092', 'alt': 'C', 'ref': 'CCACT', 'chrom': '14', 'pos': 77027549, 'genomeVersion': 'GRCh38', }], }, 'mmeSubmittedDate': mock.ANY, 'mmeDeletedDate': None, }}) self.assertEqual( response_json['individualsByGuid'][NO_SUBMISSION_INDIVIDUAL_GUID]['mmeSubmittedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) self.assertListEqual(response_json['genesById'].keys(), ['ENSG00000186092']) # Test proxy calls self.assertEqual(len(responses.calls), 4) expected_body = { 'patient': { 'id': 'HG00733', 'label': 'HG00733', 'contact': {'href': 'mailto:[email protected]', 'name': 'PI', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'genomicFeatures': [{ 'gene': {'id': 'ENSG00000186092'}, 'variant': { 'start': 77027549, 'assembly': 'GRCh38', 'referenceName': '14', 'alternateBases': 'C', 'referenceBases': 'CCACT' }, 'zygosity': 0 }], } } self.assertEqual(responses.calls[1].request.url, 'http://*****:*****@broadinstitute.org', 'name': 'Test Name', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', }, 'phenotypes': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, ], })) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual(set(response_json.keys()), {'mmeResultsByGuid', 'individualsByGuid', 'genesById'}) self.assertEqual(len(response_json['mmeResultsByGuid']), 1) self.assertDictEqual(response_json['mmeResultsByGuid'].values()[0], PARSED_NEW_MATCH_JSON) self.assertDictEqual(response_json['individualsByGuid'], {NO_SUBMISSION_INDIVIDUAL_GUID: { 'mmeResultGuids': response_json['mmeResultsByGuid'].keys(), 'mmeSubmittedData': { 'patient': { 'id': 'HG00733', 'label': 'HG00733', 'contact': {'href': 'mailto:[email protected]', 'name': 'Test Name', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, ], 'genomicFeatures': [], }, 'phenotypes': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, ], 'geneVariants': [], }, 'mmeSubmittedDate': mock.ANY, 'mmeDeletedDate': None, }}) self.assertEqual( response_json['individualsByGuid'][NO_SUBMISSION_INDIVIDUAL_GUID]['mmeSubmittedDate'][:10], datetime.today().strftime('%Y-%m-%d') ) self.assertListEqual(response_json['genesById'].keys(), ['ENSG00000186092']) # Test updates project MME contact project = Project.objects.get(family__individual__guid=NO_SUBMISSION_INDIVIDUAL_GUID) self.assertEqual(project.mme_primary_data_owner, 'PI,Test Name') self.assertEqual(project.mme_contact_url, 'mailto:[email protected],[email protected]') # Test proxy calls self.assertEqual(len(responses.calls), 7) expected_body = { 'patient': { 'id': 'HG00733', 'label': 'HG00733', 'contact': {'href': 'mailto:[email protected]', 'name': 'Test Name', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, ], 'genomicFeatures': [], } } self.assertEqual(responses.calls[4].request.url, 'http://localhost:9020/patient/add') self.assertEqual(responses.calls[4].request.headers['X-Auth-Token'], 'abcd') self.assertEqual(responses.calls[4].request.headers['Accept'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertEqual(responses.calls[4].request.headers['Content-Type'], 'application/vnd.ga4gh.matchmaker.v1.0+json') self.assertDictEqual(json.loads(responses.calls[4].request.body), expected_body) self.assertEqual(responses.calls[4].response.status_code, 409)
def test_get_individual_mme_matches(self): url = reverse(get_individual_mme_matches, args=[INDIVIDUAL_GUID]) _check_login(self, url) response = self.client.get(url) self.assertEqual(response.status_code, 200) response_json = response.json() self.assertSetEqual(set(response_json.keys()), {'mmeResultsByGuid', 'individualsByGuid', 'genesById'}) self.assertSetEqual( set(response_json['mmeResultsByGuid'].keys()), {'MR0007228_VCGS_FAM50_156', RESULT_STATUS_GUID} ) self.assertDictEqual(response_json['mmeResultsByGuid'][RESULT_STATUS_GUID], { 'id': 'P0004515', 'score': 0.5706712016939723, 'patient': { 'genomicFeatures': [ {'gene': {'id': 'OR4F5'}}, {'gene': {'id': 'CICP27'}}, {'gene': {'id': 'DDX11L1'}}, ], 'contact': { 'href': 'mailto:[email protected],[email protected]', 'name': 'Baylor UDN Clinical Site' }, 'id': 'P0004515', 'features': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0003273', 'label': 'Hip contracture', 'observed': 'no'}, ], }, 'phenotypes': [ {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'}, {'id': 'HP:0003273', 'label': 'Hip contracture', 'observed': 'no'}, ], 'geneVariants': [ {'geneId': 'ENSG00000186092'}, {'geneId': 'ENSG00000233750'}, {'geneId': 'ENSG00000223972'}, ], 'matchStatus': { 'matchmakerResultGuid': RESULT_STATUS_GUID, 'comments': '', 'weContacted': False, 'hostContacted': True, 'deemedIrrelevant': True, 'flagForAnalysis': False, 'createdDate': '2019-02-12T18:43:56.358Z', }, }) self.assertDictEqual(response_json['individualsByGuid'], {INDIVIDUAL_GUID: { 'mmeResultGuids': mock.ANY, 'mmeSubmittedData': { 'patient': { 'id': 'NA19675_1_01', 'label': 'NA19675_1', 'contact': {'href': 'mailto:[email protected]', 'name': 'Sam Baxter', 'institution': 'Broad Center for Mendelian Genomics'}, 'species': 'NCBITaxon:9606', 'features': [ {'id': 'HP:0001252', 'label': 'Muscular hypotonia', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'genomicFeatures': [{ 'gene': {'id': 'ENSG00000186092'}, 'variant': { 'end': 77027548, 'start': 77027549, 'assembly': 'GRCh38', 'referenceName': '14', 'alternateBases': 'C', 'referenceBases': 'CCACT' }, 'zygosity': 1 }], }, 'phenotypes': [ {'id': 'HP:0001252', 'label': 'Muscular hypotonia', 'observed': 'yes'}, {'id': 'HP:0001263', 'label': 'Global developmental delay', 'observed': 'no'}, {'id': 'HP:0012469', 'label': 'Infantile spasms', 'observed': 'yes'} ], 'geneVariants': [{ 'geneId': 'ENSG00000186092', 'alt': 'C', 'ref': 'CCACT', 'chrom': '14', 'pos': 77027549, 'genomeVersion': 'GRCh38', }], }, 'mmeSubmittedDate': '2018-05-23T09:07:49.719Z', 'mmeDeletedDate': None, }}) self.assertSetEqual( set(response_json['individualsByGuid'][INDIVIDUAL_GUID]['mmeResultGuids']), {'MR0007228_VCGS_FAM50_156', RESULT_STATUS_GUID}) self.assertSetEqual( set(response_json['genesById'].keys()), {'ENSG00000186092', 'ENSG00000233750', 'ENSG00000223972'} )
def test_create_update_and_delete_locus_list(self): create_locus_list_url = reverse(create_locus_list_handler) _check_login(self, create_locus_list_url) # send invalid requests to create locus_list response = self.client.post(create_locus_list_url, content_type='application/json', data=json.dumps({})) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, '"Name" is required') response = self.client.post(create_locus_list_url, content_type='application/json', data=json.dumps({ 'name': 'new_locus_list', 'isPublic': True, 'rawItems': 'DDX11L1, foo 10:10-1 chr100:1-10 \n2:1234-5678', })) self.assertEqual(response.status_code, 400) self.assertEqual(response.reason_phrase, 'This list contains invalid genes/ intervals. Update them, or select the "Ignore invalid genes and intervals" checkbox to ignore.') self.assertListEqual(response.json()['invalidLocusListItems'], ['chr10:10-1', 'chr100:1-10', 'foo']) # send valid request to create locus_list response = self.client.post(create_locus_list_url, content_type='application/json', data=json.dumps({ 'name': 'new_locus_list', 'isPublic': True, 'ignoreInvalidItems': True, 'rawItems': 'DDX11L1, foo chr100:1-1 \nchr2:1234-5678', })) self.assertEqual(response.status_code, 200) new_locus_list_response = response.json() self.assertEqual(len(new_locus_list_response['locusListsByGuid']), 1) new_locus_list = new_locus_list_response['locusListsByGuid'].values()[0] self.assertEqual(new_locus_list['name'], 'new_locus_list') self.assertEqual(new_locus_list['isPublic'], True) self.assertSetEqual( {item['geneId'] for item in new_locus_list['items'] if item.get('geneId')}, set(new_locus_list_response['genesById'].keys()) ) self.assertListEqual( new_locus_list['items'], [ {'geneId': 'ENSG00000223972'}, {'chrom': '2', 'start': 1234, 'end': 5678, 'genomeVersion': '37', 'locusListIntervalGuid': mock.ANY} ] ) guid = new_locus_list['locusListGuid'] gene_id = new_locus_list['items'][0]['geneId'] new_locus_list_model = LocusList.objects.filter(guid=guid).first() self.assertIsNotNone(new_locus_list_model) self.assertEqual(new_locus_list_model.name, new_locus_list['name']) self.assertEqual(new_locus_list_model.is_public, new_locus_list['isPublic']) self.assertEqual(new_locus_list_model.locuslistgene_set.count(), 1) self.assertEqual(new_locus_list_model.locuslistgene_set.first().gene_id, gene_id) self.assertEqual(new_locus_list_model.locuslistinterval_set.count(), 1) new_interval = new_locus_list_model.locuslistinterval_set.first() self.assertEqual(new_interval.chrom, '2') self.assertEqual(new_interval.start, 1234) # update the locus_list update_locus_list_url = reverse(update_locus_list_handler, args=[guid]) response = self.client.post(update_locus_list_url, content_type='application/json', data=json.dumps( {'name': 'updated_locus_list', 'isPublic': False, 'rawItems': 'DDX11L1 FAM138A'})) self.assertEqual(response.status_code, 200) updated_locus_list_response = response.json() self.assertEqual(len(updated_locus_list_response['locusListsByGuid']), 1) updated_locus_list = updated_locus_list_response['locusListsByGuid'].values()[0] self.assertEqual(updated_locus_list['name'], 'updated_locus_list') self.assertEqual(updated_locus_list['isPublic'], False) self.assertEqual(len(updated_locus_list_response['genesById']), 2) self.assertTrue(gene_id in updated_locus_list_response['genesById']) new_gene_id = next(gid for gid in updated_locus_list_response['genesById'] if gid != gene_id) self.assertSetEqual({item['geneId'] for item in updated_locus_list['items']}, {new_gene_id, gene_id}) updated_locus_list_model = LocusList.objects.filter(guid=guid).first() self.assertIsNotNone(updated_locus_list_model) self.assertEqual(updated_locus_list_model.name, updated_locus_list['name']) self.assertEqual(updated_locus_list_model.is_public, updated_locus_list['isPublic']) self.assertEqual(updated_locus_list_model.locuslistgene_set.count(), 2) self.assertEqual(updated_locus_list_model.locuslistgene_set.last().gene_id, new_gene_id) self.assertEqual(updated_locus_list_model.locuslistinterval_set.count(), 0) # delete the locus_list delete_locus_list_url = reverse(delete_locus_list_handler, args=[guid]) response = self.client.post(delete_locus_list_url, content_type='application/json') self.assertEqual(response.status_code, 200) # check that locus_list was deleted new_locus_list = LocusList.objects.filter(guid=guid) self.assertEqual(len(new_locus_list), 0)