def test_sync_rml_orderform_inactivate(rml_store: Store, rml_orderform: str, helpers: StoreHelpers): # GIVEN a rml orderform and a store where all the apptags exists half some inactive and # some active prep_category = "rml" sign = "PG" activate = False inactivate = True helpers.add_application( store=rml_store, application_tag="apptag_to_inactivate", is_archived=False, application_type=prep_category, ) active_apps_from_start = rml_store.applications(category=prep_category, archived=False).count() inactive_apps_from_start = rml_store.applications(category=prep_category, archived=True).count() # WHEN syncing app-tags in that orderform import_apptags( store=rml_store, excel_path=rml_orderform, prep_category=prep_category, signature=sign, activate=activate, inactivate=inactivate, sheet_name="Drop down list", tag_column=0, tag_row=1, ) # THEN the number of active should be less and the number of inactive more than before active_apps_after_when = rml_store.applications(category=prep_category, archived=False).count() inactive_apps_after_when = rml_store.applications(category=prep_category, archived=True).count() assert active_apps_from_start > active_apps_after_when assert inactive_apps_from_start < inactive_apps_after_when
def test_get_presence_status_status_db( caplog, helpers: StoreHelpers, wipe_demultiplex_api: DeleteDemuxAPI, flowcell_name: str, ): """Test to see if the presence of a flowcell is detected in status-db""" caplog.set_level(logging.INFO) # GIVEN DeleteDemuxAPI objects, one with amd one without a flowcell in status-db wipe_demux_api: DeleteDemuxAPI = wipe_demultiplex_api # WHEN the flowcell name is parsed and fetched fetching the presence of a flowcell in either context empty_presence: bool = wipe_demux_api.status_db_presence # THEN there should be an appropriate presence in both cases assert not empty_presence # WHEN adding a flowcell into the statusdb and checking its updated presence helpers.add_flowcell(store=wipe_demux_api.status_db, flowcell_id=flowcell_name, sequencer_type="novaseq") populated_presence: bool = wipe_demux_api.status_db_presence # THEN the presence should be updated assert populated_presence
def test_add_relationship_bad_father(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test to add a relationship using a non-existing father""" # GIVEN a database with a sample and an case disk_store: Store = base_context.status_db sample = helpers.add_sample(disk_store) sample_id = sample.internal_id father_id = "bad_father" case = helpers.add_case(disk_store) case_id = case.internal_id status = "affected" # WHEN adding a relationship result = cli_runner.invoke( add, [ "relationship", case_id, sample_id, "-s", status, "-f", father_id, ], obj=base_context, ) # THEN it should not be added assert result.exit_code == 1 assert disk_store.FamilySample.query.count() == 0
def test_add_family_required(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test to add a case using only the required arguments""" # GIVEN a database with a customer and an panel disk_store: Store = base_context.status_db customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id panel: models.Panel = helpers.ensure_panel(store=disk_store) panel_id = panel.name name = "case_name" # WHEN adding a panel result = cli_runner.invoke( add, [ "family", "--panel", panel_id, "--analysis", CLI_OPTION_ANALYSIS, "--data-delivery", CLI_OPTION_DELIVERY, customer_id, name, ], obj=base_context, ) # THEN it should be added assert result.exit_code == 0 assert disk_store.Family.query.count() == 1 assert disk_store.Family.query.first().name == name assert disk_store.Family.query.first().panels == [panel_id]
def test_delete_case_with_dry_run( cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers, caplog ): """Test that the delete case will not delete the case in dry-run mode""" # GIVEN a database with a case base_store: Store = base_context.status_db case_obj = helpers.add_case(base_store) case_id = case_obj.internal_id sample = helpers.add_sample(base_store) helpers.add_relationship(store=base_store, case=case_obj, sample=sample) assert base_store.Family.query.count() == 1 assert base_store.FamilySample.query.count() == 1 assert base_store.Sample.query.count() == 1 # WHEN deleting a case caplog.set_level(logging.DEBUG) result = cli_runner.invoke( delete_case_command, [case_id, "--yes", "--dry-run"], obj=base_context ) # THEN it should not have been deleted assert result.exit_code == SUCCESS assert base_store.Family.query.count() == 1 assert base_store.FamilySample.query.count() == 1 assert base_store.Sample.query.count() == 1 assert "Link:" in caplog.text assert "Sample is linked" in caplog.text assert "Case:" in caplog.text assert " was NOT deleted due to --dry-run" in caplog.text
def test_add_sample_required(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): # GIVEN a database with a customer and an application disk_store: Store = base_context.status_db sex = "male" application_tag = "dummy_tag" helpers.ensure_application(store=disk_store, tag=application_tag) helpers.ensure_application_version(store=disk_store, application_tag=application_tag) customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id name = "sample_name" # WHEN adding a sample result = cli_runner.invoke( add, [ "sample", "--sex", sex, "--application", application_tag, customer_id, name, ], obj=base_context, ) # THEN it should be added assert result.exit_code == 0 assert disk_store.Sample.query.count() == 1 assert disk_store.Sample.query.first().name == name assert disk_store.Sample.query.first().sex == sex
def test_add_family_priority(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test that the added case get the priority we send in""" # GIVEN a database with a customer and an panel disk_store: Store = base_context.status_db # WHEN adding a case customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id panel: models.Panel = helpers.ensure_panel(store=disk_store) panel_id = panel.name name = "case_name" priority = "priority" result = cli_runner.invoke( add, [ "family", "--panel", panel_id, "--priority", priority, "--analysis", CLI_OPTION_ANALYSIS, "--data-delivery", CLI_OPTION_DELIVERY, customer_id, name, ], obj=base_context, ) # THEN it should be added assert result.exit_code == 0 assert disk_store.Family.query.count() == 1 assert disk_store.Family.query.first().priority_human == priority
def test_add_family_bad_data_delivery( cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers ): """Test to add a case using only the required arguments""" # GIVEN a database with a customer and an panel # WHEN adding a case without data delivery disk_store: Store = base_context.status_db customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id panel: models.Panel = helpers.ensure_panel(store=disk_store) panel_id = panel.name name = "case_name" non_existing_data_delivery = "aws" result = cli_runner.invoke( add, [ "case", "--panel", panel_id, "--analysis", CLI_OPTION_ANALYSIS, "--data-delivery", non_existing_data_delivery, customer_id, name, ], obj=base_context, ) # THEN it should not be added assert result.exit_code != 0 assert disk_store.Family.query.count() == 0
def test_dry_run( cli_runner: CliRunner, clean_context: CGConfig, timestamp_yesterday: dt.datetime, helpers: StoreHelpers, caplog, mocker, ): """Test command with dry run options""" # GIVEN a case on disk that could be deleted caplog.set_level(logging.INFO) base_store = clean_context.status_db helpers.add_analysis( base_store, pipeline=Pipeline.BALSAMIC, started_at=timestamp_yesterday, uploaded_at=timestamp_yesterday, cleaned_at=None, ) case_id = "balsamic_case_clean" analysis_to_clean = base_store.family(case_id).analyses[0] case_path = clean_context.meta_apis["analysis_api"].get_case_path(case_id) Path(case_path).mkdir(exist_ok=True, parents=True) mocker.patch.object(TrailblazerAPI, "is_latest_analysis_ongoing") TrailblazerAPI.is_latest_analysis_ongoing.return_value = False # WHEN dry running with dry run specified result = cli_runner.invoke(clean_run_dir, [case_id, "-d", "-y"], obj=clean_context) # THEN command should say it would have deleted assert result.exit_code == EXIT_SUCCESS assert "Would have deleted" in caplog.text assert case_id in caplog.text assert analysis_to_clean in base_store.analyses_to_clean(pipeline=Pipeline.BALSAMIC)
def test_add_relationship_mother(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test to add a relationship with a mother""" # GIVEN a database with a sample and an case disk_store: Store = base_context.status_db sample = helpers.add_sample(disk_store) sample_id = sample.internal_id mother = helpers.add_sample(disk_store, name="mother") mother_id = mother.internal_id case = helpers.add_case(disk_store) case_id = case.internal_id status = "affected" # WHEN adding a relationship result = cli_runner.invoke( add, [ "relationship", case_id, sample_id, "-s", status, "-m", mother_id, ], obj=base_context, ) # THEN it should be added assert result.exit_code == 0 assert disk_store.FamilySample.query.count() == 1 assert disk_store.FamilySample.query.first( ).mother.internal_id == mother_id
def fixture_real_populated_compress_fastq_api( real_compress_api: CompressAPI, compress_hk_fastq_bundle: dict, helpers: StoreHelpers) -> CompressAPI: """Populated compress api fixture""" helpers.ensure_hk_bundle(real_compress_api.hk_api, compress_hk_fastq_bundle) return real_compress_api
def fixture_microbial_store_dummy_tag(microbial_store: Store, helpers: StoreHelpers) -> Store: """Populate a microbial store with a extra dummy app tag""" helpers.ensure_application(store=microbial_store, tag="dummy_tag", application_type="mic", is_archived=False) return microbial_store
def fixture_applications_store(store: Store, application_versions_file: str, helpers: StoreHelpers) -> Store: """Return a store populated with applications from excel file""" versions: Iterable[ApplicationVersionSchema] = parse_application_versions( excel_path=application_versions_file) for version in versions: helpers.ensure_application(store=store, tag=version.app_tag) return store
def test_lists_family(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test to that cases displays case in database""" # GIVEN a database with a case base_store: Store = base_context.status_db case = helpers.add_case(base_store) # WHEN listing cases result = cli_runner.invoke(cases, obj=base_context) # THEN the case should be listed assert result.exit_code == 0 assert case.internal_id in result.output
def test_delete_case_with_father_links( cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers ): """Test that the delete case will not delete a sample linked to another case as father""" # GIVEN a database with a case base_store: Store = base_context.status_db case_obj = helpers.add_case(base_store, "first_case_linked_to_sample") case_id = case_obj.internal_id sample_father = helpers.add_sample(base_store, "father") sample_child = helpers.add_sample(base_store, "child") helpers.add_relationship(store=base_store, case=case_obj, sample=sample_father) case_obj2 = helpers.add_case(base_store, "second_case_linked_to_sample") helpers.add_relationship( store=base_store, case=case_obj2, sample=sample_child, father=sample_father ) assert base_store.Family.query.count() == 2 assert base_store.FamilySample.query.count() == 2 assert base_store.Sample.query.count() == 2 # WHEN deleting a case result = cli_runner.invoke(delete_case_command, [case_id, "--yes"], obj=base_context) # THEN the first case should be gone with its link to the sample but not the other or # the father sample assert result.exit_code == SUCCESS assert base_store.Family.query.count() == 1 assert base_store.FamilySample.query.count() == 1 assert base_store.Sample.query.count() == 2
def test_delete_case_without_options( cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers ): """Test to delete a case using only the required arguments""" # GIVEN a database with a case base_store: Store = base_context.status_db helpers.add_case(base_store) assert base_store.Family.query.count() == 1 # WHEN deleting a case result = cli_runner.invoke(delete_case_command, obj=base_context) # THEN it should abort assert result.exit_code != SUCCESS
def test_delete_child_case(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test that the delete case will not delete a sample linked to another case as mother""" # GIVEN a database with a mother case and a child case with the mother as mother base_store: Store = base_context.status_db case_mother = helpers.add_case(base_store, "case_mother") sample_mother = helpers.add_sample(base_store, "mother") sample_child = helpers.add_sample(base_store, "child") helpers.add_relationship(store=base_store, case=case_mother, sample=sample_mother) case_child = helpers.add_case(base_store, "case_child") case_child_id = case_child.internal_id helpers.add_relationship( store=base_store, case=case_child, sample=sample_child, mother=sample_mother ) assert base_store.Family.query.count() == 2 assert base_store.FamilySample.query.count() == 2 assert base_store.Sample.query.count() == 2 # WHEN deleting the child case result = cli_runner.invoke(delete_case_command, [case_child_id, "--yes"], obj=base_context) # THEN the child sample is deletable assert result.exit_code == SUCCESS assert base_store.Family.query.count() == 1 assert base_store.FamilySample.query.count() == 1 assert base_store.Sample.query.count() == 1
def fixture_rml_store(store: Store, helpers: StoreHelpers) -> Store: """Populate a store with microbial application tags""" active_apptags = [ "RMLP10R300", "RMLP10S130", "RMLP15R100", "RMLP15R200", "RMLP15R400", "RMLP15R500", "RMLP15R750", "RMLP15R825", "RMLP15S100", "RMLP15S125", "RMLP15S150", "RMLP15S175", "RMLP15S200", "RMLP15S225", "RMLP15S425", ] inactive_apptags = [ "RMLP05R800", "RMLP15S250", "RMLP15S275", "RMLP15S300", "RMLP15S325", "RMLP15S350", "RMLP15S375", "RMLP15S400", "RMLP15S450", "RMLP15S475", "RMLP15S500", "RMLS05R200", "RMLCUSR800", "RMLCUSS160", ] for app_tag in active_apptags: helpers.ensure_application(store=store, tag=app_tag, application_type="rml", is_archived=False) for app_tag in inactive_apptags: helpers.ensure_application(store=store, tag=app_tag, application_type="rml", is_archived=True) return store
def test_validate_sex_unknown_new_sex(orders_api: OrdersAPI, mip_order_to_submit: dict, helpers: StoreHelpers): # GIVEN we have an order with a sample that is already in the database and with different gender but the new is of # type "unknown" order_data = OrderIn.parse_obj(mip_order_to_submit, project=OrderType.MIP_DNA) store = orders_api.status customer_obj = store.customer(order_data.customer) # add sample with different sex than in order for sample in order_data.samples: sample_obj: models.Sample = helpers.add_sample( store=store, subject_id=sample.subject_id, name=sample.name, gender=sample.sex, customer_id=customer_obj.internal_id, ) sample.sex = "unknown" store.add_commit(sample_obj) for sample in order_data.samples: assert sample_obj.sex != sample.sex submitter: MipDnaSubmitter = MipDnaSubmitter(lims=orders_api.lims, status=orders_api.status) # WHEN calling _validate_sex submitter._validate_subject_sex(samples=order_data.samples, customer_id=order_data.customer)
def test_analysis_without_started_at(upload_context: CGConfig, cli_runner: CliRunner, helpers: StoreHelpers, caplog): # GIVEN a correct case_id and a correct date analysis: models.Analysis = helpers.add_analysis( upload_context.status_db, started_at=datetime.now(), pipeline=Pipeline.MIP_DNA, ) case_id: str = analysis.family.internal_id a_date: datetime = analysis.started_at assert a_date caplog.set_level(logging.INFO) # WHEN calling delivery_report without date parameter cli_runner.invoke( delivery_report, [case_id], obj=upload_context, ) # THEN it should contain the date in the logged info assert "Using analysis started at: " in caplog.text
def test_validate_sex_inconsistent_sex(orders_api: OrdersAPI, mip_order_to_submit: dict, helpers: StoreHelpers): # GIVEN we have an order with a sample that is already in the database but with different sex order_data = OrderIn.parse_obj(mip_order_to_submit, project=OrderType.MIP_DNA) store = orders_api.status customer_obj = store.customer(order_data.customer) # add sample with different sex than in order sample: MipDnaSample for sample in order_data.samples: sample_obj: models.Sample = helpers.add_sample( store=store, subject_id=sample.subject_id, name=sample.name, gender="male" if sample.sex == "female" else "female", customer_id=customer_obj.internal_id, ) store.add_commit(sample_obj) assert sample_obj.sex != sample.sex submitter: MipDnaSubmitter = MipDnaSubmitter(lims=orders_api.lims, status=orders_api.status) # WHEN calling _validate_sex # THEN an OrderError should be raised on non-matching sex with pytest.raises(OrderError): submitter._validate_subject_sex(samples=order_data.samples, customer_id=order_data.customer)
def fixture_rna_mip_context( cg_context: CGConfig, analysis_family_single_case: dict, helpers: StoreHelpers, apptag_rna: str, case_id: str, housekeeper_api: HousekeeperAPI, ) -> CGConfig: cg_context.housekeeper_api_ = housekeeper_api analysis_family_single_case["data_analysis"] = str(Pipeline.MIP_RNA) if not cg_context.status_db.family(case_id): helpers.ensure_case_from_dict(cg_context.status_db, case_info=analysis_family_single_case, app_tag=apptag_rna) cg_context.meta_apis["analysis_api"] = MipRNAAnalysisAPI(cg_context) return cg_context
def test_add_sample_bad_application(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): # GIVEN a database with a customer disk_store: Store = base_context.status_db # WHEN adding a sample sex = "male" application = "dummy_application" customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id name = "dummy_name" result = cli_runner.invoke( add, [ "sample", "--sex", sex, "--application", application, customer_id, name, ], obj=base_context, ) # THEN it should complain about missing application instead of adding a sample assert result.exit_code == 1 assert disk_store.Sample.query.count() == 0
def test_add_family_bad_panel(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers): """Test to add a case using a non-existing panel""" # GIVEN a database with a customer disk_store: Store = base_context.status_db # WHEN adding a case customer: models.Customer = helpers.ensure_customer(store=disk_store) customer_id = customer.internal_id panel_id = "dummy_panel" name = "dummy_name" result = cli_runner.invoke( add, [ "family", "--panel", panel_id, "--analysis", CLI_OPTION_ANALYSIS, "--data-delivery", CLI_OPTION_DELIVERY, customer_id, name, ], obj=base_context, ) # THEN it should complain about missing panel instead of adding a case assert result.exit_code == 1 assert disk_store.Family.query.count() == 0
def test_validate_submitted_order(sarscov2_order_to_submit: dict, base_store: Store, helpers: StoreHelpers): # GIVEN sarscov2 order with three samples, all in the database order: OrderIn = OrderIn.parse_obj(sarscov2_order_to_submit, OrderType.SARS_COV_2) sample: SarsCov2Sample for sample in order.samples: helpers.add_sample(store=base_store, name=sample.name, customer_id=order.customer) # WHEN validating the order # THEN it should be regarded as invalid with (pytest.raises(OrderError)): SarsCov2Submitter(status=base_store, lims=None).validate_order(order=order)
def test_validate_submitted_control_order(sarscov2_order_to_submit: dict, base_store: Store, helpers: StoreHelpers): # GIVEN sarscov2 order with three control samples, all in the database order: OrderIn = OrderIn.parse_obj(sarscov2_order_to_submit, OrderType.SARS_COV_2) sample: SarsCov2Sample for sample in order.samples: helpers.add_sample(store=base_store, name=sample.name, customer_id=order.customer) sample.control = ControlEnum.positive # WHEN validating the order # THEN it should be regarded as valid SarsCov2Submitter(status=base_store, lims=None).validate_order(order=order)
def test_upload_auto_with_pipeline_as_argument( cli_runner: CliRunner, helpers: StoreHelpers, timestamp: datetime.datetime, upload_context: CGConfig, caplog, ): """Test upload auto""" # GIVEN a store with a MIP analysis pipeline = Pipeline.MIP_DNA helpers.add_analysis(store=upload_context.status_db, completed_at=timestamp, pipeline=pipeline) # WHEN uploading all analysis from pipeline MIP caplog.set_level(logging.INFO) cli_runner.invoke(auto, ["--pipeline", "mip-dna"], obj=upload_context) # THEN assert that the MIP analysis was successfully uploaded assert "Uploading family" in caplog.text
def test_lists_sample_in_unreceived_samples( cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers ): """Test to that cases displays case in database""" # GIVEN a database with a case base_store: Store = base_context.status_db case = helpers.add_case(base_store) sample1 = helpers.add_sample(base_store, "sample1") helpers.add_relationship(base_store, case=case, sample=sample1) # WHEN listing cases result = cli_runner.invoke(cases, ["-o", "count"], obj=base_context) # THEN the case should be listed assert result.exit_code == 0 assert case.internal_id in result.output assert "0/1" in result.output
def test_validate_case_name(rml_order_to_submit: dict, base_store: Store, helpers: StoreHelpers): # GIVEN pool order with a case already all in the database order: OrderIn = OrderIn.parse_obj(rml_order_to_submit, OrderType.RML) sample: RmlSample customer: models.Customer = helpers.ensure_customer( store=base_store, customer_id=order.customer) for sample in order.samples: case = helpers.ensure_case( store=base_store, name=PoolSubmitter.create_case_name(ticket=order.ticket, pool_name=sample.pool), customer=customer, data_analysis=Pipeline.FLUFFY, data_delivery=DataDelivery.STATINA, ) base_store.add_commit(case)
def test_get_samples_required(cli_runner: CliRunner, base_context: CGConfig, disk_store: Store, helpers: StoreHelpers): """Test to get several samples using only the required arguments""" # GIVEN a database with two samples sample_id1 = "1" helpers.add_sample(store=disk_store, internal_id=sample_id1) sample_id2 = "2" helpers.add_sample(store=disk_store, internal_id=sample_id2) assert disk_store.Sample.query.count() == 2 # WHEN getting a sample result = cli_runner.invoke(get, ["sample", sample_id1, sample_id2], obj=base_context) # THEN it should have been get assert result.exit_code == 0 assert sample_id1 in result.output assert sample_id2 in result.output