Пример #1
0
    def test_categorize_advice_missing(self):
        """Test that the advisor does not choke on an ancient advice that does not exist anymore."""

        project = project_pb2.Project(
            project_id='1234',
            target_job=job_pb2.Job(
                name='Steward/ Hôtesse',
                feminine_name='Hôtesse',
                masculine_name='Steward',
            ),
            advices=[
                project_pb2.Advice(advice_id='spontaneous-application',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=2),
                project_pb2.Advice(advice_id='advice-does-no-exist-anymore',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=2),
            ])
        self.database.advice_modules.insert_many([
            {
                'adviceId': 'spontaneous-application',
                'categories': ['first', 'second'],
                'triggerScoringModel': 'constant(2)',
                'isReadyForProd': True,
            },
        ])

        advisor.maybe_categorize_advice(self.user, project, self.database)
        # Point check that some categorization happened.
        self.assertEqual(['spontaneous-application'],
                         project.advice_categories[0].advice_ids)
Пример #2
0
    def test_categorize_all_pieces_of_advice(self):
        """Test that the advisor categorize all advice modules."""

        project = project_pb2.Project(
            project_id='1234',
            target_job=job_pb2.Job(
                name='Steward/ Hôtesse',
                feminine_name='Hôtesse',
                masculine_name='Steward',
            ),
            advices=[
                project_pb2.Advice(advice_id='spontaneous-application',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=3),
                project_pb2.Advice(advice_id='other-work-env',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=2),
                project_pb2.Advice(advice_id='one-star',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=1),
            ])
        self.database.advice_modules.insert_many([
            {
                'adviceId': 'spontaneous-application',
                'categories': ['first', 'second'],
                'triggerScoringModel': 'constant(2)',
                'isReadyForProd': True,
            },
            {
                'adviceId': 'other-work-env',
                'categories': ['second'],
                'triggerScoringModel': 'constant(0)',
                'isReadyForProd': True,
            },
            {
                'adviceId': 'one-star',
                'categories': ['second'],
                'triggerScoringModel': 'constant(0)',
                'isReadyForProd': True,
            },
        ])

        advisor.maybe_categorize_advice(self.user, project, self.database)
        # First category is the category with all the 3-stars advice.
        self.assertEqual(['spontaneous-application'],
                         project.advice_categories[0].advice_ids)
        self.assertEqual('three-stars',
                         project.advice_categories[0].category_id)
        self.assertEqual(
            ['other-work-env', 'spontaneous-application', 'one-star'],
            project.advice_categories[1].advice_ids)
        self.assertEqual('second', project.advice_categories[1].category_id)
Пример #3
0
    def test_no_categories_if_already_categorized(self):
        """The advice_categories field does not get computed again."""

        project = project_pb2.Project(
            advice_categories=[
                project_pb2.AdviceCategory(category_id='very-old-category')
            ],
            advices=[
                project_pb2.Advice(advice_id='spontaneous-application',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=3)
            ])
        self.database.advice_modules.insert_one({
            'adviceId':
            'spontaneous-application',
            'categories': ['first', 'second'],
            'triggerScoringModel':
            'constant(2)',
            'isReadyForProd':
            True,
        })

        self.assertFalse(
            advisor.maybe_categorize_advice(self.user, project, self.database))
        self.assertEqual(['very-old-category'],
                         [c.category_id for c in project.advice_categories])
Пример #4
0
    def test_no_categories_if_project_incomplete(self):
        """The advice_categorues field does not get populated when the project is marked
            as incomplete."""

        project = project_pb2.Project(is_incomplete=True)
        self.assertFalse(
            advisor.maybe_categorize_advice(self.user, project, self.database))
Пример #5
0
    def test_avoid_double_first_advice(self):
        """The advisor avoids having the same first advice for two neighbor categories."""

        project = project_pb2.Project(
            project_id='1234',
            target_job=job_pb2.Job(
                name='Steward/ Hôtesse',
                feminine_name='Hôtesse',
                masculine_name='Steward',
            ),
            advices=[
                project_pb2.Advice(advice_id='spontaneous-application',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=2),
                project_pb2.Advice(advice_id='other-work-env',
                                   status=project_pb2.ADVICE_RECOMMENDED,
                                   num_stars=1)
            ])
        self.database.advice_modules.insert_many([
            {
                'adviceId': 'spontaneous-application',
                'categories': ['first', 'second', 'third'],
                'triggerScoringModel': 'constant(2)',
                'isReadyForProd': True,
            },
            {
                'adviceId': 'other-work-env',
                'categories': ['first', 'second', 'third'],
                'triggerScoringModel': 'constant(0)',
                'isReadyForProd': True,
            },
        ])

        advisor.maybe_categorize_advice(self.user, project, self.database)
        # First category is the category with all the 3-stars advice.
        self.assertEqual(3,
                         len(project.advice_categories),
                         msg=project.advice_categories)
        self.assertEqual(['spontaneous-application', 'other-work-env'],
                         project.advice_categories[0].advice_ids)
        self.assertEqual(['other-work-env', 'spontaneous-application'],
                         project.advice_categories[1].advice_ids)
        self.assertEqual(['spontaneous-application', 'other-work-env'],
                         project.advice_categories[2].advice_ids)
Пример #6
0
def _save_user(user_data, is_new_user):
    _tick('Save user start')

    if is_new_user:
        previous_user_data = user_data
    else:
        _tick('Load old user data')
        previous_user_data = _get_user_data(user_data.user_id)
        if user_data.revision and previous_user_data.revision > user_data.revision:
            # Do not overwrite newer data that was saved already: just return it.
            return previous_user_data

    if not previous_user_data.registered_at.seconds:
        user_data.registered_at.FromDatetime(now.get())
        # No need to pollute our DB with super precise timestamps.
        user_data.registered_at.nanos = 0
        # Enable Advisor for new users.
        if not ADVISOR_DISABLED_FOR_TESTING:
            user_data.features_enabled.advisor = user_pb2.ACTIVE
            user_data.features_enabled.advisor_email = user_pb2.ACTIVE
            user_data.profile.email_days.extend(
                [user_pb2.MONDAY, user_pb2.WEDNESDAY, user_pb2.FRIDAY])
    elif not _is_test_user(previous_user_data):
        user_data.registered_at.CopyFrom(previous_user_data.registered_at)
        user_data.features_enabled.advisor = previous_user_data.features_enabled.advisor

    _tick('Unverified data zone check start')
    # TODO(guillaume): Check out how we could not recompute that every time gracefully.
    if _is_in_unverified_data_zone(user_data.profile, user_data.projects):
        user_data.app_not_available = True
    _tick('Unverified data zone check end')

    _populate_feature_flags(user_data)

    for project in user_data.projects:
        if project.is_incomplete:
            continue
        _tick('Process project start')
        rome_id = project.target_job.job_group.rome_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())

        previous_project = next((p for p in previous_user_data.projects
                                 if p.project_id == project.project_id),
                                project_pb2.Project())
        if project.job_search_length_months != previous_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

        _tick('Populate local stats')
        if not project.HasField('local_stats'):
            _populate_job_stats_dict({rome_id: project.local_stats},
                                     project.mobility.city)

        _tick('Diagnostic')
        advisor.maybe_diagnose(user_data, project, _DB)

        _tick('Advisor')
        advisor.maybe_advise(user_data, project, _DB,
                             parse.urljoin(flask.request.base_url, '/')[:-1])

        _tick('Categorizer')
        advisor.maybe_categorize_advice(user_data, project, _DB)

        _tick('New feedback')
        if not is_new_user and (project.feedback.text
                                or project.feedback.score):
            if project.feedback.text and not previous_project.feedback.text:
                _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))

        _tick('Process project end')

    if not is_new_user:
        _assert_no_credentials_change(previous_user_data, user_data)
        _copy_unmodifiable_fields(previous_user_data, user_data)
        _populate_feature_flags(user_data)

    user_data.revision += 1

    _tick('Save user')
    _save_low_level(user_data, is_new_user=is_new_user)
    _tick('Return user proto')

    return user_data
Пример #7
0
    def test_no_categories_if_no_advice(self):
        """The advice_categories field does not get populated when advice aren't."""

        project = project_pb2.Project()
        self.assertFalse(
            advisor.maybe_categorize_advice(self.user, project, self.database))