def test_diagnostic_main_challenges(self) -> None: """Compute the diagnostic main challenge for a project.""" project = project_pb2.Project() project.original_self_diagnostic.category_id = 'bravo' self.user.profile.ClearField('gender') self.user.profile.locale = '' self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_one({ 'blockerSentence': 'bad profile', 'categoryId': 'everyone', 'filters': ['constant(3)'], 'metricDetails': 'Libéré·e', 'order': 1, 'bobExplanation': "postuler à des offres en ligne n'est pas le canal le plus efficace.", }) self.database.diagnostic_overall.insert_one({ 'categoryId': 'everyone', 'score': 50, 'sentenceTemplate': 'Manque de précision dans la recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.database.diagnostic_responses.insert_one({ 'responseId': 'bravo:everyone', 'text': "You shouldn't congratulate yourself just yet", }) self.database.translations.insert_many([ { 'string': 'Libéré·e_FEMININE', 'fr': 'Libérée', }, { 'string': 'Libéré·e_MASCULINE', 'fr': 'Libéré', }, { 'string': "postuler à des offres en ligne n'est pas le canal le plus efficace.", 'fr': "postuler à des offres en ligne n'est pas le canal le plus efficace.", }, ]) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertEqual('everyone', project.diagnostic.category_id) self.assertEqual(['everyone'], [c.category_id for c in project.diagnostic.categories]) self.assertEqual('Libéré·e', project.diagnostic.categories[0].metric_details) self.assertEqual(diagnostic_pb2.NEEDS_ATTENTION, project.diagnostic.categories[0].relevance) self.assertTrue(project.diagnostic.categories[0].is_highlighted) self.assertEqual('bad profile', project.diagnostic.categories[0].blocker_sentence) self.assertEqual("postuler à des offres en ligne n'est pas le canal le plus efficace.", project.diagnostic.bob_explanation) self.assertEqual( "You shouldn't congratulate yourself just yet", project.diagnostic.response)
def test_diagnostic_main_challenges_translation_key(self) -> None: """Compute the diagnostic main challenge for a project and use keys to translate it.""" project = project_pb2.Project() project.original_self_diagnostic.category_id = 'bravo' self.user.profile.gender = user_profile_pb2.MASCULINE self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_one({ 'categoryId': 'everyone', 'filters': ['constant(3)'], 'metricTitle': 'overriden by the translation', 'order': 1, 'bobExplanation': 'overriden by the translation', }) self.database.diagnostic_overall.insert_one({ 'categoryId': 'everyone', 'score': 50, 'sentenceTemplate': 'Manque de précision dans la recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.database.diagnostic_responses.insert_one({ 'responseId': 'bravo:everyone', 'text': 'Yo, random text!', }) self.database.translations.insert_many([ { 'string': 'diagnosticMainChallenges:everyone:metric_details_FEMININE', 'fr': 'Libérée', }, { 'string': 'diagnosticMainChallenges:everyone:metric_title', 'fr': 'The title', }, { 'string': 'diagnosticMainChallenges:everyone:metric_details_MASCULINE', 'fr': 'Libéré', }, { 'string': 'diagnosticMainChallenges:everyone:bob_explanation', 'fr': 'postuler', }, { 'string': 'diagnosticResponses:bravo:everyone:text', 'fr': 'You do not have a job yet', } ]) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertEqual(['The title'], [c.metric_title for c in project.diagnostic.categories]) self.assertEqual(['Libéré'], [c.metric_details for c in project.diagnostic.categories]) self.assertEqual('postuler', project.diagnostic.bob_explanation) self.assertEqual('You do not have a job yet', project.diagnostic.response)
def test_missing_diagnostic_main_challenges(self) -> None: """Does not set a main challenge ID if none is found.""" project = project_pb2.Project() self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_one({ 'categoryId': 'noone', 'filters': ['constant(0)'], 'order': 1, }) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertFalse(project.diagnostic.category_id) self.assertEqual(['noone'], [c.category_id for c in project.diagnostic.categories]) self.assertEqual( diagnostic_pb2.RELEVANT_AND_GOOD, project.diagnostic.categories[0].relevance)
def test_translate_diagnostic_overall_using_key(self) -> None: """Diagnostic overall uses keyed translations.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE self.user.profile.locale = 'fr@tu' self.database.diagnostic_overall.insert_one({ 'categoryId': 'women', 'id': 'rec0123456789', 'filters': ['for-women'], 'score': 50, 'sentenceTemplate': 'Manque de précision dans votre recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.database.translations.insert_many([ { 'string': 'diagnosticOverall:rec0123456789:sentence_template', 'fr@tu': 'You should check your methods', }, { 'string': 'diagnosticOverall:rec0123456789:sentence_template_FEMININE', 'fr@tu': 'You should check your methods, woman!', }, { 'string': 'diagnosticOverall:rec0123456789:text_template', 'fr@tu': 'Not enough precision in your search', }, ]) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual( 'You should check your methods, woman!', project.diagnostic.overall_sentence) self.assertEqual('Not enough precision in your search', project.diagnostic.text)
def test_translate_diagnostic_overall(self) -> None: """Diagnostic overall uses translations.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE self.user.profile.locale = 'fr@tu' self.database.diagnostic_overall.insert_one({ 'categoryId': 'women', 'filters': ['for-women'], 'score': 50, 'sentenceTemplate': 'Manque de précision dans votre recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.database.translations.insert_many([ { 'string': 'Vous devriez réfléchir à vos méthodes', 'fr@tu': 'Tu devrais réfléchir à tes méthodes', }, { 'string': 'Manque de précision dans votre recherche', 'fr@tu': 'Manque de précision dans ta recherche', }, ]) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual( 'Manque de précision dans ta recherche', project.diagnostic.overall_sentence) self.assertEqual('Tu devrais réfléchir à tes méthodes', project.diagnostic.text)
def test_diagnostic_main_challenges_translation(self) -> None: """Translate the diagnostic main challenge for a project.""" project = project_pb2.Project() self.user.profile.ClearField('gender') self.user.profile.locale = 'nl' self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_one({ 'blockerSentence': 'bad profile', 'categoryId': 'everyone', 'filters': ['constant(3)'], 'order': 1, 'bobExplanation': "postuler à des offres en ligne n'est pas le canal le plus efficace.", }) self.database.diagnostic_overall.insert_one({ 'categoryId': 'everyone', 'score': 50, 'sentenceTemplate': 'Manque de précision dans la recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.database.translations.insert_many([ { 'string': 'Manque de précision dans la recherche', 'nl': 'Gebrek aan precisie in onderzoek', }, { 'string': 'Vous devriez réfléchir à vos méthodes', 'nl': 'U moet nadenken over uw methoden', }, { 'string': 'bad profile', 'nl': 'slecht profiel', }, { 'string': "postuler à des offres en ligne n'est pas le canal le plus efficace.", 'nl': 'Online solliciteren is niet het meest efficiënte kanaal.', } ]) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertEqual('slecht profiel', project.diagnostic.categories[0].blocker_sentence) self.assertEqual('Online solliciteren is niet het meest efficiënte kanaal.', project.diagnostic.bob_explanation)
def _save_project(project: project_pb2.Project, previous_project: project_pb2.Project, user_data: user_pb2.User) -> project_pb2.Project: # TODO(cyrille): Check for completeness here, rather than in client. if project.is_incomplete: return project tick.tick('Process project start') rome_id = project.target_job.job_group.rome_id departement_id = project.city.departement_id if not project.project_id: # Add ID, timestamp and stats to new projects project.project_id = _create_new_project_id(user_data) common_proto.set_date_now(project.created_at) database = mongo.get_connections_from_env().stats_db tick.tick('Populate local stats') if previous_project.city.departement_id != departement_id or \ previous_project.target_job.job_group.rome_id != rome_id: project.ClearField('local_stats') if not project.HasField('local_stats'): project.local_stats.CopyFrom( jobs.get_local_stats(database, departement_id, rome_id)) tick.tick('Diagnostic') diagnostic.maybe_diagnose(user_data, project, database) tick.tick('Advisor') advisor.maybe_advise(user_data, project, database) tick.tick('Strategies') strategist.maybe_strategize(user_data, project, database) tick.tick('New feedback') if project.feedback.text and not previous_project.feedback.text: give_project_feedback(user_data.user_id, '@' in user_data.profile.email, project) tick.tick('Process project end') return project
def test_diagnostic_main_challenges_genderized(self) -> None: """Compute the diagnostic main challenge for a project and use its genderized details.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.MASCULINE self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_one({ 'categoryId': 'everyone', 'filters': ['constant(3)'], 'metricDetails': 'Libéré·e', 'order': 1, }) self.database.translations.insert_many([ { 'string': 'Libéré·e_FEMININE', 'fr': 'Libérée', }, { 'string': 'Libéré·e_MASCULINE', 'fr': 'Libéré', }, ]) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertEqual(['Libéré'], [c.metric_details for c in project.diagnostic.categories])
def test_diagnostic_multiple_main_challenges(self) -> None: """Compute the diagnostic main challenge for a project.""" project = project_pb2.Project() self.database.diagnostic_main_challenges.drop() self.database.diagnostic_main_challenges.insert_many([ { 'categoryId': 'second', 'filters': ['constant(0)'], 'order': 2, }, { 'categoryId': 'first', 'filters': ['constant(2)'], 'order': 1, }, { 'categoryId': 'third', 'filters': ['constant(3)'], 'order': 3, }, ]) diagnostic.maybe_diagnose(self.user, project, self.database) self.assertEqual('first', project.diagnostic.category_id) self.assertEqual( ['first', 'second', 'third'], [c.category_id for c in project.diagnostic.categories]) self.assertEqual( [ diagnostic_pb2.NEEDS_ATTENTION, diagnostic_pb2.RELEVANT_AND_GOOD, diagnostic_pb2.NEEDS_ATTENTION ], [c.relevance for c in project.diagnostic.categories]) self.assertEqual( [True, False, False], [c.is_highlighted for c in project.diagnostic.categories])
def test_templates_diagnostic_overall(self) -> None: """Diagnostic overall uses templates.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE project.target_job.name = 'Directrice technique' self.database.diagnostic_overall.insert_one({ 'categoryId': 'women', 'filters': ['for-women'], 'score': 50, 'sentenceTemplate': 'Améliorez votre recherche pour le métier %ofJobName', 'textTemplate': 'Vous êtes motivé%eFeminine', }) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual( 'Améliorez votre recherche pour le métier de directrice technique', project.diagnostic.overall_sentence) self.assertEqual('Vous êtes motivée', project.diagnostic.text)
def test_diagnostic(self, mock_logging: mock.MagicMock) -> None: """Compute a nice diagnostic with overall sentence.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE self.user.profile.locale = 'fr' self.database.diagnostic_overall.insert_one({ 'categoryId': 'women', 'filters': ['for-women'], 'score': 50, 'sentenceTemplate': 'Manque de précision dans la recherche', 'textTemplate': 'Vous devriez réfléchir à vos méthodes', }) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual(50, project.diagnostic.overall_score, msg=project.diagnostic) self.assertEqual( 'Manque de précision dans la recherche', project.diagnostic.overall_sentence) self.assertEqual('Vous devriez réfléchir à vos méthodes', project.diagnostic.text) mock_logging.assert_not_called()
def test_diagnostic_overall_sorted(self) -> None: """Get the overall sentence in order.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE self.database.diagnostic_overall.insert_many([ { '_order': 1, 'categoryId': 'women', 'sentenceTemplate': 'Overall text for women if nothing triggered', }, { '_order': 0, 'categoryId': 'women', 'sentenceTemplate': 'Overall text for women as first pass', }, ]) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual( 'Overall text for women as first pass', project.diagnostic.overall_sentence)
def test_diagnostic_overall_restrict_to_main_challenge(self) -> None: """Get the overall sentence for a specific main challenge.""" project = project_pb2.Project() self.user.profile.gender = user_profile_pb2.FEMININE self.user.profile.locale = 'fr@tu' self.database.translations.insert_many([ { 'string': 'Voici vos stratégies', 'fr@tu': 'Voici tes stratégi%eFeminines', }, { 'string': 'Overall text for women if main challenge set', 'fr@tu': 'Overall text for women if main challenge set', }, ]) self.database.diagnostic_main_challenges.insert_one({ 'categoryId': 'women', 'strategiesIntroduction': 'Voici vos strats', 'filters': ['for-women'], 'order': 1, }) self.database.diagnostic_overall.insert_many([ { 'categoryId': 'other-category', 'filters': ['for-women'], 'sentenceTemplate': 'Overall text for women if no main challenge', }, { 'categoryId': 'women', 'filters': ['for-women'], 'strategiesIntroduction': 'Voici vos stratégies', 'sentenceTemplate': 'Overall text for women if main challenge set', }, ]) self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual( 'Overall text for women if main challenge set', project.diagnostic.overall_sentence) self.assertEqual('Voici tes stratégies', project.diagnostic.strategies_introduction)
def _save_project(project: project_pb2.Project, previous_project: project_pb2.Project, user_data: user_pb2.User) -> project_pb2.Project: # TODO(cyrille): Check for completeness here, rather than in client. if project.is_incomplete: return project _tick('Process project start') rome_id = project.target_job.job_group.rome_id departement_id = project.city.departement_id if not project.project_id: # Add ID, timestamp and stats to new projects project.project_id = _create_new_project_id(user_data) project.created_at.FromDatetime(now.get()) project.created_at.nanos = 0 if not project.WhichOneof( 'job_search_length') and project.job_search_length_months: if project.job_search_length_months < 0: project.job_search_has_not_started = True else: job_search_length_days = 30.5 * project.job_search_length_months job_search_length_duration = datetime.timedelta( days=job_search_length_days) project.job_search_started_at.FromDatetime( project.created_at.ToDatetime() - job_search_length_duration) project.job_search_started_at.nanos = 0 database = flask.current_app.config['DATABASE'] _tick('Populate local stats') if previous_project.city.departement_id != departement_id or \ previous_project.target_job.job_group.rome_id != rome_id: project.ClearField('local_stats') if not project.HasField('local_stats'): project.local_stats.CopyFrom( jobs.get_local_stats(database, departement_id, rome_id)) _tick('Diagnostic') diagnostic.maybe_diagnose(user_data, project, database) _tick('Advisor') advisor.maybe_advise(user_data, project, database, parse.urljoin(flask.request.base_url, '/')[:-1]) _tick('Strategies') strategist.maybe_strategize(user_data, project, database) _tick('New feedback') if project.feedback.text and not previous_project.feedback.text: stars = ':star:' * project.feedback.score user_url = parse.urljoin(flask.request.base_url, f'/eval?userId={user_data.user_id}') feedback = '\n> '.join(project.feedback.text.split('\n')) slack_text = f'[{stars}] <{user_url}|{user_data.user_id}>\n> {feedback}' give_feedback(feedback_pb2.Feedback( user_id=str(user_data.user_id), project_id=str(project.project_id), feedback=project.feedback.text, source=feedback_pb2.PROJECT_FEEDBACK, score=project.feedback.score), slack_text=slack_text) _tick('Process project end') return project
def test_no_diagnostic_sentence(self) -> None: """Don't generate a general sentence if database is not populated.""" project = self.user.projects.add() self.assertTrue(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertFalse(project.diagnostic.overall_sentence)
def test_no_diagnostic_if_already_diagnosed(self) -> None: """The diagnostic does not get computed again.""" project = project_pb2.Project(is_incomplete=True, diagnostic=diagnostic_pb2.Diagnostic()) self.assertFalse(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertEqual('', str(project.diagnostic))
def test_no_diagnostic_if_project_incomplete(self) -> None: """The diagnostic does not get populated when the project is marked as incomplete.""" project = project_pb2.Project(is_incomplete=True) self.assertFalse(diagnostic.maybe_diagnose(self.user, project, self.database)) self.assertFalse(project.HasField('diagnostic'))