{"action":"created","comment":{"url":"https://api.github.com/repos/PressLabs/silver/pulls/comments/90634742","pull_request_review_id":11151108,"id":90634742,"diff_hunk":"@@ -1,27 +1,308 @@\n+import sys\n+from copy import deepcopy\n+\n+from rest_framework import permissions, status\n from rest_framework.reverse import reverse\n+from six import iteritems\n \n from silver.api.serializers import PaymentMethodSerializer\n from silver.models import PaymentMethod\n-from silver.tests.factories import CustomerFactory, PaymentMethodFactory\n+from silver.api.views import PaymentMethodList, PaymentMethodDetail\n from silver.tests.spec.util.api_get_assert import APIGetAssert\n+from silver.tests.factories import CustomerFactory, PaymentMethodFactory\n+from silver.tests.utils import register_processor\n \n \n class TestPaymentMethodEndpoints(APIGetAssert):\n     serializer_class = PaymentMethodSerializer\n \n-    def test_filter_processor(self):\n-        customer = CustomerFactory.create()\n-        payment_method = PaymentMethodFactory.create(\n-            customer=customer\n-        )\n+    def setUp(self):\n+        self.customer = CustomerFactory.create()\n+\n+        super(TestPaymentMethodEndpoints, self).setUp()\n+\n+    def create_payment_method(self, *args, **kwargs):\n+        payment_method = PaymentMethodFactory.create(*args, **kwargs)\n+        payment_method.added_at.replace(microsecond=0)\n+\n+        return payment_method\n+\n+    def test_get_listing(self):\n+        PaymentMethodFactory.create(customer=CustomerFactory.create())\n+        payment_method = self.create_payment_method(customer=self.customer)\n+\n+        url = reverse('payment-method-list', kwargs={\n+            'customer_pk': self.customer.pk\n+        })\n+\n+        self.assert_get_data(url, [payment_method])\n+\n+    def test_get_detail(self):\n+        PaymentMethodFactory.create(customer=CustomerFactory.create())\n+        payment_method = self.create_payment_method(customer=self.customer)\n+\n+        url = reverse('payment-method-detail', kwargs={\n+            'customer_pk': self.customer.pk,\n+            'payment_method_id': payment_method.pk\n+        })\n+\n+        self.assert_get_data(url, payment_method)\n+\n+    def test_post_listing(self):\n+        processor_url = reverse('payment-processor-detail', kwargs={\n+            'processor_name': 'manual'\n+        })\n+\n+        url = reverse('payment-method-list', kwargs={\n+            'customer_pk': self.customer.pk\n+        })\n+\n+        response = self.client.post(url, data={\n+            'payment_processor': processor_url,\n+            'state': PaymentMethod.States.Uninitialized\n+        }, format='json')\n+\n+        payment_method = PaymentMethod.objects.get(customer=self.customer)\n+        self.assert_get_data(response.data['url'], payment_method)\n+\n+    def test_post_listing_additional_data_wrong_state(self):\n+        processor_url = reverse('payment-processor-detail', kwargs={\n+            'processor_name': 'manual'\n+        })\n+\n+        url = reverse('payment-method-list', kwargs={\n+            'customer_pk': self.customer.pk\n+        })\n+\n+        response = self.client.post(url, data={\n+            'payment_processor': processor_url,\n+            'state': PaymentMethod.States.Uninitialized,\n+            'additional_data': '{\"random\": \"value\"}'\n+        }, format='json')\n+\n+        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)\n+\n+    def test_post_listing_invalid_initial_state(self):\n+        invalid_initial_states = list(set(PaymentMethod.States.as_list()) - {\n+            PaymentMethod.States.Uninitialized,\n+            PaymentMethod.States.Unverified,\n+            PaymentMethod.States.Enabled})\n+\n+        processor_url = reverse('payment-processor-detail', kwargs={\n+            'processor_name': 'manual'\n+        })\n+\n+        url = reverse('payment-method-list', kwargs={\n+            'customer_pk': self.customer.pk\n+        })\n+\n+        for state in invalid_initial_states:\n+            response = self.client.post(url, data={\n+                'payment_processor': processor_url,\n+                'state': state\n+            }, format='json')\n+\n+            self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)\n+\n+    def test_put_detail_state_transitions(self):\n+        states = PaymentMethod.States.as_list()\n+        permutations = [(old, new) for old in states for new in states]\n+\n+        valid_transitions = set()\n+        for _, transition in iteritems(PaymentMethod.state_transitions):\n+            if isinstance(transition['source'], (tuple, list)):\n+                unmerged_transitions = set([(old, transition['target']) for\n+                                            old in transition['source']])\n+            else:\n+                unmerged_transitions = {(transition['source'],\n+                                         transition['target'])}\n+\n+            valid_transitions = valid_transitions.union(unmerged_transitions)\n+\n+        # add x -> x transitions as they are allowed\n+        valid_transitions = valid_transitions.union(\n+            set([(x, x) for x in states]))\n+\n+        valid_transition_list = list(valid_transitions)\n+\n+        for old, new in permutations:\n+            payment_method = self.create_payment_method(customer=self.customer,\n+                                                        state=old)\n+\n+            url = reverse('payment-method-detail', kwargs={\n+                'customer_pk': self.customer.pk,\n+                'payment_method_id': payment_method.pk\n+            })\n+            response = self.client.get(url, format='json')\n+\n+            data = response.data\n+            data['state'] = new\n+\n+            response = self.client.put(url, data=data, format='json')\n+\n+            message = '{} -> {}: code got {{}} expected {{}}'.format(old, new)\n+            if (old, new) in valid_transition_list:\n+                self.assertEqual(response.status_code,\n+                                 status.HTTP_200_OK,\n+                                 message.format(response.status_code,\n+                                                status.HTTP_200_OK))\n+                self.assertEqual(data, response.data,\n+                                 message.format(response.status_code,\n+                                                status.HTTP_200_OK))\n+            else:\n+                self.assertEqual(response.status_code,\n+                                 status.HTTP_409_CONFLICT,\n+                                 message.format(response.status_code,\n+                                                status.HTTP_409_CONFLICT))","path":"silver/tests/spec/test_payment_method.py","position":162,"original_position":162,"commit_id":"facf76211c4513571d7dcffd7a2fdc701bbf8584","original_commit_id":"facf76211c4513571d7dcffd7a2fdc701bbf8584","user":{"login":"bogdanpetrea","id":8372264,"avatar_url":"https://avatars.githubusercontent.com/u/8372264?v=3","gravatar_id":"","url":"https://api.github.com/users/bogdanpetrea","html_url":"https://github.com/bogdanpetrea","followers_url":"https://api.github.com/users/bogdanpetrea/followers","following_url":"https://api.github.com/users/bogdanpetrea/following{/other_user}","gists_url":"https://api.github.com/users/bogdanpetrea/gists{/gist_id}","starred_url":"https://api.github.com/users/bogdanpetrea/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bogdanpetrea/subscriptions","organizations_url":"https://api.github.com/users/bogdanpetrea/orgs","repos_url":"https://api.github.com/users/bogdanpetrea/repos","events_url":"https://api.github.com/users/bogdanpetrea/events{/privacy}","received_events_url":"https://api.github.com/users/bogdanpetrea/received_events","type":"User","site_admin":false},"body":"We might need a test for this test. 😁 ","created_at":"2016-12-02T12:35:49Z","updated_at":"2016-12-02T12:41:05Z","html_url":"https://github.com/PressLabs/silver/pull/388#discussion_r90634742","pull_request_url":"https://api.github.com/repos/PressLabs/silver/pulls/388","_links":{"self":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/comments/90634742"},"html":{"href":"https://github.com/PressLabs/silver/pull/388#discussion_r90634742"},"pull_request":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/388"}}},"pull_request":{"url":"https://api.github.com/repos/PressLabs/silver/pulls/388","id":95508457,"html_url":"https://github.com/PressLabs/silver/pull/388","diff_url":"https://github.com/PressLabs/silver/pull/388.diff","patch_url":"https://github.com/PressLabs/silver/pull/388.patch","issue_url":"https://api.github.com/repos/PressLabs/silver/issues/388","number":388,"state":"open","locked":false,"title":"payment method tests fixes #343 ","user":{"login":"krodyrobi","id":4136467,"avatar_url":"https://avatars.githubusercontent.com/u/4136467?v=3","gravatar_id":"","url":"https://api.github.com/users/krodyrobi","html_url":"https://github.com/krodyrobi","followers_url":"https://api.github.com/users/krodyrobi/followers","following_url":"https://api.github.com/users/krodyrobi/following{/other_user}","gists_url":"https://api.github.com/users/krodyrobi/gists{/gist_id}","starred_url":"https://api.github.com/users/krodyrobi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krodyrobi/subscriptions","organizations_url":"https://api.github.com/users/krodyrobi/orgs","repos_url":"https://api.github.com/users/krodyrobi/repos","events_url":"https://api.github.com/users/krodyrobi/events{/privacy}","received_events_url":"https://api.github.com/users/krodyrobi/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-11-28T14:29:58Z","updated_at":"2016-12-02T12:41:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"af376827f2274f59b8c6fadd485196b636e0ee1e","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/PressLabs/silver/pulls/388/commits","review_comments_url":"https://api.github.com/repos/PressLabs/silver/pulls/388/comments","review_comment_url":"https://api.github.com/repos/PressLabs/silver/pulls/comments{/number}","comments_url":"https://api.github.com/repos/PressLabs/silver/issues/388/comments","statuses_url":"https://api.github.com/repos/PressLabs/silver/statuses/facf76211c4513571d7dcffd7a2fdc701bbf8584","head":{"label":"PressLabs:343_payment_method_tests","ref":"343_payment_method_tests","sha":"facf76211c4513571d7dcffd7a2fdc701bbf8584","user":{"login":"PressLabs","id":1033395,"avatar_url":"https://avatars.githubusercontent.com/u/1033395?v=3","gravatar_id":"","url":"https://api.github.com/users/PressLabs","html_url":"https://github.com/PressLabs","followers_url":"https://api.github.com/users/PressLabs/followers","following_url":"https://api.github.com/users/PressLabs/following{/other_user}","gists_url":"https://api.github.com/users/PressLabs/gists{/gist_id}","starred_url":"https://api.github.com/users/PressLabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PressLabs/subscriptions","organizations_url":"https://api.github.com/users/PressLabs/orgs","repos_url":"https://api.github.com/users/PressLabs/repos","events_url":"https://api.github.com/users/PressLabs/events{/privacy}","received_events_url":"https://api.github.com/users/PressLabs/received_events","type":"Organization","site_admin":false},"repo":{"id":24887812,"name":"silver","full_name":"PressLabs/silver","owner":{"login":"PressLabs","id":1033395,"avatar_url":"https://avatars.githubusercontent.com/u/1033395?v=3","gravatar_id":"","url":"https://api.github.com/users/PressLabs","html_url":"https://github.com/PressLabs","followers_url":"https://api.github.com/users/PressLabs/followers","following_url":"https://api.github.com/users/PressLabs/following{/other_user}","gists_url":"https://api.github.com/users/PressLabs/gists{/gist_id}","starred_url":"https://api.github.com/users/PressLabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PressLabs/subscriptions","organizations_url":"https://api.github.com/users/PressLabs/orgs","repos_url":"https://api.github.com/users/PressLabs/repos","events_url":"https://api.github.com/users/PressLabs/events{/privacy}","received_events_url":"https://api.github.com/users/PressLabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/PressLabs/silver","description":"Django app + RESTful API for automatic billing","fork":false,"url":"https://api.github.com/repos/PressLabs/silver","forks_url":"https://api.github.com/repos/PressLabs/silver/forks","keys_url":"https://api.github.com/repos/PressLabs/silver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PressLabs/silver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PressLabs/silver/teams","hooks_url":"https://api.github.com/repos/PressLabs/silver/hooks","issue_events_url":"https://api.github.com/repos/PressLabs/silver/issues/events{/number}","events_url":"https://api.github.com/repos/PressLabs/silver/events","assignees_url":"https://api.github.com/repos/PressLabs/silver/assignees{/user}","branches_url":"https://api.github.com/repos/PressLabs/silver/branches{/branch}","tags_url":"https://api.github.com/repos/PressLabs/silver/tags","blobs_url":"https://api.github.com/repos/PressLabs/silver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PressLabs/silver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PressLabs/silver/git/refs{/sha}","trees_url":"https://api.github.com/repos/PressLabs/silver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PressLabs/silver/statuses/{sha}","languages_url":"https://api.github.com/repos/PressLabs/silver/languages","stargazers_url":"https://api.github.com/repos/PressLabs/silver/stargazers","contributors_url":"https://api.github.com/repos/PressLabs/silver/contributors","subscribers_url":"https://api.github.com/repos/PressLabs/silver/subscribers","subscription_url":"https://api.github.com/repos/PressLabs/silver/subscription","commits_url":"https://api.github.com/repos/PressLabs/silver/commits{/sha}","git_commits_url":"https://api.github.com/repos/PressLabs/silver/git/commits{/sha}","comments_url":"https://api.github.com/repos/PressLabs/silver/comments{/number}","issue_comment_url":"https://api.github.com/repos/PressLabs/silver/issues/comments{/number}","contents_url":"https://api.github.com/repos/PressLabs/silver/contents/{+path}","compare_url":"https://api.github.com/repos/PressLabs/silver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PressLabs/silver/merges","archive_url":"https://api.github.com/repos/PressLabs/silver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PressLabs/silver/downloads","issues_url":"https://api.github.com/repos/PressLabs/silver/issues{/number}","pulls_url":"https://api.github.com/repos/PressLabs/silver/pulls{/number}","milestones_url":"https://api.github.com/repos/PressLabs/silver/milestones{/number}","notifications_url":"https://api.github.com/repos/PressLabs/silver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PressLabs/silver/labels{/name}","releases_url":"https://api.github.com/repos/PressLabs/silver/releases{/id}","deployments_url":"https://api.github.com/repos/PressLabs/silver/deployments","created_at":"2014-10-07T11:39:38Z","updated_at":"2016-11-19T12:11:06Z","pushed_at":"2016-12-02T11:49:08Z","git_url":"git://github.com/PressLabs/silver.git","ssh_url":"git@github.com:PressLabs/silver.git","clone_url":"https://github.com/PressLabs/silver.git","svn_url":"https://github.com/PressLabs/silver","homepage":"https://www.presslabs.com/silver/","size":1762,"stargazers_count":79,"watchers_count":79,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":58,"forks":14,"open_issues":58,"watchers":79,"default_branch":"master"}},"base":{"label":"PressLabs:master","ref":"master","sha":"013a18e74b5720e6b39f3ea1f073b712921ce7dd","user":{"login":"PressLabs","id":1033395,"avatar_url":"https://avatars.githubusercontent.com/u/1033395?v=3","gravatar_id":"","url":"https://api.github.com/users/PressLabs","html_url":"https://github.com/PressLabs","followers_url":"https://api.github.com/users/PressLabs/followers","following_url":"https://api.github.com/users/PressLabs/following{/other_user}","gists_url":"https://api.github.com/users/PressLabs/gists{/gist_id}","starred_url":"https://api.github.com/users/PressLabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PressLabs/subscriptions","organizations_url":"https://api.github.com/users/PressLabs/orgs","repos_url":"https://api.github.com/users/PressLabs/repos","events_url":"https://api.github.com/users/PressLabs/events{/privacy}","received_events_url":"https://api.github.com/users/PressLabs/received_events","type":"Organization","site_admin":false},"repo":{"id":24887812,"name":"silver","full_name":"PressLabs/silver","owner":{"login":"PressLabs","id":1033395,"avatar_url":"https://avatars.githubusercontent.com/u/1033395?v=3","gravatar_id":"","url":"https://api.github.com/users/PressLabs","html_url":"https://github.com/PressLabs","followers_url":"https://api.github.com/users/PressLabs/followers","following_url":"https://api.github.com/users/PressLabs/following{/other_user}","gists_url":"https://api.github.com/users/PressLabs/gists{/gist_id}","starred_url":"https://api.github.com/users/PressLabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PressLabs/subscriptions","organizations_url":"https://api.github.com/users/PressLabs/orgs","repos_url":"https://api.github.com/users/PressLabs/repos","events_url":"https://api.github.com/users/PressLabs/events{/privacy}","received_events_url":"https://api.github.com/users/PressLabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/PressLabs/silver","description":"Django app + RESTful API for automatic billing","fork":false,"url":"https://api.github.com/repos/PressLabs/silver","forks_url":"https://api.github.com/repos/PressLabs/silver/forks","keys_url":"https://api.github.com/repos/PressLabs/silver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PressLabs/silver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PressLabs/silver/teams","hooks_url":"https://api.github.com/repos/PressLabs/silver/hooks","issue_events_url":"https://api.github.com/repos/PressLabs/silver/issues/events{/number}","events_url":"https://api.github.com/repos/PressLabs/silver/events","assignees_url":"https://api.github.com/repos/PressLabs/silver/assignees{/user}","branches_url":"https://api.github.com/repos/PressLabs/silver/branches{/branch}","tags_url":"https://api.github.com/repos/PressLabs/silver/tags","blobs_url":"https://api.github.com/repos/PressLabs/silver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PressLabs/silver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PressLabs/silver/git/refs{/sha}","trees_url":"https://api.github.com/repos/PressLabs/silver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PressLabs/silver/statuses/{sha}","languages_url":"https://api.github.com/repos/PressLabs/silver/languages","stargazers_url":"https://api.github.com/repos/PressLabs/silver/stargazers","contributors_url":"https://api.github.com/repos/PressLabs/silver/contributors","subscribers_url":"https://api.github.com/repos/PressLabs/silver/subscribers","subscription_url":"https://api.github.com/repos/PressLabs/silver/subscription","commits_url":"https://api.github.com/repos/PressLabs/silver/commits{/sha}","git_commits_url":"https://api.github.com/repos/PressLabs/silver/git/commits{/sha}","comments_url":"https://api.github.com/repos/PressLabs/silver/comments{/number}","issue_comment_url":"https://api.github.com/repos/PressLabs/silver/issues/comments{/number}","contents_url":"https://api.github.com/repos/PressLabs/silver/contents/{+path}","compare_url":"https://api.github.com/repos/PressLabs/silver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PressLabs/silver/merges","archive_url":"https://api.github.com/repos/PressLabs/silver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PressLabs/silver/downloads","issues_url":"https://api.github.com/repos/PressLabs/silver/issues{/number}","pulls_url":"https://api.github.com/repos/PressLabs/silver/pulls{/number}","milestones_url":"https://api.github.com/repos/PressLabs/silver/milestones{/number}","notifications_url":"https://api.github.com/repos/PressLabs/silver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PressLabs/silver/labels{/name}","releases_url":"https://api.github.com/repos/PressLabs/silver/releases{/id}","deployments_url":"https://api.github.com/repos/PressLabs/silver/deployments","created_at":"2014-10-07T11:39:38Z","updated_at":"2016-11-19T12:11:06Z","pushed_at":"2016-12-02T11:49:08Z","git_url":"git://github.com/PressLabs/silver.git","ssh_url":"git@github.com:PressLabs/silver.git","clone_url":"https://github.com/PressLabs/silver.git","svn_url":"https://github.com/PressLabs/silver","homepage":"https://www.presslabs.com/silver/","size":1762,"stargazers_count":79,"watchers_count":79,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":58,"forks":14,"open_issues":58,"watchers":79,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/388"},"html":{"href":"https://github.com/PressLabs/silver/pull/388"},"issue":{"href":"https://api.github.com/repos/PressLabs/silver/issues/388"},"comments":{"href":"https://api.github.com/repos/PressLabs/silver/issues/388/comments"},"review_comments":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/388/comments"},"review_comment":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/PressLabs/silver/pulls/388/commits"},"statuses":{"href":"https://api.github.com/repos/PressLabs/silver/statuses/facf76211c4513571d7dcffd7a2fdc701bbf8584"}}}}
{"actor":{"display_login":"bogdanpetrea"}}