text:
"""Unit tests for I Done This integration."""

import json
import logging
from io import StringIO
from urllib.error import HTTPError, URLError
from urllib.request import urlopen

from django.contrib.auth.models import User
from django.core.cache import cache
from django.test import RequestFactory
from djblets.cache.backend import cache_memoize, make_cache_key
from djblets.conditions import ConditionSet, Condition
from djblets.testing.decorators import add_fixtures
from reviewboard.reviews.conditions import ReviewRequestRepositoriesChoice
from reviewboard.reviews.models import ReviewRequestDraft
from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                               encrypt_password)

from rbintegrations.idonethis.forms import (
    IDoneThisIntegrationAccountPageForm,
    IDoneThisIntegrationConfigForm)
from rbintegrations.idonethis.integration import IDoneThisIntegration
from rbintegrations.idonethis.utils import get_user_team_ids
from rbintegrations.testing.testcases import IntegrationTestCase

class IDoneThisIntegrationTests(IntegrationTestCase):
    """Test posting of I Done This entries with review request activity."""

    integration_cls = IDoneThisIntegration

    fixtures = ['test_scmtools', 'test_users']

    def setUp(self):
        """Set up this test case."""
        super(IDoneThisIntegrationTests, self).setUp()

        self.user = User.objects.create_user(username='testuser')
        self.team_ids_cache_key = make_cache_key('idonethis-team_ids-testuser')
        self.profile = self.user.get_profile()
        self.profile.settings['idonethis'] = {
            'api_token': encrypt_password('tok123'),
        }

    def test_post_review_request_closed_completed(self):
        """Testing IDoneThisIntegration posts on review request closed as
        completed
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        request = urlopen.spy.calls[0].args[0]
        self.assertEqual(request.get_full_url(),
                         'https://beta.idonethis.com/api/v2/entries')
        self.assertEqual(request.get_method(), 'POST')
        self.assertEqual(request.get_header('Authorization'), 'Token tok123')

        self.assertEqual(
            json.loads(request.data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_closed_completed_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request closed as
        completed with local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_request_closed_discarded(self):
        """Testing IDoneThisIntegration posts on review request closed as
        discarded
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.DISCARDED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Discarded review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_closed_discarded_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request closed as
        discarded with local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.DISCARDED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Discarded review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_request_published_normal(self):
        """Testing IDoneThisIntegration posts on review request published"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=False)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Published review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_published_normal_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request published with
        local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=False)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Published review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_request_published_reopen(self):
        """Testing IDoneThisIntegration posts on review request published after
        discard and reopen
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review_request.close(review_request.DISCARDED)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.reopen(self.user)

        # Reopened discarded review is not public until publish,
        # so post_entry should not post.
        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 0)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 2)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Reopened review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_published_reopen_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request published after
        discard and reopen with local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        review_request.close(review_request.DISCARDED)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.reopen(self.user)

        # Reopened discarded review is not public until publish,
        # so post_entry should not post.
        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 0)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 2)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Reopened review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_request_published_update(self):
        """Testing IDoneThisIntegration posts on review request published after
        update
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        draft = ReviewRequestDraft.create(review_request)
        draft.summary = 'My new summary'
        draft.description = 'My new description'
        draft.save()

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Updated review request 1: My new summary '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_published_update_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request published after
        update with local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        draft = ReviewRequestDraft.create(review_request)
        draft.summary = 'My new summary'
        draft.description = 'My new description'
        draft.save()

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Updated review request 1: My new summary '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_request_reopened(self):
        """Testing IDoneThisIntegration posts on review request reopened after
        after submit
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review_request.close(review_request.SUBMITTED)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.reopen(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Reopened review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_request_reopened_with_local_site(self):
        """Testing IDoneThisIntegration posts on review request reopened after
        submit with local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)
        review_request.local_site.users.add(self.user)

        review_request.close(review_request.SUBMITTED)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.reopen(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Reopened review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/ #group',
            })

    def test_post_review_published_with_0_issues(self):
        """Testing IDoneThisIntegration posts on review published with no open
        issues
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_0_issues_local_site(self):
        """Testing IDoneThisIntegration posts on review published with no open
        issues and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_review_published_with_1_issue(self):
        """Testing IDoneThisIntegration posts on review published with 1 open
        issue
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review (1 issue) on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_1_issue_local_site(self):
        """Testing IDoneThisIntegration posts on review published with 1 open
        issue and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review (1 issue) on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_review_published_with_2_issues(self):
        """Testing IDoneThisIntegration posts on review published with > 1 open
        issues
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review, issue_opened=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review (2 issues) on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_2_issues_local_site(self):
        """Testing IDoneThisIntegration posts on review published with > 1 open
        issues and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review, issue_opened=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted review (2 issues) on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_review_published_with_shipit_0_issues(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and no open issues
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_shipit_0_issues_local_site(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and no open issues and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_review_published_with_shipit_1_issue(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and 1 open issue
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! (1 issue) on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_shipit_1_issue_local_site(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and 1 open issue and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! (1 issue) on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_review_published_with_shipit_2_issues(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and > 1 open issues
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review, issue_opened=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! (2 issues) on review request 1: '
                        'Test Review Request '
                        'http://example.com/r/1/#review1 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_review_published_with_shipit_2_issues_local_site(self):
        """Testing IDoneThisIntegration posts on review published with Ship it!
        and > 1 open issues and local site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    ship_it=True)
        self.create_general_comment(review, issue_opened=True)
        self.create_general_comment(review, issue_opened=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Posted Ship it! (2 issues) on review request 1: '
                        'Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review1 '
                        '#group',
            })

    def test_post_reply_published(self):
        """Testing IDoneThisIntegration posts on reply published"""
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    publish=True)
        comment = self.create_general_comment(review, issue_opened=True)

        reply = self.create_reply(review, user=self.user)
        self.create_general_comment(reply, reply_to=comment)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        reply.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Replied to review request 1: Test Review Request '
                        'http://example.com/r/1/#review2 #group',
            })

    @add_fixtures(['test_site'])
    def test_post_reply_published_with_local_site(self):
        """Testing IDoneThisIntegration posts on reply published with local
        site
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            with_local_site=True,
            local_id=1,
            publish=True)
        group = self.create_review_group(name='group', with_local_site=True)
        review_request.target_groups.add(group)

        review = self.create_review(review_request,
                                    user=self.user,
                                    publish=True)
        comment = self.create_general_comment(review, issue_opened=True)

        reply = self.create_reply(review, user=self.user)
        self.create_general_comment(reply, reply_to=comment)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', with_local_site=True)
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        reply.publish()

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Replied to review request 1: Test Review Request '
                        'http://example.com/s/local-site-1/r/1/#review2 '
                        '#group',
            })

    def test_no_post_review_published_to_owner_only(self):
        """Testing IDoneThisIntegration doesn't post on review published to
        owner only
        """
        review_request = self.create_review_request(
            create_repository=True,
            summary='Test Review Request',
            publish=True)

        review = self.create_review(review_request, user=self.user)
        self.create_general_comment(review)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review.publish(to_owner_only=True)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

    def test_no_post_without_user(self):
        """Testing IDoneThisIntegration doesn't post without a user"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(self.integration.get_configs)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(self.integration.get_configs.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_no_post_with_inactive_user(self):
        """Testing IDoneThisIntegration doesn't post with inactive user"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        self.user.is_active = False

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(self.integration.get_configs)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(self.integration.get_configs.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_no_post_without_api_token(self):
        """Testing IDoneThisIntegration doesn't post without an API Token"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        self.profile.settings['idonethis'] = {}

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(self.integration.get_configs)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(self.integration.get_configs.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_no_post_without_matching_condition(self):
        """Testing IDoneThisIntegration doesn't post without a matching
        condition
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123', repository_operator='none')
        self._create_config(team_id='teamABC', repository_operator='none')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_no_post_without_matching_team_id(self):
        """Testing IDoneThisIntegration doesn't post without a matching
        team ID
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123x')
        self._create_config(team_id='teamABCx')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_no_post_with_team_ids_error(self):
        """Testing IDoneThisIntegration doesn't post after error while
        requesting the user team IDs
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.assertNotIn(self.team_ids_cache_key, cache)

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_fake=_urlopen_raise_httperror)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)
        self.assertEqual(urlopen.spy.calls[0].args[0].get_full_url(),
                         'https://beta.idonethis.com/api/v2/teams')

    def test_try_post_with_httperror(self):
        """Testing IDoneThisIntegration tries to post to multiple teams with
        HTTPError
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self._create_config(team_id='teamABC')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_fake=_urlopen_raise_httperror)
        self.spy_on(logging.error)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 2)
        self.assertEqual(len(logging.error.spy.calls), 2)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_try_post_with_urlerror(self):
        """Testing IDoneThisIntegration tries to post to multiple teams with
        URLError
        """
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self._create_config(team_id='teamABC')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_fake=_urlopen_raise_urlerror)
        self.spy_on(logging.error)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 2)
        self.assertEqual(len(logging.error.spy.calls), 2)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

    def test_post_to_multiple_teams(self):
        """Testing IDoneThisIntegration posts to multiple matched teams"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self._create_config(team_id='teamABC')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 2)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

        self.assertEqual(
            json.loads(urlopen.spy.calls[1].args[0].data),
            {
                'team_id': 'teamABC',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    def test_post_once_to_duplicate_teams(self):
        """Testing IDoneThisIntegration posts once to duplicate teams"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='group')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self._create_config(team_id='teamABC')
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 2)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

        self.assertEqual(
            json.loads(urlopen.spy.calls[1].args[0].data),
            {
                'team_id': 'teamABC',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #group',
            })

    def test_post_with_multiple_target_groups(self):
        """Testing IDoneThisIntegration posts with multiple target groups"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)
        group = self.create_review_group(name='groupA')
        review_request.target_groups.add(group)
        group = self.create_review_group(name='new group-B')
        review_request.target_groups.add(group)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/ #groupA #new_group_B',
            })

    def test_post_without_target_groups(self):
        """Testing IDoneThisIntegration posts without target groups"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/',
            })

    def test_post_with_extra_whitespace_removed(self):
        """Testing IDoneThisIntegration posts with extra whitespace removed"""
        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='    Test    Review     Request    ',
            publish=True)

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})
        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.spy_on(self.integration.post_entry)
        self.spy_on(urlopen, call_original=False)

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)

        self.assertEqual(
            json.loads(urlopen.spy.calls[0].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/',
            })

    def test_post_multiple_events_with_single_team_ids_request(self):
        """Testing IDoneThisIntegration posts multiple events with a single
        request for the user team IDs
        """
        def _urlopen(request, **kwargs):
            if request.get_full_url().endswith('/teams'):
                return StringIO(json.dumps([
                    {
                        'hash_id': 'team123',
                    },
                ]))

            return StringIO('')

        review_request = self.create_review_request(
            create_repository=True,
            submitter=self.user,
            summary='Test Review Request',
            publish=False)

        self._create_config(team_id='team123')
        self.integration.enable_integration()

        self.assertNotIn(self.team_ids_cache_key, cache)

        self.spy_on(self.integration.post_entry)
        self.spy_on(get_user_team_ids)
        self.spy_on(urlopen, call_fake=_urlopen)

        review_request.publish(self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 1)
        self.assertEqual(len(get_user_team_ids.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 2)

        self.assertIsNone(self.integration.post_entry.spy.calls[0].exception)
        self.assertEqual(urlopen.spy.calls[0].args[0].get_full_url(),
                         'https://beta.idonethis.com/api/v2/teams')

        self.assertIn(self.team_ids_cache_key, cache)
        self.assertEqual(cache.get(self.team_ids_cache_key), {'team123'})

        self.assertEqual(urlopen.spy.calls[1].args[0].get_full_url(),
                         'https://beta.idonethis.com/api/v2/entries')

        self.assertEqual(
            json.loads(urlopen.spy.calls[1].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Published review request 1: Test Review Request '
                        'http://example.com/r/1/',
            })

        review_request.close(review_request.SUBMITTED, self.user)

        self.assertEqual(len(self.integration.post_entry.spy.calls), 2)
        self.assertEqual(len(get_user_team_ids.spy.calls), 2)
        self.assertEqual(len(urlopen.spy.calls), 3)

        self.assertEqual(urlopen.spy.calls[2].args[0].get_full_url(),
                         'https://beta.idonethis.com/api/v2/entries')
        self.assertEqual(
            json.loads(urlopen.spy.calls[2].args[0].data),
            {
                'team_id': 'team123',
                'status': 'done',
                'body': 'Completed review request 1: Test Review Request '
                        'http://example.com/r/1/',
            })

    def _create_config(self,
                       team_id,
                       with_local_site=False,
                       repository_operator='any'):
        """Create an integration config with the given parameters.

        Args:
            team_id (unicode):
                The team ID to post entries to.

            with_local_site (boolean, optional):
                Whether the configuration should be for a local site.

            repository_operator (unicode, optional):
                Operator for a repository choice to satisfy the condition.
        """
        choice = ReviewRequestRepositoriesChoice()

        condition_set = ConditionSet(conditions=[
            Condition(choice=choice,
                      operator=choice.get_operator(repository_operator)),
        ])

        if with_local_site:
            local_site = self.get_local_site(name=self.local_site_name)
        else:
            local_site = None

        config = self.integration.create_config(name='Config %s' % team_id,
                                                enabled=True,
                                                local_site=local_site)
        config.set('team_id', team_id)
        config.set('conditions', condition_set.serialize())
        config.save()

class IDoneThisIntegrationFormTests(IntegrationTestCase):
    """Test the admin configuration and user account page forms."""

    integration_cls = IDoneThisIntegration

    def setUp(self):
        """Initialize this test case."""
        super(IDoneThisIntegrationFormTests, self).setUp()

        self.request = RequestFactory().get('test')
        self.user = User.objects.create_user(username='testuser')
        self.team_ids_cache_key = make_cache_key('idonethis-team_ids-testuser')
        self.profile = self.user.get_profile()

    def test_admin_clean_team_id_whitespace(self):
        """Testing IDoneThisIntegration admin form, cleaning team ID strips
        whitespace
        """
        form = IDoneThisIntegrationConfigForm(
            integration=self.integration,
            request=self.request,
            data={
                'team_id': '  team123  ',
            })

        self.spy_on(form.clean_team_id)

        form.full_clean()

        self.assertEqual(len(form.clean_team_id.spy.calls), 1)
        self.assertEqual(form.cleaned_data['team_id'], 'team123')

    def test_admin_clean_team_id_validation(self):
        """Testing IDoneThisIntegration admin form, cleaning team ID containing
        slash raises validation error
        """
        form = IDoneThisIntegrationConfigForm(integration=self.integration,
                                              request=self.request)
        form.cleaned_data = {
            'team_id': 't/team123',
        }

        self.assertRaisesValidationError(
            'Team ID cannot contain slashes.',
            form.clean_team_id)

    def test_user_clean_token_empty(self):
        """Testing IDoneThisIntegration user form, cleaning empty API token
        skips validation
        """
        form = IDoneThisIntegrationAccountPageForm(
            page=None,
            request=self.request,
            user=self.user,
            data={
                'idonethis_api_token': '   ',
            })

        self.spy_on(urlopen)
        self.spy_on(form.clean_idonethis_api_token)

        form.full_clean()

        self.assertEqual(len(urlopen.spy.calls), 0)
        self.assertEqual(len(form.clean_idonethis_api_token.spy.calls), 1)

        self.assertEqual(form.cleaned_data['idonethis_api_token'], '')

    def test_user_clean_token_validation_request(self):
        """Testing IDoneThisIntegration user form, cleaning API token strips
        whitespace and performs validation API request
        """
        form = IDoneThisIntegrationAccountPageForm(
            page=None,
            request=self.request,
            user=self.user,
            data={
                'idonethis_api_token': '  tok123  ',
            })

        self.spy_on(urlopen, call_original=False)
        self.spy_on(logging.error)
        self.spy_on(form.clean_idonethis_api_token)

        form.full_clean()

        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 0)
        self.assertEqual(len(form.clean_idonethis_api_token.spy.calls), 1)

        request = urlopen.spy.calls[0].args[0]
        self.assertEqual(request.get_full_url(),
                         'https://beta.idonethis.com/api/v2/noop')
        self.assertEqual(request.get_method(), 'GET')
        self.assertEqual(request.get_header('Authorization'), 'Token tok123')
        self.assertIsNone(request.data)

        self.assertEqual(form.cleaned_data['idonethis_api_token'], 'tok123')

    def test_user_clean_token_validation_httperror(self):
        """Testing IDoneThisIntegration user form, cleaning API token with
        HTTPError raises validation error
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': 'tok123',
        }

        self.spy_on(urlopen, call_fake=_urlopen_raise_httperror)
        self.spy_on(logging.error)

        self.assertRaisesValidationError(
            'Error validating the API Token. Make sure the token matches your '
            'I Done This Account Settings.',
            form.clean_idonethis_api_token)

        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 1)

    def test_user_clean_token_validation_urlerror(self):
        """Testing IDoneThisIntegration user form, cleaning API token with
        URLError raises validation error
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': 'tok123',
        }

        self.spy_on(urlopen, call_fake=_urlopen_raise_urlerror)
        self.spy_on(logging.error)

        self.assertRaisesValidationError(
            'Error validating the API Token. Make sure the token matches your '
            'I Done This Account Settings.',
            form.clean_idonethis_api_token)

        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 1)

    def test_user_load_token_empty(self):
        """Testing IDoneThisIntegration user form, loading empty API token
        when not in settings
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)

        self.spy_on(decrypt_password)

        form.load()

        self.assertEqual(len(decrypt_password.spy.calls), 0)

        self.assertIsNone(form.fields['idonethis_api_token'].initial)

    def test_user_load_token_decrypted(self):
        """Testing IDoneThisIntegration user form, loading decrypted API token
        from settings
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        self.profile.settings['idonethis'] = {
            'api_token': encrypt_password('tok123'),
        }

        self.spy_on(decrypt_password)

        form.load()

        self.assertEqual(len(decrypt_password.spy.calls), 1)

        self.assertEqual(form.fields['idonethis_api_token'].initial, 'tok123')

    def test_user_save_token_empty(self):
        """Testing IDoneThisIntegration user form, saving empty API token
        creates empty settings
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': '',
        }

        self.spy_on(encrypt_password)
        self.spy_on(self.profile.save)

        form.save()

        self.assertEqual(len(encrypt_password.spy.calls), 0)
        self.assertEqual(len(self.profile.save.spy.calls), 1)

        self.assertEqual(self.profile.settings['idonethis'], {})

    def test_user_save_token_empty_removes_old_token(self):
        """Testing IDoneThisIntegration user form, saving empty API token
        removes old token from settings and deletes cached team IDs
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': '',
        }
        self.profile.settings['idonethis'] = {
            'api_token': encrypt_password('tok123'),
            'other_key': 'other value',
        }

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})

        self.spy_on(encrypt_password)
        self.spy_on(self.profile.save)

        form.save()

        self.assertEqual(len(encrypt_password.spy.calls), 0)
        self.assertEqual(len(self.profile.save.spy.calls), 1)

        self.assertEqual(
            self.profile.settings['idonethis'],
            {
                'other_key': 'other value',
            })
        self.assertNotIn(self.team_ids_cache_key, cache)

    def test_user_save_token_encrypted(self):
        """Testing IDoneThisIntegration user form, saving encrypted API token
        to settings
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': 'tok123',
        }

        self.spy_on(encrypt_password)
        self.spy_on(self.profile.save)

        form.save()

        self.assertEqual(len(encrypt_password.spy.calls), 1)
        self.assertEqual(len(self.profile.save.spy.calls), 1)

        self.assertEqual(
            decrypt_password(self.profile.settings['idonethis']['api_token']),
            'tok123')

    def test_user_save_token_encrypted_replaces_old_token(self):
        """Testing IDoneThisIntegration user form, saving encrypted API token
        replaces old token in settings and deletes cached team IDs
        """
        form = IDoneThisIntegrationAccountPageForm(page=None,
                                                   request=self.request,
                                                   user=self.user)
        form.cleaned_data = {
            'idonethis_api_token': 'tokABC',
        }
        self.profile.settings['idonethis'] = {
            'api_token': encrypt_password('tok123'),
            'other_key': 'other value',
        }

        cache.set(self.team_ids_cache_key, {'team123', 'teamABC'})

        self.spy_on(encrypt_password)
        self.spy_on(self.profile.save)

        form.save()

        self.assertEqual(len(encrypt_password.spy.calls), 1)
        self.assertEqual(len(self.profile.save.spy.calls), 1)

        self.assertEqual(
            decrypt_password(self.profile.settings['idonethis']['api_token']),
            'tokABC')
        self.assertEqual(self.profile.settings['idonethis']['other_key'],
                         'other value')
        self.assertNotIn(self.team_ids_cache_key, cache)

class IDoneThisIntegrationUtilTests(IntegrationTestCase):
    """Test utility methods which are not fully covered by other tests."""

    integration_cls = IDoneThisIntegration

    def setUp(self):
        """Initialize this test case."""
        super(IDoneThisIntegrationUtilTests, self).setUp()

        self.user = User.objects.create_user(username='testuser')
        self.team_ids_cache_key = make_cache_key('idonethis-team_ids-testuser')
        self.profile = self.user.get_profile()
        self.profile.settings['idonethis'] = {
            'api_token': encrypt_password('tok123'),
        }

    def test_get_user_team_ids_without_token(self):
        """Testing IDoneThisIntegration team IDs get None without an API
        token
        """
        self.profile.settings['idonethis'] = {}

        self.spy_on(cache_memoize)
        self.spy_on(urlopen)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 0)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertIsNone(team_ids)
        self.assertNotIn(self.team_ids_cache_key, cache)

    def test_get_user_team_ids_from_cache(self):
        """Testing IDoneThisIntegration team IDs get data from cache without
        API request
        """
        cached_team_ids = {'team123', 'teamABC'}
        cache.set(self.team_ids_cache_key, cached_team_ids)

        self.spy_on(cache_memoize)
        self.spy_on(urlopen)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 0)

        self.assertEqual(team_ids, cached_team_ids)

    def test_get_user_team_ids_request(self):
        """Testing IDoneThisIntegration team IDs get data from API request
        if not in cache
        """
        response = json.dumps([
            {
                'name': 'Example Team 1',
                'created_at': '2016-07-05T07:13:57.873Z',
                'updated_at': '2016-07-05T07:13:57.873Z',
                'hash_id': 'team123'
            }, {
                'name': 'Example Team 2',
                'created_at': '2016-07-05T07:13:57.875Z',
                'updated_at': '2016-07-05T07:13:57.875Z',
                'hash_id': 'teamABC'
            }, {
                'name': 'Duplicate Team 1',
                'created_at': '2016-07-05T07:13:57.877Z',
                'updated_at': '2016-07-05T07:13:57.877Z',
                'hash_id': 'team123'
            }])

        self.spy_on(cache_memoize)
        self.spy_on(urlopen,
                    call_fake=lambda request, **kwargs: StringIO(response))
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 0)

        request = urlopen.spy.calls[0].args[0]
        self.assertEqual(request.get_full_url(),
                         'https://beta.idonethis.com/api/v2/teams')
        self.assertEqual(request.get_method(), 'GET')
        self.assertEqual(request.get_header('Authorization'), 'Token tok123')
        self.assertIsNone(request.data)

        self.assertEqual(team_ids, {'team123', 'teamABC'})
        self.assertEqual(team_ids, cache.get(self.team_ids_cache_key))

    def test_get_user_team_ids_request_empty_team_list(self):
        """Testing IDoneThisIntegration team IDs get empty set if API request
        gets empty list
        """
        self.spy_on(cache_memoize)
        self.spy_on(urlopen,
                    call_fake=lambda request, **kwargs: StringIO('[]'))
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 0)

        self.assertEqual(team_ids, set())
        self.assertEqual(team_ids, cache.get(self.team_ids_cache_key))

    def test_get_user_team_ids_request_httperror(self):
        """Testing IDoneThisIntegration team IDs get None if API request gets
        HTTPError
        """
        self.spy_on(cache_memoize)
        self.spy_on(urlopen, call_fake=_urlopen_raise_httperror)
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 2)

        self.assertIsNone(team_ids)
        self.assertNotIn(self.team_ids_cache_key, cache)

    def test_get_user_team_ids_request_urlerror(self):
        """Testing IDoneThisIntegration team IDs get None if API request gets
        URLError
        """
        self.spy_on(cache_memoize)
        self.spy_on(urlopen, call_fake=_urlopen_raise_urlerror)
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 2)

        self.assertIsNone(team_ids)
        self.assertNotIn(self.team_ids_cache_key, cache)

    def test_get_user_team_ids_request_invalid_json(self):
        """Testing IDoneThisIntegration team IDs get None if API request gets
        invalid JSON
        """
        self.spy_on(cache_memoize)
        self.spy_on(urlopen,
                    call_fake=lambda request, **kwargs: StringIO('[invalid'))
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 1)

        self.assertIsNone(team_ids)
        self.assertNotIn(self.team_ids_cache_key, cache)

    def test_get_user_team_ids_request_invalid_team_data(self):
        """Testing IDoneThisIntegration team IDs get None if API request gets
        invalid team data
        """
        self.spy_on(cache_memoize)
        self.spy_on(urlopen,
                    call_fake=lambda request, **kw: StringIO('[{"a":"b"}]'))
        self.spy_on(logging.error)

        team_ids = get_user_team_ids(self.user)

        self.assertEqual(len(cache_memoize.spy.calls), 1)
        self.assertEqual(len(urlopen.spy.calls), 1)
        self.assertEqual(len(logging.error.spy.calls), 1)

        self.assertIsNone(team_ids)
        self.assertNotIn(self.team_ids_cache_key, cache)

def _urlopen_raise_httperror(request, **kwargs):
    """Fake urlopen that raises an HTTPError for testing.

    Args:
        request (urllib2.Request):
            The request to open.

        **kwargs (dict):
            Additional keyword arguments passed to urlopen.

    Raises:
        urllib2.HTTPError:
            The error for testing.
    """
    raise HTTPError(request.get_full_url(), 401, '', {}, StringIO(''))

def _urlopen_raise_urlerror(request, **kwargs):
    """Fake urlopen that raises a URLError for testing.

    Args:
        request (urllib2.Request):
            The request to open.

        **kwargs (dict):
            Additional keyword arguments passed to urlopen.

    Raises:
        urllib2.URLError:
            The error for testing.
    """
    raise URLError('url error')


text:
using AllReady.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AllReady.UnitTest
{
    public static class MockHelper
    {
        public static Mock<SignInManager<ApplicationUser>> CreateSignInManagerMock(Mock<UserManager<ApplicationUser>> userManager)
        {
            var httpContext = new Mock<HttpContext>();

            var contextAccessor = new Mock<IHttpContextAccessor>();
            contextAccessor.Setup(mock => mock.HttpContext).Returns(() => httpContext.Object);
            var claimsFactory = new Mock<IUserClaimsPrincipalFactory<ApplicationUser>>();
            var signInManager = new Mock<SignInManager<ApplicationUser>>(
            userManager.Object,
            contextAccessor.Object,
            claimsFactory.Object,
            null, null);

            return signInManager;
        }

        public static Mock<UserManager<ApplicationUser>> CreateUserManagerMock()
        {
            return new Mock<UserManager<ApplicationUser>>(Mock.Of<IUserStore<ApplicationUser>>(), null, null, null, null, null, null, null, null);
        }

    }
}

redpajama_set_name: RedPajamaGithub


text:
package org.randomcoder.mvc.controller;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class LoginControllerTest {
  private LoginController c;

  @Before public void setUp() {
    c = new LoginController();
  }

  @After public void tearDown() {
    c = null;
  }

  @Test public void testLogin() {
    assertEquals("login", c.login());
  }

  @Test public void testLoginError() {
    assertEquals("login-error", c.loginError());
  }
}


text:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode>SOAP-ENV:Server</faultcode>
      <faultstring>BPCOR-6136: Sending errors for the pending requests in the process scope since, the process instance has completed</faultstring>
      <faultactor>sun-bpel-engine</faultactor>
      <detail>
        <detailText>BPCOR-6136: Sending errors for the pending requests in the process scope since, the process instance has completed</detailText>
      </detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


text:
var api = api || {};  //!< @namespace api

/**
 * Configuration
 */
api.fps = 60;
api.KEYPRESS_TIME = 1000 / api.fps;
api.speedDroping = false;

/**
 * Get obstacles information.
 * @return a list of obstacles
 */
api.getObstacles = function(){
  var obs = [];
  for (var i in runner.horizon.obstacles){
    var obstacle = runner.horizon.obstacles[i];
    var ob = {};
    for (var key in obstacle)
      ob[key] = obstacle[key];
    obs.push(ob);
  }
  return obs;
};

/**
 * Get player(tRex) information.
 * @return a dict of obstacles
 */
api.getPlayer = function(){
  var player = {};
  var tRex = runner.tRex;
  for (var key in tRex)
    player[key] = tRex[key];
  return player;
};

/**
 * Get currentSpeed.
 * @return a number
 */
api.getCurrentSpeed = function(){
  return runner.currentSpeed;
};

/**
 * Check if game is paused
 * @return a boolean
 */
api.isPaused = function(){
  return runner.paused;
};

/**
 * Get keycode
 * @param {keycode name}, like 'JUMP', 'DUCK'
 */
api.getKeycode = function(type){
  for (var keycode in Runner.keycodes[type])
    return keycode;
};

/**
 * Jump
 */
api.jump = function(){
  if (this.getPlayer().status != 'JUMPING')
    Keyboard.keydown(this.getKeycode('JUMP'));
};

/**
 * Duck
 */
api.duck = function(){
  Keyboard.keydown(this.getKeycode('DUCK'));
};

/**
 * Start Ducking
 */
api.duckStart = function(){
  clearInterval(this.speedDropIntervalId);
  this.duckIntervalId = setInterval("api.duck()", this.KEYPRESS_TIME);
};

/**
 * Stop Ducking
 */
api.duckStop = function(){
  clearInterval(this.duckIntervalId);
  Keyboard.keyup(this.getKeycode('DUCK'));
};

/**
 * Checking if not JUMPING
 */
api.speedDropHandler = function(){
  if (this.getPlayer().status != 'JUMPING'){
    Keyboard.keyup(this.getKeycode('DUCK'));
    clearInterval(this.speedDropIntervalId);
    this.speedDroping = false;
  }
};

/**
 * Start Speed Droping
 */
api.speedDrop = function(){
  if (this.speedDroping)
    return;
  this.speedDroping = true;
  Keyboard.keydown(this.getKeycode('DUCK'));
  this.speedDropIntervalId = setInterval("api.speedDropHandler()", this.KEYPRESS_TIME);
};

/**
 * Check if game is paused, then play it
 */
api.keepPlay = function(){
  if (runner.paused)
    runner.play();
};


text:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Example Camera Margin</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <script src="../../build/perenquen.dev.js"></script>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>
<script>

    /*
        In this example we learn how to use secure margin to move your player without move the camera
        Use arrow keys UP, DOWN, LEFT, RIGHT to move the spaceship
     */

    var game = new PQ.Game();
    game.start();

    //Load assets
    game.assetLoader.add([
        {url: "../assets/game.json"}
    ]).load(onAssetsLoaded);

    //enable keyboard, also you can enable from the config, see the keyboards examples
    game.inputManager.enableKeyboard();

    //Create arrow hotkeys
    var up = game.inputManager.keyboard.getHotKey(PQ.Key.UP);
    var down = game.inputManager.keyboard.getHotKey(PQ.Key.DOWN);
    var left = game.inputManager.keyboard.getHotKey(PQ.Key.LEFT);
    var right = game.inputManager.keyboard.getHotKey(PQ.Key.RIGHT);

    function onAssetsLoaded(){
        //Create a 2000x2000 container
        var container = new PQ.Container()
                .setSize(2000, 2000)
                .setPosition(game.scene.width/2, game.scene.height/2)
                .addTo(game.scene);

        //Add a tilingbackground
        var background = new PQ.TilingSprite('starBackground.png', container.width, container.height)
                .setPosition(container.width/2, container.height/2)
                .addTo(container);

        //Create and label each sectors to know where you are.
        var graphic = new PQ.Graphics()
                .lineStyle(1, 0xffffff, 0.1)
                .addTo(container);

        var sectorSize = 200;

        for(var i = 1; i <= sectorSize; i++){
            graphic.moveTo(sectorSize * i, 0)
                    .lineTo(sectorSize * i, container.height)
                    .moveTo(0, sectorSize*i)
                    .lineTo(container.width, sectorSize*i);
        }

        function getText(x,y){
            return new PQ.Text(x + " - " + y, {
                fill: 0xffffff,
                font: "30px Arial"
            }).setAlpha(0.2);
        }

        for(var x = 0; x < 10; x++){
            for(var y = 0; y < 10; y++){

                getText(x,y).setPosition(200*x + 100, 200*y + 100)
                        .addTo(container);

            }
        }

        //Now we can add the play
        var player = new PQ.Sprite('player.png')
                .setPosition(container.width/2, container.height/2)
                .setRotation(PQ.utils.degToRad(90))
                .setScale(3)
                .addTo(container);

        //Implement a simple control system with arrow keys
        var speed = 300;
        player.update = function(gameTime){
            if(up.isDown){
                this.setAngularSpeed(speed);
            }else if(down.isDown){
                this.setAngularSpeed(-speed);
            }else if(down.isReleased || up.isReleased){
                this.setAngularSpeed(0);
            }

            if(left.isDown){
                this.direction -= 3*gameTime.delta;
            }else if(right.isDown){
                this.direction += 3*gameTime.delta;
            }

            this.rotation = this.direction + PQ.utils.degToRad(90);
        };

        //Camera follows the target in fixed mode
        game.scene.camera.setLimits(0,0,2000,2000); //Limit the view
        game.scene.camera.setTarget(player);

        //Set the margins
        var marginTop = 100;
        var marginBottom = 100;
        var marginLeft = 100;
        var marginRight = 100;
        game.scene.camera.setMargin(marginTop, marginBottom, marginLeft, marginRight);

        //And add a cross in the HUD layer to show the center of the screen
        //And a rectangle to show the margins
        var cross = new PQ.Graphics()
                .lineStyle(1, 0xff0000, 0.5)
                .moveTo(400, 0)
                .lineTo(400, 600)
                .moveTo(0, 300)
                .lineTo(800, 300)
                .lineStyle(2, 0x00ff00, 0.5)
                .drawRect(marginLeft, marginTop, 800 - marginLeft - marginRight, 600 - marginTop - marginBottom)
                .addTo(game.scene.hud);

    }
</script>
</body>
</html>


text:
[![Build Status](https://travis-ci.org/WebAssembly/decompressor-prototype.svg?branch=master)](https://travis-ci.org/WebAssembly/decompressor-prototype)

# Layer 1 decompressor protype


text:
package main

import (
	"bytes"
	"go/format"
	"io"
	"log"
	"os"
	"text/template"
)

func main() {
	typeList := []string{
		// Expressions:
		"ArrayType",
		"BadExpr",
		"BasicLit",
		"BinaryExpr",
		"CallExpr",
		"ChanType",
		"CompositeLit",
		"Ellipsis",
		"FuncLit",
		"FuncType",
		"Ident",
		"IndexExpr",
		"InterfaceType",
		"KeyValueExpr",
		"MapType",
		"ParenExpr",
		"SelectorExpr",
		"SliceExpr",
		"StarExpr",
		"StructType",
		"TypeAssertExpr",
		"UnaryExpr",

		// Statements:
		"AssignStmt",
		"BadStmt",
		"BlockStmt",
		"BranchStmt",
		"CaseClause",
		"CommClause",
		"DeclStmt",
		"DeferStmt",
		"EmptyStmt",
		"ExprStmt",
		"ForStmt",
		"GoStmt",
		"IfStmt",
		"IncDecStmt",
		"LabeledStmt",
		"RangeStmt",
		"ReturnStmt",
		"SelectStmt",
		"SendStmt",
		"SwitchStmt",
		"TypeSwitchStmt",

		// Others:
		"Comment",
		"CommentGroup",
		"FieldList",
		"File",
		"Package",
	}

	astcastFile, err := os.Create("astcast.go")
	if err != nil {
		log.Fatal(err)
	}
	writeCode(astcastFile, typeList)
	astcastTestFile, err := os.Create("astcast_test.go")
	if err != nil {
		log.Fatal(err)
	}
	writeTests(astcastTestFile, typeList)
}

func generateCode(tmplText string, typeList []string) []byte {
	tmpl := template.Must(template.New("code").Parse(tmplText))
	var code bytes.Buffer
	tmpl.Execute(&code, typeList)
	prettyCode, err := format.Source(code.Bytes())
	if err != nil {
		panic(err)
	}
	return prettyCode
}

func writeCode(output io.Writer, typeList []string) {
	code := generateCode(`// Code generated by astcast_generate.go; DO NOT EDIT

// Package astcast wraps type assertion operations in such way that you don't have
// to worry about nil pointer results anymore.
package astcast

import (
	"go/ast"
)

// A set of sentinel nil-like values that are returned
// by all "casting" functions in case of failed type assertion.
var (
{{ range . }}
Nil{{.}} = &ast.{{.}}{}
{{- end }}
)

{{ range . }}
// To{{.}} returns x as a non-nil *ast.{{.}}.
// If ast.Node actually has such dynamic type, the result is
// identical to normal type assertion. In case if it has
// different type, the returned value is Nil{{.}}.
func To{{.}}(x ast.Node) *ast.{{.}} {
	if x, ok := x.(*ast.{{.}}); ok {
		return x
	}
	return Nil{{.}}
}
{{ end }}
`, typeList)
	output.Write(code)
}

func writeTests(output io.Writer, typeList []string) {
	code := generateCode(`// Code generated by astcast_generate.go; DO NOT EDIT

package astcast

import (
	"go/ast"
	"testing"
)

{{ range . }}
func TestTo{{.}}(t *testing.T) {
	// Test successfull cast.
	if x := To{{.}}(&ast.{{.}}{}); x == Nil{{.}} || x == nil {
		t.Error("expected successfull cast, got nil")
	}
	// Test nil cast.
	if x := To{{.}}(nil); x != Nil{{.}} {
		t.Error("nil node didn't resulted in a sentinel value return")
	}
	// Test unsuccessfull cast.
	{{- if (eq . "Ident") }}
		if x := To{{.}}(&ast.CallExpr{}); x != Nil{{.}} || x == nil {
			t.Errorf("expected unsuccessfull cast to return nil sentinel")
		}
	{{- else }}
		if x := To{{.}}(&ast.Ident{}); x != Nil{{.}} || x == nil {
			t.Errorf("expected unsuccessfull cast to return nil sentinel")
		}
	{{- end }}
}
{{ end }}
`, typeList)
	output.Write(code)
}


text:
module.exports = function(config, appJsLoader, jssrc) {
  return {

    //make the source folder location available to the browser:
    client: {
      jssrc: jssrc
    },

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../../..',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load in the browser
    files: [
      'target/jstest/node_modules/chai/chai.js',
      jssrc + '/libs/bower/requirejs/js/require.js',
      'target/jstest/node_modules/karma-requirejs/lib/adapter.js',
      jssrc + '/' + appJsLoader, // scripts/Init.js or scripts/Main.min.js
      'src/test/javascript/test-main.js',
      {pattern: jssrc + '/libs/**', included: false},
      {pattern: jssrc + '/scripts/**', included: false},
      {pattern: jssrc + '/templates/**', included: false},
      {pattern: 'src/test/javascript/tests/**', included: false},
    ],

    // list of files / patterns to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  };
}


text:
require File.join(File.dirname(__FILE__), '..', '/spec_helper')
require 'ci_server_plugins/test_server_plugin'
module Blinky

  class StubBlinky
  end

  describe "TestCiServer" do

    before(:each) do
      @blinky = StubBlinky.new
      @blinky.extend(TestCiServer)
    end

    it "cycles through all possible statuses" do
      @blinky.should_receive(:building!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:failure!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:building!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:warning!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:building!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:success!).ordered
      @blinky.should_receive(:sleep).ordered
      @blinky.should_receive(:off!).ordered

      @blinky.watch_test_server
    end

  end
end


text:
/**
 * @ngdoc function
 * @name forms.function:Hosts
 * @description This form is for adding/editing a host on the inventory page
*/

export default ['i18n',
function(i18n) {
        return {

            addTitle: i18n._('CREATE HOST'),
            editTitle: '{{ host.name }}',
            name: 'host',
            basePath: 'hosts',
            well: false,
            formLabelSize: 'col-lg-3',
            formFieldSize: 'col-lg-9',
            iterator: 'host',
            detailsClick: "$state.go('hosts.edit', null, {reload:true})",
            activeEditState: 'hosts.edit',
            stateTree: 'hosts',
            headerFields:{
                enabled: {
                    class: 'Form-header-field',
                    ngClick: 'toggleHostEnabled(host)',
                    type: 'toggle',
                    awToolTip: "
" +
                        i18n._("Indicates if a host is available and should be included in running jobs.") +
                        "

" +
                        i18n._("For hosts that are part of an external" +
                               " inventory, this may be" +
                               " reset by the inventory sync process.") +
                        "
",
                    dataTitle: i18n._('Host Enabled'),
                }
            },
            fields: {
                name: {
                    label: i18n._('Host Name'),
                    type: 'text',
                    required: true,
                    awPopOver: "
" +
                    i18n._("Provide a host name, ip address, or ip address:port. Examples include:") +
                        "
" +
                        "
myserver.domain.com
" +
                        "127.0.0.1
" +
                        "10.1.0.140:25
" +
                        "server.example.com:25" +
                        "
",
                    dataTitle: i18n._('Host Name'),
                    dataPlacement: 'right',
                    dataContainer: 'body',
                    ngDisabled: '!(host.summary_fields.user_capabilities.edit || canAdd)'
                },
                description: {
                    label: i18n._('Description'),
                    ngDisabled: '!(host.summary_fields.user_capabilities.edit || canAdd)',
                    type: 'text'
                },
                variables: {
                    label: i18n._('Variables'),
                    type: 'code_mirror',
                    variables: 'variables',
                    class: 'Form-formGroup--fullWidth',
                    "default": "---",
                    awPopOver: "
" + i18n._("Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.") + "
" +
                        "JSON:
\n" +
                        "
{
 "somevar": "somevalue",
 "password": "magic"
 }
\n" +
                        "YAML:
\n" +
                        "
---
somevar: somevalue
password: magic

\n" +
                        '
' + i18n.sprintf(i18n._('View JSON examples at %s'), 'www.json.org') + '
' +
                        '
' + i18n.sprintf(i18n._('View YAML examples at %s'), 'docs.ansible.com') + '
',
                }
            },

            buttons: {
                cancel: {
                    ngClick: 'formCancel()',
                    ngShow: '(host.summary_fields.user_capabilities.edit || canAdd)'
                },
                close: {
                    ngClick: 'formCancel()',
                    ngShow: '!(host.summary_fields.user_capabilities.edit || canAdd)'
                },
                save: {
                    ngClick: 'formSave()',
                    ngDisabled: true,
                    ngShow: '(host.summary_fields.user_capabilities.edit || canAdd)'
                }
            },

            related: {
                ansible_facts: {
                    name: 'ansible_facts',
                    awToolTip: i18n._('Please save before viewing facts.'),
                    dataPlacement: 'top',
                    title: i18n._('Facts'),
                    skipGenerator: true
                },
                groups: {
                    name: 'groups',
                    awToolTip: i18n._('Please save before defining groups.'),
                    dataPlacement: 'top',
                    ngClick: "$state.go('hosts.edit.groups')",
                    title: i18n._('Groups'),
                    iterator: 'group',
                    skipGenerator: true
                },
                insights: {
                    name: 'insights',
                    awToolTip: i18n._('Please save before viewing Insights.'),
                    dataPlacement: 'top',
                    title: i18n._('Insights'),
                    skipGenerator: true,
                    ngIf: "host.insights_system_id!==null && host.summary_fields.inventory.hasOwnProperty('insights_credential_id')"
                },
                completed_jobs: {
                    name: 'completed_jobs',
                    title: i18n._('Completed Jobs'),
                    skipGenerator: true
                }
            }
        };
    }];