def test_job_number_can_be_changed(self, mock_get_client): old_number = "FS10000" new_number = "FS10001" instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) job = TalentLinkJobFactory( talentlink_id=1, job_number=old_number, last_imported=instant, homepage=self.homepage, ) advertisements = [ get_advertisement(talentlink_id=1, job_number=new_number) ] mock_get_client.return_value = self.get_mocked_client(advertisements) later = instant + datetime.timedelta(days=1) with freeze_time(later): call_command("import_jobs", stdout=mock.MagicMock()) # No new job has been created self.assertEqual(TalentLinkJob.objects.count(), 1) job.refresh_from_db() self.assertEqual(job.talentlink_id, 1) self.assertEqual(job.job_number, new_number) # The job has been reimported self.assertEqual(job.last_imported, later)
def test_job_logo_is_removed_if_removed_in_import( self, mock_import_image_from_url, mock_get_client): job = TalentLinkJobFactory(talentlink_id=1) logo = ImageFactory(talentlink_image_id="aaa") job.logo = logo job.save() advertisements = [ get_advertisement(talentlink_id=1, title="New title 1"), ] logos = [ {}, ] mock_get_client.return_value = self.get_mocked_client(advertisements, logos=logos) out = StringIO() call_command("import_jobs", stdout=out) out.seek(0) output = out.read() self.assertIn("1 existing jobs updated", output) self.assertIn("0 new images imported", output) self.assertEqual( TalentLinkJob.objects.get(talentlink_id=1).logo, None, ) self.assertEqual( CustomImage.objects.filter(talentlink_image_id="aaa").count(), 0, )
def test_job_missing_from_import_are_deleted(self, mock_get_client): instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) TalentLinkJobFactory(talentlink_id=1, last_imported=instant, homepage=self.homepage) TalentLinkJobFactory(talentlink_id=2, last_imported=instant, homepage=self.homepage) self.assertEqual(TalentLinkJob.objects.count(), 2) advertisements = [get_advertisement(talentlink_id=2)] mock_get_client.return_value = self.get_mocked_client(advertisements) call_command("import_jobs", stdout=mock.MagicMock()) # Only one new job remains. Jobs not in import are deleted. self.assertEqual(TalentLinkJob.objects.count(), 1) self.assertEqual( TalentLinkJob.objects.filter(talentlink_id=1).count(), 0) self.assertEqual( TalentLinkJob.objects.filter(talentlink_id=2).count(), 1)
def test_attachments_are_not_deleted_if_another_job_uses_them( self, mock_get_client): job_1 = TalentLinkJobFactory(talentlink_id=1, homepage=self.homepage) doc_1 = DocumentFactory(talentlink_attachment_id=111) doc_2 = DocumentFactory(talentlink_attachment_id=222) job_1.attachments.add(doc_1) job_1.attachments.add(doc_2) job_1.save() job_2 = TalentLinkJobFactory(talentlink_id=2, homepage=self.homepage) job_2.attachments.add(doc_1) job_2.save() job = TalentLinkJob.objects.get(talentlink_id=1) doc = CustomDocument.objects.get(talentlink_attachment_id=111) self.assertEqual(doc.jobs.all().count(), 2) job.delete() job = TalentLinkJob.objects.filter(talentlink_id=1) doc = CustomDocument.objects.filter(talentlink_attachment_id=111) self.assertEqual(job.count(), 0) self.assertEqual( doc.count(), 1, msg= "attached document should be not deleted if it is being used elsewhere", ) self.assertEqual(doc[0].jobs.all().count(), 1) job_2 = TalentLinkJob.objects.get(talentlink_id=2) self.assertEqual(job_2.attachments.first(), doc[0])
def setUp(self): """ Set up 5 subcategories and 2 categories """ self.talentlinkjobs = [] self.subcategories = [] self.categories = [] self.root_page = Page.objects.get(id=1) self.homepage = RecruitmentHomePageFactory.build_with_fk_objs_committed( job_board=JOB_BOARD_CHOICES[0] ) self.root_page.add_child(instance=self.homepage) self.homepage_internal = RecruitmentHomePageFactory.build_with_fk_objs_committed( job_board=JOB_BOARD_CHOICES[1] ) self.root_page.add_child(instance=self.homepage_internal) for i in range(4): subcat = JobSubcategoryFactory.build() subcat.save() # Add jobs for each subcategory according to its index (eg. self.subcategories[2] gets 2 jobs) for j in range(i): job = TalentLinkJobFactory.build(homepage=self.homepage) job.subcategory = subcat job.save() self.talentlinkjobs.append(job) self.subcategories.append(subcat) for i in range(2): cat = JobCategoryFactory.build() cat.save() self.categories.append(cat)
def test_job_number_clash_with_existing_job(self, mock_get_client): job_number = "FS10000" instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) job = TalentLinkJobFactory( talentlink_id=1, job_number=job_number, last_imported=instant, homepage=self.homepage, ) advertisements = [ get_advertisement(talentlink_id=1, job_number=job_number), get_advertisement(talentlink_id=2, job_number=job_number), ] mock_get_client.return_value = self.get_mocked_client(advertisements) later = instant + datetime.timedelta(days=1) with freeze_time(later): call_command("import_jobs", stdout=mock.MagicMock()) jobs = TalentLinkJob.objects.filter(job_number=job_number) self.assertEqual(jobs.count(), 2) # Both jobs have been (re)imported for job in jobs: self.assertEqual(job.last_imported, later)
def test_get_categories_summary_respects_job_board(self): self.categories[1].subcategories.add( self.subcategories[1] ) # this subcategory has 1 job summary = JobCategory.get_categories_summary(homepage=self.homepage) self.assertEqual(summary.count(), 1) # Should return nothing since the jobs in setup are all external jobs (JOB_BOARD_CHOICES[0]) summary = JobCategory.get_categories_summary(homepage=self.homepage_internal) self.assertEqual(summary.count(), 0) # Create internal job job = TalentLinkJobFactory(homepage=self.homepage_internal) job.subcategory = self.subcategories[1] job.save() summary = JobCategory.get_categories_summary(homepage=self.homepage_internal) self.assertEqual(summary.count(), 1)
def test_pound_sign_values_ordered_first(self): TalentLinkJobFactory(homepage=self.homepage, searchable_salary="£1") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Everything") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Anything") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="£2") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Zero") request = RequestFactory().get(self.homepage.url, SERVER_NAME=self.site.hostname) context = jobs_search_filters(request) self.assertEqual( [ foo["label"] for foo in context["filters"][ self.salary_filter_index]["options"] ], ["£1", "£2", "Anything", "Everything", "Zero"], )
def test_pound_signs_later_in_the_string_ordered_first(self): TalentLinkJobFactory(homepage=self.homepage, searchable_salary="£1") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="£30,001 - £40,000") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Everything") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Up to £4") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="£20,001 - £30,000") TalentLinkJobFactory(homepage=self.homepage, searchable_salary="Zero") request = RequestFactory().get(self.homepage.url, SERVER_NAME=self.site.hostname) context = jobs_search_filters(request) self.assertEqual( [ foo["label"] for foo in context["filters"][ self.salary_filter_index]["options"] ], [ "Up to £4", "£1", "£20,001 - £30,000", "£30,001 - £40,000", "Everything", "Zero", ], )
def test_existing_job_imported_date(self, mock_get_client): instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) job = TalentLinkJobFactory(talentlink_id=164579, last_imported=instant, homepage=self.homepage) self.assertEqual(job.last_imported, instant) mock_get_client.return_value = self.get_mocked_client() later = instant + datetime.timedelta(days=1) with freeze_time(later): call_command("import_jobs", stdout=mock.MagicMock()) job.refresh_from_db() self.assertEqual(job.last_imported, later)
def test_update_existing_job_and_importing_missing_subcategories( self, mock_get_client): TalentLinkJobFactory(talentlink_id=164579, homepage=self.homepage) mock_get_client.return_value = self.get_mocked_client() JobSubcategory.objects.get( title=FIXTURE_JOB_SUBCATEGORY_TITLE).delete() out = StringIO() call_command("import_jobs", "--import_categories", stdout=out) out.seek(0) output = out.read() self.assertIn("1 existing jobs updated", output) self.assertIn("0 new jobs created", output)
def test_descriptions_are_updated(self): job = TalentLinkJobFactory(talentlink_id=1, description="Old value", homepage=self.homepage) description = [{ "label": "New Info", "order": 1, "value": "<p>This is a paragraph of text.</p>", }] expected = """ <h3>New Info</h3> <p>This is a paragraph of text.</p> """ self.assertEqual(job.description, "Old value") self.compare_processed_record(description, expected)
def test_with_existing_job(self, mock_get_client): TalentLinkJobFactory(talentlink_id=164579, homepage=self.homepage) mock_get_client.return_value = self.get_mocked_client() out = StringIO() call_command("import_jobs", stdout=out) out.seek(0) output = out.read() self.assertIn("1 existing jobs updated", output) self.assertIn("0 new jobs created", output) self.assertEqual( JobSubcategory.objects.filter( title=FIXTURE_JOB_SUBCATEGORY_TITLE).count(), 1, msg= "Category should be inserted if --import_categories is specified.", )
def test_attachments_are_deleted_when_the_job_is(self, mock_get_client): job = TalentLinkJobFactory(talentlink_id=1, homepage=self.homepage) doc = DocumentFactory(talentlink_attachment_id=111) job.attachments.add(doc) job.save() job = TalentLinkJob.objects.filter(talentlink_id=1) doc = CustomDocument.objects.filter(talentlink_attachment_id=111) self.assertEqual(job.count(), 1) self.assertEqual(doc.count(), 1) job.delete() job = TalentLinkJob.objects.filter(talentlink_id=1) doc = CustomDocument.objects.filter(talentlink_attachment_id=111) self.assertEqual(job.count(), 0) self.assertEqual( doc.count(), 0, msg="attached document should be deleted if its job is deleted", )
def test_update_existing_job_with_missing_subcategories( self, mock_get_client): TalentLinkJobFactory(talentlink_id=164579, homepage=self.homepage) mock_get_client.return_value = self.get_mocked_client() JobSubcategory.objects.get( title=FIXTURE_JOB_SUBCATEGORY_TITLE).delete() out = StringIO() call_command("import_jobs", stdout=out) out.seek(0) output = out.read() self.assertIn("0 existing jobs updated", output) self.assertIn("0 new jobs created", output) self.assertIn("JobSubcategory matching query does not exist.", output) self.assertEqual( JobSubcategory.objects.filter( title=FIXTURE_JOB_SUBCATEGORY_TITLE).count(), 0, msg= "Subcategory should not be inserted if --import_categories is not specified.", )
def test_logo_is_deleted_when_the_job_is(self, mock_import_image_from_url, mock_get_client): job_1 = TalentLinkJobFactory(talentlink_id=1) job_2 = TalentLinkJobFactory(talentlink_id=2) logo_1 = ImageFactory() logo_2 = ImageFactory() job_1.logo = logo_1 job_2.logo = logo_2 job_1.save() job_2.save() self.assertEqual( TalentLinkJob.objects.get(talentlink_id=1).logo, CustomImage.objects.get(id=logo_1.id), ) job_1.delete() self.assertEqual( CustomImage.objects.filter(id=logo_1.id).count(), 0, msg="Logo 1 should be deleted when Job 1 is.", ) self.assertEqual( TalentLinkJob.objects.get(talentlink_id=2).logo, CustomImage.objects.get(id=logo_2.id), msg= "Job 2 and Logo 2 should be unaffected when Job 1 and Logo 1 is deleted.", )
def test_logo_is_not_deleted_if_another_job_is_using_it( self, mock_import_image_from_url, mock_get_client): job_1 = TalentLinkJobFactory(talentlink_id=1) job_2 = TalentLinkJobFactory(talentlink_id=2) logo = ImageFactory() job_1.logo = logo job_2.logo = logo job_1.save() job_2.save() self.assertEqual( TalentLinkJob.objects.get(talentlink_id=1).logo, CustomImage.objects.get(id=logo.id), ) self.assertEqual( TalentLinkJob.objects.get(talentlink_id=2).logo, CustomImage.objects.get(id=logo.id), ) job_1.delete() self.assertEqual( CustomImage.objects.filter(id=logo.id).count(), 1, msg="Logo should not be deleted if it is still in use.", ) self.assertEqual( TalentLinkJob.objects.get(talentlink_id=2).logo, CustomImage.objects.get(id=logo.id), msg= "Job 2 and its logo should be unaffected when Job 1 is deleted.", )
def test_error_cases_are_not_imported(self, mock_update_fn, mock_get_client): instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) TalentLinkJobFactory( talentlink_id=1, title="Original title 1", last_imported=instant, homepage=self.homepage, ) job_2 = TalentLinkJobFactory( talentlink_id=2, title="Original title 2", last_imported=instant, homepage=self.homepage, ) self.assertEqual(TalentLinkJob.objects.count(), 2) error_message = "This is a test error message" def error_or_original(job, ad, homepage, defaults, import_categories): """ Raise an error for id 1 only""" if job.talentlink_id == 1: raise KeyError(error_message) else: return update_job_from_ad(job, ad, self.homepage, defaults, import_categories) mock_update_fn.side_effect = error_or_original advertisements = [ get_advertisement(talentlink_id=1, title="New title 1"), get_advertisement(talentlink_id=2, title="New title 2"), ] mock_get_client.return_value = self.get_mocked_client(advertisements) out = StringIO() later = instant + datetime.timedelta(days=1) with freeze_time(later): call_command("import_jobs", stdout=out) out.seek(0) output = out.read() self.assertIn(error_message, output) self.assertIn("1 existing jobs updated", output) self.assertIn("1 errors", output) # job_1 should have been deleted from db as it isn't imported self.assertEqual( TalentLinkJob.objects.filter(talentlink_id=1).count(), 0, msg="Jobs not in import should be deleted.", ) job_2.refresh_from_db() self.assertEqual(job_2.title, "New title 2") # job 2 has been updated self.assertEqual(job_2.last_imported, later) # job 2 has been updated
def test_job_missing_from_import_are_deleted_only_if_from_same_board( self, mock_get_client): homepage_internal = RecruitmentHomePageFactory.build_with_fk_objs_committed( job_board=JOB_BOARD_CHOICES[1]) self.root_page.add_child(instance=homepage_internal) instant = datetime.datetime(2020, 1, 29, 12, 0, 0, tzinfo=datetime.timezone.utc) TalentLinkJobFactory( talentlink_id=1, job_number="AABBSAME", homepage=self.homepage, last_imported=instant, ) TalentLinkJobFactory( talentlink_id=2, job_number="CCDD", homepage=self.homepage, last_imported=instant, ) TalentLinkJobFactory( talentlink_id=3, job_number="AABBSAME", homepage=homepage_internal, last_imported=instant, ) self.assertEqual( TalentLinkJob.objects.filter(homepage=self.homepage).count(), 2) self.assertEqual( TalentLinkJob.objects.filter(homepage=homepage_internal).count(), 1) # Create mock client faking results for 2 boards board_external_advertisements = [ get_advertisement(talentlink_id=1, job_number="AABBSAME"), ] board_internal_advertisements = [ get_advertisement(talentlink_id=3, job_number="AABBSAME"), ] client = mock.Mock() client.service.getAdvertisementsByPage.side_effect = [ { "advertisements": { "advertisement": board_external_advertisements }, "totalResults": 143, }, no_further_pages_response, { "advertisements": { "advertisement": board_internal_advertisements }, "totalResults": 143, }, no_further_pages_response, ] mock_get_client.return_value = client call_command("import_jobs", import_categories=True, stdout=mock.MagicMock()) # Only one new job remains. Jobs not in import are deleted. self.assertEqual( TalentLinkJob.objects.filter(homepage=self.homepage).count(), 1) self.assertEqual( TalentLinkJob.objects.filter(homepage=homepage_internal).count(), 1)