@mock.patch('website.mailchimp_utils.get_mailchimp_api')
    def test_merge(self, mock_get_mailchimp_api):
        other_user = factories.UserFactory()
        other_user.save()

        # define values for users' fields
        today = datetime.datetime.now()
        yesterday = today - datetime.timedelta(days=1)

        self.user.comments_viewed_timestamp['shared_gt'] = today
        other_user.comments_viewed_timestamp['shared_gt'] = yesterday
        self.user.comments_viewed_timestamp['shared_lt'] = yesterday
        other_user.comments_viewed_timestamp['shared_lt'] = today
        self.user.comments_viewed_timestamp['user'] = yesterday
        other_user.comments_viewed_timestamp['other'] = yesterday

        self.user.email_verifications = {'user': {'email': 'a'}}
        other_user.email_verifications = {'other': {'email': 'b'}}

        self.user.external_accounts = [factories.ExternalAccountFactory()]
        other_user.external_accounts = [factories.ExternalAccountFactory()]

        self.user.mailchimp_mailing_lists = {
            'user': True,
            'shared_gt': True,
            'shared_lt': False,
        }
        other_user.mailchimp_mailing_lists = {
            'other': True,
            'shared_gt': False,
            'shared_lt': True,
        }

        self.user.piwik_token = 'abc'
        other_user.piwik_token = 'def'

        self.user.security_messages = {
            'user': today,
            'shared': today,
        }
        other_user.security_messages = {
            'other': today,
            'shared': today,
        }

        self.user.system_tags = ['user', 'shared']
        other_user.system_tags = ['other', 'shared']

        self.user.watched = [factories.WatchConfigFactory()]
        other_user.watched = [factories.WatchConfigFactory()]

        self.user.save()
        other_user.save()

        # define expected behavior for ALL FIELDS of the User object
        default_to_master_user_fields = [
            '_id',
            'date_confirmed',
            'date_disabled',
            'date_last_login',
            'date_registered',
            'email_last_sent',
            'family_name',
            'fullname',
            'given_name',
            'is_claimed',
            'is_invited',
            'is_registered',
            'jobs',
            'locale',
            'merged_by',
            'middle_names',
            'password',
            'piwik_token',
            'recently_added',
            'schools',
            'social',
            'suffix',
            'timezone',
            'username',
            'mailing_lists',
            'verification_key',
            '_affiliated_institutions',
            'contributor_added_email_records'
        ]

        calculated_fields = {
            'comments_viewed_timestamp': {
                'user': yesterday,
                'other': yesterday,
                'shared_gt': today,
                'shared_lt': today,
            },
            'email_verifications': {
                'user': {'email': 'a'},
                'other': {'email': 'b'},
            },
            'emails': [
                self.user.username,
                other_user.username,
            ],
            'external_accounts': [
                self.user.external_accounts[0]._id,
                other_user.external_accounts[0]._id,
            ],
            'mailchimp_mailing_lists': {
                'user': True,
                'other': True,
                'shared_gt': True,
                'shared_lt': True,
            },
            'osf_mailing_lists': {
                'Open Science Framework Help': True
            },
            'security_messages': {
                'user': today,
                'other': today,
                'shared': today,
            },
            'system_tags': ['user', 'shared', 'other'],
            'unclaimed_records': {},
            'watched': [
                self.user.watched[0]._id,
                other_user.watched[0]._id,
            ],
        }

        # from the explicit rules above, compile expected field/value pairs
        expected = {}
        expected.update(calculated_fields)
        for key in default_to_master_user_fields:
            expected[key] = getattr(self.user, key)

        # ensure all fields of the user object have an explicit expectation
        assert_equal(
            set(expected.keys()),
            set(self.user._fields),
        )

        # mock mailchimp
        mock_client = mock.MagicMock()
        mock_get_mailchimp_api.return_value = mock_client
        mock_client.lists.list.return_value = {'data': [{'id': x, 'list_name': list_name} for x, list_name in enumerate(self.user.mailchimp_mailing_lists)]}

        # perform the merge
        self.user.merge_user(other_user)
        self.user.save()
        handlers.celery_teardown_request()

        # check each field/value pair
        for k, v in expected.iteritems():
            assert_equal(
                getattr(self.user, k),
                v,
                # "{} doesn't match expectation".format(k)
            )

        # check fields set on merged user
        assert_equal(other_user.merged_by, self.user)

        assert_equal(
            0,
            models.Session.find(
                Q('data.auth_user_id', 'eq', other_user._id)
            ).count()
        )
dataset/ETHPy150Open CenterForOpenScience/osf.io/tests/models/test_user.py/TestUserMerging.test_merge/original