{"action":"created","comment":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/52378161","id":52378161,"diff_hunk":"@@ -34,337 +42,20 @@ def test_handle_callback(self):\n         assert_equal(res.get('display_name'), 'Fake User Name')\n         assert_equal(res.get('provider_id'), 'Fake User ID')\n \n-    def test_citation_lists(self):\n-        mock_client = mock.Mock()\n-        mock_folders = [\n-            {\n-                'data': {\n-                    'name': 'Fake Folder',\n-                    'key': 'Fake Key',\n-                }\n-            }\n-        ]\n \n-        mock_client.collections.return_value = mock_folders\n-        self.provider._client = mock_client\n-        mock_account = mock.Mock()\n-        self.provider.account = mock_account\n+class ZoteroNodeSettingsTestCase(models.OAuthCitationsNodeSettingsTestSuiteMixin, OsfTestCase):\n+    short_name = 'zotero'\n+    full_name = 'Zotero'\n+    ProviderClass = ZoteroCitationsProvider\n+    OAuthProviderClass = model.Zotero\n+    ExternalAccountFactory = ZoteroAccountFactory\n \n-        res = self.provider.citation_lists(ZoteroCitationsProvider()._extract_folder)\n-        assert_equal(\n-            res[1]['name'],\n-            'Fake Folder'\n-        )\n-        assert_equal(\n-            res[1]['id'],\n-            'Fake Key'\n-        )\n+    NodeSettingsFactory = ZoteroNodeSettingsFactory\n+    NodeSettingsClass = model.ZoteroNodeSettings\n+    UserSettingsFactory = ZoteroUserSettingsFactory\n \n-class ZoteroNodeSettingsTestCase(OsfTestCase):\n \n-    def setUp(self):\n-        super(ZoteroNodeSettingsTestCase, self).setUp()\n-        self.node = ProjectFactory()\n-        self.node_settings = model.ZoteroNodeSettings(owner=self.node)\n-        self.node_settings.save()\n-        self.user = self.node.creator\n-        self.user_settings = self.user.get_or_add_addon('zotero')\n-\n-    def tearDown(self):\n-        super(ZoteroNodeSettingsTestCase, self).tearDown()\n-        self.user_settings.remove()\n-        self.node_settings.remove()\n-        self.node.remove()\n-        self.user.remove()\n-\n-    @mock.patch('website.addons.zotero.model.Zotero')\n-    def test_api_not_cached(self, mock_zotero):\n-        # The first call to .api returns a new object\n-        api = self.node_settings.api\n-        mock_zotero.assert_called_once()\n-        assert_equal(api, mock_zotero())\n-\n-    @mock.patch('website.addons.zotero.model.Zotero')\n-    def test_api_cached(self, mock_zotero):\n-        # Repeated calls to .api returns the same object\n-        self.node_settings._api = 'testapi'\n-        api = self.node_settings.api\n-        assert_false(mock_zotero.called)\n-        assert_equal(api, 'testapi')\n-\n-    def test_set_auth(self):\n-        external_account = ZoteroAccountFactory()\n-        self.user.external_accounts.append(external_account)\n-        self.user.save()\n-\n-        # this should be reset after the call\n-        self.node_settings.zotero_list_id = 'anything'\n-\n-        self.node_settings.set_auth(\n-            external_account=external_account,\n-            user=self.user\n-        )\n-\n-        # this instance is updated\n-        assert_equal(\n-            self.node_settings.external_account,\n-            external_account\n-        )\n-        assert_equal(\n-            self.node_settings.user_settings,\n-            self.user_settings\n-        )\n-        assert_is_none(\n-            self.node_settings.zotero_list_id\n-        )\n-\n-        # user_settings was updated\n-        # TODO: The call to grant_oauth_access in set_auth should be mocked\n-        assert_true(\n-            self.user_settings.verify_oauth_access(\n-                node=self.node,\n-                external_account=external_account,\n-            )\n-        )\n-\n-    def test_set_auth_wrong_user(self):\n-        external_account = ZoteroAccountFactory()\n-        self.user.external_accounts.append(external_account)\n-        self.user.save()\n-\n-        with assert_raises(PermissionsError):\n-            self.node_settings.set_auth(\n-                external_account=external_account,\n-                user=UserFactory()\n-            )\n-\n-    def test_deauthorize(self):\n-        self.node_settings.external_account = ZoteroAccountFactory()\n-        self.node_settings.zotero_list_id = 'something'\n-        self.node_settings.user_settings = self.user_settings\n-        self.node_settings.save()\n-\n-        assert_true(self.node_settings.zotero_list_id)\n-        self.node_settings.deauthorize(auth=Auth(self.user))\n-        self.node_settings.save()\n-        assert_is(self.node_settings.user_settings, None)\n-        assert_is(self.node_settings.zotero_list_id, None)\n-\n-        last_log = self.node.logs[-1]\n-        assert_equal(last_log.action, 'zotero_node_deauthorized')\n-        params = last_log.params\n-        assert_in('node', params)\n-        assert_in('project', params)\n-\n-    def test_clear_auth(self):\n-        self.node_settings.external_account = ZoteroAccountFactory()\n-        self.node_settings.zotero_list_id = 'something'\n-        self.node_settings.user_settings = self.user_settings\n-        self.node_settings.save()\n-\n-        self.node_settings.clear_auth()\n-\n-        assert_is_none(self.node_settings.external_account)\n-        assert_is_none(self.node_settings.zotero_list_id)","path":"website/addons/zotero/tests/test_models.py","position":177,"original_position":177,"commit_id":"e567bdb0ed315f6e00be7d541e5d034fe926eeb6","original_commit_id":"e567bdb0ed315f6e00be7d541e5d034fe926eeb6","user":{"login":"mfraezz","id":5659262,"avatar_url":"https://avatars.githubusercontent.com/u/5659262?v=3","gravatar_id":"","url":"https://api.github.com/users/mfraezz","html_url":"https://github.com/mfraezz","followers_url":"https://api.github.com/users/mfraezz/followers","following_url":"https://api.github.com/users/mfraezz/following{/other_user}","gists_url":"https://api.github.com/users/mfraezz/gists{/gist_id}","starred_url":"https://api.github.com/users/mfraezz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfraezz/subscriptions","organizations_url":"https://api.github.com/users/mfraezz/orgs","repos_url":"https://api.github.com/users/mfraezz/repos","events_url":"https://api.github.com/users/mfraezz/events{/privacy}","received_events_url":"https://api.github.com/users/mfraezz/received_events","type":"User","site_admin":false},"body":"[`test_clear_settings`](https://github.com/CenterForOpenScience/osf.io/blob/develop/website/addons/base/testing/models.py#L226) secretly does the same thing, as [`AddonCitationsNodeSettings.folder_id`](https://github.com/CenterForOpenScience/osf.io/pull/4962/files#diff-fcda41ab988f395bf849bacc226f5b76R45) just returns `list_id`.","created_at":"2016-02-09T21:39:27Z","updated_at":"2016-02-09T21:39:27Z","html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4962#discussion_r52378161","pull_request_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962","_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/52378161"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4962#discussion_r52378161"},"pull_request":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962"}}},"pull_request":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962","id":57702556,"html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4962","diff_url":"https://github.com/CenterForOpenScience/osf.io/pull/4962.diff","patch_url":"https://github.com/CenterForOpenScience/osf.io/pull/4962.patch","issue_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4962","number":4962,"state":"open","locked":false,"title":"[RFR][Feature] Better generics for citation addons","user":{"login":"mfraezz","id":5659262,"avatar_url":"https://avatars.githubusercontent.com/u/5659262?v=3","gravatar_id":"","url":"https://api.github.com/users/mfraezz","html_url":"https://github.com/mfraezz","followers_url":"https://api.github.com/users/mfraezz/followers","following_url":"https://api.github.com/users/mfraezz/following{/other_user}","gists_url":"https://api.github.com/users/mfraezz/gists{/gist_id}","starred_url":"https://api.github.com/users/mfraezz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfraezz/subscriptions","organizations_url":"https://api.github.com/users/mfraezz/orgs","repos_url":"https://api.github.com/users/mfraezz/repos","events_url":"https://api.github.com/users/mfraezz/events{/privacy}","received_events_url":"https://api.github.com/users/mfraezz/received_events","type":"User","site_admin":false},"body":"[#OSF-5369]\r\n\r\nPurpose\r\n======\r\nGeneralize code for citation addons (Mendeley and Zotero) so that duplication is minimized.\r\n\r\nChanges\r\n=======\r\n\r\n- [X] Views generalized\r\n- [X] Serializers generalized\r\n- [X] Providers generalized\r\n- [X] Models generalized\r\n- [x] Tests generalized\r\n- [x] Migration script for node settings model written:\r\n   * `<addon>_list_id  --> list_id`\r\n\r\nSide Effects\r\n=========\r\nNone","created_at":"2016-01-29T21:05:03Z","updated_at":"2016-02-09T21:39:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bc9e19b3b491e78d43a04f9640c67f9c7bfdd7c6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962/commits","review_comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962/comments","review_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4962/comments","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/e567bdb0ed315f6e00be7d541e5d034fe926eeb6","head":{"label":"mfraezz:feature/citation-generics","ref":"feature/citation-generics","sha":"e567bdb0ed315f6e00be7d541e5d034fe926eeb6","user":{"login":"mfraezz","id":5659262,"avatar_url":"https://avatars.githubusercontent.com/u/5659262?v=3","gravatar_id":"","url":"https://api.github.com/users/mfraezz","html_url":"https://github.com/mfraezz","followers_url":"https://api.github.com/users/mfraezz/followers","following_url":"https://api.github.com/users/mfraezz/following{/other_user}","gists_url":"https://api.github.com/users/mfraezz/gists{/gist_id}","starred_url":"https://api.github.com/users/mfraezz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfraezz/subscriptions","organizations_url":"https://api.github.com/users/mfraezz/orgs","repos_url":"https://api.github.com/users/mfraezz/repos","events_url":"https://api.github.com/users/mfraezz/events{/privacy}","received_events_url":"https://api.github.com/users/mfraezz/received_events","type":"User","site_admin":false},"repo":{"id":26929858,"name":"osf.io","full_name":"mfraezz/osf.io","owner":{"login":"mfraezz","id":5659262,"avatar_url":"https://avatars.githubusercontent.com/u/5659262?v=3","gravatar_id":"","url":"https://api.github.com/users/mfraezz","html_url":"https://github.com/mfraezz","followers_url":"https://api.github.com/users/mfraezz/followers","following_url":"https://api.github.com/users/mfraezz/following{/other_user}","gists_url":"https://api.github.com/users/mfraezz/gists{/gist_id}","starred_url":"https://api.github.com/users/mfraezz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfraezz/subscriptions","organizations_url":"https://api.github.com/users/mfraezz/orgs","repos_url":"https://api.github.com/users/mfraezz/repos","events_url":"https://api.github.com/users/mfraezz/events{/privacy}","received_events_url":"https://api.github.com/users/mfraezz/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mfraezz/osf.io","description":"Facilitating Open Science","fork":true,"url":"https://api.github.com/repos/mfraezz/osf.io","forks_url":"https://api.github.com/repos/mfraezz/osf.io/forks","keys_url":"https://api.github.com/repos/mfraezz/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mfraezz/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mfraezz/osf.io/teams","hooks_url":"https://api.github.com/repos/mfraezz/osf.io/hooks","issue_events_url":"https://api.github.com/repos/mfraezz/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/mfraezz/osf.io/events","assignees_url":"https://api.github.com/repos/mfraezz/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/mfraezz/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/mfraezz/osf.io/tags","blobs_url":"https://api.github.com/repos/mfraezz/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mfraezz/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mfraezz/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/mfraezz/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mfraezz/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/mfraezz/osf.io/languages","stargazers_url":"https://api.github.com/repos/mfraezz/osf.io/stargazers","contributors_url":"https://api.github.com/repos/mfraezz/osf.io/contributors","subscribers_url":"https://api.github.com/repos/mfraezz/osf.io/subscribers","subscription_url":"https://api.github.com/repos/mfraezz/osf.io/subscription","commits_url":"https://api.github.com/repos/mfraezz/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/mfraezz/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/mfraezz/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/mfraezz/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/mfraezz/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/mfraezz/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mfraezz/osf.io/merges","archive_url":"https://api.github.com/repos/mfraezz/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mfraezz/osf.io/downloads","issues_url":"https://api.github.com/repos/mfraezz/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/mfraezz/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/mfraezz/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/mfraezz/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mfraezz/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/mfraezz/osf.io/releases{/id}","deployments_url":"https://api.github.com/repos/mfraezz/osf.io/deployments","created_at":"2014-11-20T20:12:10Z","updated_at":"2015-01-28T20:39:13Z","pushed_at":"2016-02-08T20:35:34Z","git_url":"git://github.com/mfraezz/osf.io.git","ssh_url":"git@github.com:mfraezz/osf.io.git","clone_url":"https://github.com/mfraezz/osf.io.git","svn_url":"https://github.com/mfraezz/osf.io","homepage":"http://osf.io","size":119633,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"CenterForOpenScience:develop","ref":"develop","sha":"8aad1128109776dcb88a6bb427800c8b6e69262e","user":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"repo":{"id":10199599,"name":"osf.io","full_name":"CenterForOpenScience/osf.io","owner":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CenterForOpenScience/osf.io","description":"Facilitating Open Science","fork":false,"url":"https://api.github.com/repos/CenterForOpenScience/osf.io","forks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/forks","keys_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/teams","hooks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/hooks","issue_events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/events","assignees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/tags","blobs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/languages","stargazers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/stargazers","contributors_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contributors","subscribers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscribers","subscription_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscription","commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/merges","archive_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/downloads","issues_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/releases{/id}","deployments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/deployments","created_at":"2013-05-21T15:53:37Z","updated_at":"2016-02-09T05:00:49Z","pushed_at":"2016-02-09T20:54:37Z","git_url":"git://github.com/CenterForOpenScience/osf.io.git","ssh_url":"git@github.com:CenterForOpenScience/osf.io.git","clone_url":"https://github.com/CenterForOpenScience/osf.io.git","svn_url":"https://github.com/CenterForOpenScience/osf.io","homepage":"http://osf.io","size":265581,"stargazers_count":188,"watchers_count":188,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":145,"mirror_url":null,"open_issues_count":324,"forks":145,"open_issues":324,"watchers":188,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4962"},"issue":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4962"},"comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4962/comments"},"review_comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962/comments"},"review_comment":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4962/commits"},"statuses":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/e567bdb0ed315f6e00be7d541e5d034fe926eeb6"}}}}