コード例 #1
0
ファイル: test_gengo.py プロジェクト: rlr/fjord
    def test_no_approved_jobs(self):
        gtoj_resp = {
            u'opstat': u'ok',
            u'response': {
                u'order': {
                    u'jobs_pending': [u'746197'],
                    u'jobs_revising': [],
                    u'as_group': 0,
                    u'order_id': u'263413',
                    u'jobs_queued': u'0',
                    u'total_credits': u'0.35',
                    u'currency': u'USD',
                    u'total_units': u'7',
                    u'jobs_approved': [],
                    u'jobs_reviewable': [],
                    u'jobs_available': [],
                    u'total_jobs': u'1'
                }
            }
        }

        with patch('fjord.translations.gengo_utils.Gengo') as GengoMock:
            instance = GengoMock.return_value
            instance.getTranslationOrderJobs.return_value = gtoj_resp

            gengo_api = gengo_utils.FjordGengo()
            jobs = gengo_api.completed_jobs_for_order('263413')
            eq_(jobs, [])
コード例 #2
0
ファイル: test_api.py プロジェクト: TroJan/fjord
    def test_throttle(self):
        # We allow 50 posts per hour.
        throttle_trigger = 50

        # Descriptions have to be unique otherwise we hit the
        # double-submit throttling. So we do this fancy thing here.
        def data_generator():
            while True:
                yield {
                    "happy": True,
                    "description": u"Great! " + str(time.time()),
                    "product": u"Firefox OS",
                    "channel": u"stable",
                    "version": u"1.1",
                    "platform": u"Firefox OS",
                    "locale": "en-US",
                }

        data = data_generator()

        # Now hit the api a fajillion times making sure things got
        # created
        for i in range(throttle_trigger):
            # django-ratelimit fails the throttling if we hit the url
            # a fajillion times in rapid succession. For now, we add
            # a sleep which means this test takes 5 seconds now.
            # FIXME: Look into this more for a better solution.
            time.sleep(0.05)
            r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data.next()))
            eq_(r.status_code, 201)

        # This one should trip the throttle trigger
        r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data.next()))
        eq_(r.status_code, 429)
コード例 #3
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_invalid_unicode_url(self):
        """Tests an API call with invalid unicode URL"""
        data = {
            'happy': True,
            'description': u'Great!',
            'category': u'ui',
            'product': u'Firefox OS',
            'channel': u'stable',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
            'email': '*****@*****.**',
            'url': 'தமிழகம்',
            'manufacturer': 'OmniCorp',
            'device': 'OmniCorp',
            'country': 'US',
            'user_agent': (
                'Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0'
            ),
            'source': 'email',
            'campaign': 'email_test',
        }
        r = self.client.post(
            reverse('feedback-api'),
            content_type='application/json',
            data=json.dumps(data))

        eq_(r.status_code, 400)
        content = json.loads(r.content)
        ok_(u'url' in content)
        ok_(content['url'][0].endswith(u'is not a valid url'))
コード例 #4
0
ファイル: test_api.py プロジェクト: TroJan/fjord
    def test_valid_urls(self):
        test_data = [
            "example.com",
            "example.com:80",
            "example.com:80/foo",
            "http://example.com",
            "http://example.com/foo",
            "http://example.com:80",
            "http://example.com:80/foo",
            "https://example.com",
            "https://example.com/foo",
            "https://example.com:80",
            "https://example.com:80/foo",
            "ftp://example.com",
            "about:mozilla",
            "chrome://foo",
        ]
        for url in test_data:
            data = {
                "happy": True,
                "channel": u"stable",
                "version": u"1.1",
                "description": u"Great!",
                "product": u"Firefox OS",
                "platform": u"Firefox OS",
                "url": url,
                "locale": "en-US",
            }

            r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data))
            eq_(r.status_code, 201, msg=("%s != 201 (%s)" % (r.status_code, url)))

            get_cache("default").clear()
コード例 #5
0
ファイル: test_api.py プロジェクト: TroJan/fjord
    def test_happy(self):
        self.create_basic_data()

        resp = self.client.get(reverse("feedback-api"), {"happy": "1"})
        json_data = json.loads(resp.content)
        eq_(json_data["count"], 2)
        eq_(len(json_data["results"]), 2)
コード例 #6
0
ファイル: test_utils.py プロジェクト: rlr/fjord
    def test_basic(self):
        """Correct options should be set and values should be sorted.
        """
        options = counts_to_options(self.counts, 'fruit', 'Fruit')
        eq_(options['name'], 'fruit')
        eq_(options['display'], 'Fruit')

        eq_(options['options'][0], {
            'name': 'bananas',
            'display': 'bananas',
            'value': 'bananas',
            'count': 10,
            'checked': False,
        })
        eq_(options['options'][1], {
            'name': 'oranges',
            'display': 'oranges',
            'value': 'oranges',
            'count': 6,
            'checked': False,
        })
        eq_(options['options'][2], {
            'name': 'apples',
            'display': 'apples',
            'value': 'apples',
            'count': 5,
            'checked': False,
        })
コード例 #7
0
ファイル: test_api.py プロジェクト: TroJan/fjord
    def test_url_max_length(self):
        url_base = "http://example.com/"

        # Up to 199 characters is fine.
        data = {
            "happy": True,
            "channel": u"stable",
            "version": u"1.1",
            "description": u"Great! 199",
            "product": u"Firefox OS",
            "platform": u"Firefox OS",
            "url": url_base + ("a" * (199 - len(url_base))) + "b",
            "locale": "en-US",
        }

        r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data))
        eq_(r.status_code, 201)

        # 200th character is not fine.
        data = {
            "happy": True,
            "channel": u"stable",
            "version": u"1.1",
            "description": u"Great! 200",
            "product": u"Firefox OS",
            "platform": u"Firefox OS",
            "url": url_base + ("a" * (200 - len(url_base))) + "b",
            "locale": "en-US",
        }

        r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data))
        eq_(r.status_code, 400)
コード例 #8
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_survey_disabled(self):
        """If the survey is disabled, kick up an error"""
        survey = SurveyFactory.create(enabled=False)

        data = {
            'experiment_version': '1',
            'response_version': 1,
            'person_id': 'joemamma',
            'survey_id': survey.name,
            'flow_id': '20141113',
            'question_id': '1',
            'updated_ts': self.timestamp(),
            'question_text': 'how was lunch?',
            'variation_id': '1'
        }

        resp = self.client.post(
            reverse('heartbeat-api'),
            content_type='application/json',
            data=json.dumps(data))

        eq_(resp.status_code, 400)
        errors = json.loads(resp.content)['errors']
        eq_(errors['survey_id'],
            ['survey "%s" is not enabled' % survey.name])
コード例 #9
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_missing_data(self):
        """Missing required data kicks up an error"""
        survey = SurveyFactory.create()

        orig_data = {
            'experiment_version': '1',
            'response_version': 1,
            'person_id': 'joemamma',
            'survey_id': survey.name,
            'flow_id': '20141113',
            'question_id': '1',
            'updated_ts': self.timestamp(),
            'question_text': 'how was lunch?',
            'variation_id': '1'
        }

        for key in orig_data.keys():
            data = dict(orig_data)
            del data[key]

            resp = self.client.post(
                reverse('heartbeat-api'),
                content_type='application/json',
                data=json.dumps(data))

            eq_(resp.status_code, 400)
            resp_data = json.loads(resp.content)
            assert key in resp_data['errors']
コード例 #10
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_post_with_link(self):
        token = TokenFactory()
        flavor = AlertFlavorFactory(name='Foo', slug='fooflavor')
        flavor.allowed_tokens.add(token)

        data = {
            'severity': 5,
            'summary': 'test alert',
            'description': (
                'All we ever see of stars are their old photographs.'
            ),
            'flavor': flavor.slug,
            'emitter_name': 'testemitter',
            'emitter_version': 0,
            'links': [{'name': 'link', 'url': 'http://example.com/'}]
        }

        resp = self.client.post(
            reverse('alerts-api'),
            data=json.dumps(data),
            content_type='application/json',
            HTTP_AUTHORIZATION='token ' + token.token
        )

        eq_(resp.status_code, 201)
        alert = Alert.objects.latest('id')
        eq_(json.loads(resp.content), {'detail': {'id': alert.id}})

        links = Link.objects.filter(alert=alert)
        eq_(len(links), 1)
        eq_(links[0].name, 'link')
        eq_(links[0].url, 'http://example.com/')
コード例 #11
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_post_invalid_start_time(self):
        token = TokenFactory()
        flavor = AlertFlavorFactory(name='Foo', slug='fooflavor')
        flavor.allowed_tokens.add(token)

        data = {
            'severity': 5,
            'summary': 'test alert',
            'description': (
                'All we ever see of stars are their old photographs.'
            ),
            'flavor': flavor.slug,
            'emitter_name': 'testemitter',
            'emitter_version': 0,
            'start_time': '2015'
        }

        resp = self.client.post(
            reverse('alerts-api'),
            data=json.dumps(data),
            content_type='application/json',
            HTTP_AUTHORIZATION='token ' + token.token
        )
        eq_(resp.status_code, 400)
        content = json.loads(resp.content)
        ok_(content['detail']['start_time'][0].startswith(
            u'Datetime has wrong format.'))
コード例 #12
0
ファイル: test_domain.py プロジェクト: rlr/fjord
    def test_get_domain(self):
        testdata = [
            # URLs with good domains
            (u'foo.example.com', u'example.com'),
            (u'http://example.com/', u'example.com'),
            (u'http://foo.example.com', u'example.com'),
            (u'http://foo.example.com/', u'example.com'),
            (u'http://foo.example.com:8000/bar/?foo=bar#foobar',
             u'example.com'),
            (u'https://foo.bar.baz.example.com/', u'example.com'),
            (u'example.com.br', u'example.com.br'),
            (u'foo.example.com.br', u'example.com.br'),
            (u'https://foo.example.com.br/', u'example.com.br'),
            (u'http://blog.goo.ne.jp/shinsburger', u'goo.ne.jp'),

            # FIXME - This fails in the tests. See if this works when we
            # change the code to get the most recent tld list from Mozilla.
            # (u'http://500px.com\u6253\u4e0d\u5f00/',
            #  u'500px.com\u6253\u4e0d\u5f00'),

            # URLs with domains we don't like
            (None, u''),
            (u'', u''),
            (u'about:home', u''),
            (u'chrome://whatever', u''),
            (u'127.0.0.1', u''),
            (u'ftp://[email protected]', u''),
            (u'155.39.97.145.in-addr.arpa', u''),
            (u'example.mil', u''),
            (u'localhost', u''),
        ]

        for data, expected in testdata:
            eq_(get_domain(data), expected)
コード例 #13
0
ファイル: test_analyzer_views.py プロジェクト: rlr/fjord
    def test_front_page(self):
        r = self.client.get(self.url)
        eq_(200, r.status_code)
        self.assertTemplateUsed(r, 'analytics/analyzer/search.html')

        pq = PyQuery(r.content)
        eq_(len(pq('li.opinion')), 7)
コード例 #14
0
ファイル: test_views.py プロジェクト: rlr/fjord
 def test_redirect_to_dashboard_if_anonymous(self):
     # AnonymousUser shouldn't get to the new-user-view, so make
     # sure they get redirected to the dashboard.
     resp = self.client.get(reverse('new-user-view'), follow=True)
     eq_(resp.status_code, 200)
     self.assertTemplateNotUsed('new_user.html')
     self.assertTemplateUsed('analytics/dashboard.html')
コード例 #15
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_double_submit_throttle(self):
        # We disallow two submits in a row of the same description
        # from the same ip address.
        data = {
            'happy': True,
            'description': u'Great!',
            'product': u'Firefox OS',
            'channel': u'stable',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
        }

        # First time is fine
        r = self.client.post(
            reverse('feedback-api'),
            content_type='application/json',
            data=json.dumps(data))
        eq_(r.status_code, 201)

        # Second time and back off!
        r = self.client.post(
            reverse('feedback-api'),
            content_type='application/json',
            data=json.dumps(data))
        eq_(r.status_code, 429)
コード例 #16
0
ファイル: test_api.py プロジェクト: TroJan/fjord
    def test_invalid_unicode_url(self):
        """Tests an API call with invalid unicode URL"""
        data = {
            "happy": True,
            "description": u"Great!",
            "category": u"ui",
            "product": u"Firefox OS",
            "channel": u"stable",
            "version": u"1.1",
            "platform": u"Firefox OS",
            "locale": "en-US",
            "email": "*****@*****.**",
            "url": "தமிழகம்",
            "manufacturer": "OmniCorp",
            "device": "OmniCorp",
            "country": "US",
            "user_agent": ("Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0"),
            "source": "email",
            "campaign": "email_test",
        }
        r = self.client.post(reverse("feedback-api"), content_type="application/json", data=json.dumps(data))

        eq_(r.status_code, 400)
        content = json.loads(r.content)
        ok_(u"url" in content)
        ok_(content["url"][0].endswith(u"is not a valid url"))
コード例 #17
0
ファイル: test_sumosuggest.py プロジェクト: rlr/fjord
    def test_not_json(self):
        # If we get back text and not JSON, then the sumo search
        # suggest provider should return no links. This tests the "if
        # any exception happens, return nothing" handling.
        with requests_mock.Mocker() as m:
            m.get(SUMO_SUGGEST_API_URL, text='Gah! Something bad happened')

            patch_point = 'fjord.suggest.providers.sumosuggest.logger'
            with patch(patch_point) as logger_patch:
                # Create a mock that we can call .exception() on and
                # it makes sure it got called.
                logger_patch.exception = MagicMock()

                feedback = ResponseFactory(
                    happy=False,
                    locale=u'en-US',
                    product=u'Firefox',
                    description=(
                        u'slow browser please speed improve i am wait '
                        u'speed improv'
                    )
                )

                links = self.suggester.get_suggestions(feedback)

                # Make sure we get back no links.
                eq_(len(links), 0)

                # Make sure logger.exception() got called once.
                eq_(logger_patch.exception.call_count, 1)
コード例 #18
0
ファイル: test_api.py プロジェクト: rlr/fjord
    def test_happy(self):
        self.create_basic_data()

        resp = self.client.get(reverse('feedback-api'), {'happy': '1'})
        json_data = json.loads(resp.content)
        eq_(json_data['count'], 2)
        eq_(len(json_data['results']), 2)
コード例 #19
0
ファイル: test_forms.py プロジェクト: rlr/fjord
    def test_valid(self):
        test_data = [
            # expected, url
            ('about:mozilla', 'about:mozilla'),
            ('chrome://foo', 'chrome://foo'),
            ('ftp://example.com/', 'ftp://example.com'),

            # From Django's URLField test data
            ('http://localhost/', 'http://localhost'),
            ('http://example.com/', 'http://example.com'),
            ('http://example.com./', 'http://example.com.'),
            ('http://www.example.com/', 'http://www.example.com'),
            ('http://www.example.com:8000/test',
             'http://www.example.com:8000/test'),
            ('http://valid-with-hyphens.com/', 'valid-with-hyphens.com'),
            ('http://subdomain.domain.com/', 'subdomain.domain.com'),
            ('http://200.8.9.10/', 'http://200.8.9.10'),
            ('http://200.8.9.10:8000/test', 'http://200.8.9.10:8000/test'),
            ('http://valid-----hyphens.com/', 'http://valid-----hyphens.com'),
            ('http://www.example.com/s/http://code.djangoproject.com/tkt/13',
             'www.example.com/s/http://code.djangoproject.com/tkt/13'),
        ]

        f = EnhancedURLField()

        for expected, url in test_data:
            try:
                eq_(f.clean(url), expected)
            except ValidationError:
                print url
                raise
コード例 #20
0
ファイル: test_forms.py プロジェクト: rlr/fjord
    def test_invalid(self):
        test_data = [
            # From Django's URLField test data
            ('This field is required.', ''),
            ('This field is required.', None),
            ('Enter a valid URL.', 'foo'),
            ('Enter a valid URL.', 'http://'),
            ('Enter a valid URL.', 'http://example'),
            ('Enter a valid URL.', 'http://example.'),
            ('Enter a valid URL.', 'com.'),
            ('Enter a valid URL.', '.'),
            ('Enter a valid URL.', 'http://.com'),
            ('Enter a valid URL.', 'http://invalid-.com'),
            ('Enter a valid URL.', 'http://-invalid.com'),
            ('Enter a valid URL.', 'http://inv-.alid-.com'),
            ('Enter a valid URL.', 'http://inv-.-alid.com'),
            ('Enter a valid URL.', '[a'),
            ('Enter a valid URL.', 'http://[a'),
        ]

        f = EnhancedURLField()

        for msg, url in test_data:
            try:
                f.clean(url)
            except ValidationError as exc:
                eq_(exc.messages, [msg])
コード例 #21
0
ファイル: test_gengo.py プロジェクト: rlr/fjord
    def test_machine_translate(self):
        with patch('fjord.translations.gengo_utils.Gengo') as GengoMock:
            # Note: We're mocking with "Muy lento" because it's
            # short, but the Gengo language guesser actually can't
            # figure out what language that is.
            instance = GengoMock.return_value
            instance.postTranslationJobs.return_value = {
                u'opstat': u'ok',
                u'response': {
                    u'jobs': {
                        u'job_1': {
                            u'status': u'approved',
                            u'job_id': u'NULL',
                            u'credits': 0,
                            u'unit_count': 7,
                            u'body_src': u'Muy lento',
                            u'mt': 1,
                            u'eta': -1,
                            u'custom_data': u'10101',
                            u'tier': u'machine',
                            u'lc_tgt': u'en',
                            u'lc_src': u'es',
                            u'body_tgt': u'Very slow',
                            u'slug': u'Input machine translation',
                            u'ctime': u'2014-05-21 15:09:50.361847'
                        }
                    }
                }
            }

            gengo_api = gengo_utils.FjordGengo()
            text = u'Muy lento'
            eq_(gengo_api.machine_translate(1010, 'es', 'en', text),
                u'Very slow')
コード例 #22
0
ファイル: test_utils.py プロジェクト: rlr/fjord
    def test_not_str(self):
        eq_(u'', smart_str(1))
        eq_(u'', smart_str(1.1))
        eq_(u'', smart_str(True))
        eq_(u'', smart_str(['a']))

        eq_(u'', smart_str(None))
コード例 #23
0
ファイル: test_auth.py プロジェクト: rlr/fjord
    def test_new_user(self):
        """Tests that new users get redirected to new_user page"""
        # Create a user that has no profile--this is the sign that the
        # user is new!
        new_user = UserFactory(profile=None)
        self.client_login_user(new_user)

        # Now do some ridiculous setup so we can call login_success()
        # on the Verify and see if it did what it should be doing.

        # FIXME - this can go away post django-browserid 0.9
        new_user.backend = 'django_browserid.auth.BrowserIDBackend'

        post_request = RequestFactory().post(reverse('browserid.login'))
        post_request.user = new_user
        post_request.session = self.client.session

        fv = FjordVerify()
        fv.user = new_user
        fv.request = post_request

        resp = fv.login_success()
        eq_(200, resp.status_code)
        body = json.loads(resp.content)
        eq_(body['redirect'], reverse('new-user-view'))
コード例 #24
0
ファイル: test_views.py プロジェクト: TroJan/fjord
    def test_email_invalid(self):
        """If email_ok box is checked, but bad email or no email, ignore it."""
        url = reverse('feedback', args=(u'firefox',))

        # Invalid email address gets ignored, but response is
        # otherwise saved.
        r = self.client.post(url, {
            'happy': 0,
            'description': u'There is something wrong here.\0',
            'email_ok': 'on',
            'email': '/dev/sda1\0',
        })
        assert not models.ResponseEmail.objects.exists()
        eq_(r.status_code, 302)

        # Invalid email address is ignored if email_ok box is not
        # checked.
        r = self.client.post(url, {
            'happy': 0,
            'description': u'There is something wrong here.\0',
            'email_ok': '',
            'email': "huh what's this for?",
        })
        assert not models.ResponseEmail.objects.exists()
        # Bad email if the box is not checked is not an error.
        eq_(r.status_code, 302)
コード例 #25
0
ファイル: test_views.py プロジェクト: TroJan/fjord
    def test_valid_urls(self):
        """Test valid url field values"""
        test_data = [
            # input, expected
            ('example.com', 'http://example.com/'),
            ('http://example.com', 'http://example.com/'),
            ('https://example.com', 'https://example.com/'),
            ('ftp://example.com', ''),  # We currently redact ftp urls
            ('about:config', 'about:config'),
            ('chrome://foo', 'chrome://foo')
        ]

        url = reverse('feedback', args=(u'firefox',))
        for item, expected in test_data:
            cache.clear()

            r = self.client.post(url, {
                'url': item,
                'happy': 0,
                'description': u'foo' + item
            })

            self.assertRedirects(r, reverse('thanks'))
            latest = models.Response.objects.latest('pk')
            eq_(latest.url, expected)
コード例 #26
0
ファイル: test_models.py プロジェクト: rlr/fjord
    def test_spanish_with_dennis_and_existing_translations(self):
        """Response should pick up existing translation"""
        existing_resp = ResponseFactory(
            locale=u'es',
            product=u'firefox',
            description=u'hola',
            translated_description=u'DUDE!'
        )

        resp = ResponseFactory(
            locale=u'es',
            product=u'firefox',
            description=u'hola',
            translated_description=u''
        )

        # Set the product up for translation *after* creating the response
        # so that it doesn't get auto-translated because Response is set up
        # for auto-translation.
        prod = Product.objects.get(db_name='firefox')
        prod.translation_system = u'dennis'
        prod.save()

        # No jobs should be translated
        eq_(len(resp.generate_translation_jobs()), 0)
        eq_(resp.translated_description, existing_resp.translated_description)
コード例 #27
0
ファイル: test_views.py プロジェクト: rlr/fjord
    def test_response_view_analyzer(self):
        """Test secret section only shows up for analyzers"""
        resp = ResponseFactory(happy=True, description=u'the bestest best!')

        self.refresh()
        r = self.client.get(reverse('response_view', args=(resp.id,)))

        eq_(200, r.status_code)
        self.assertTemplateUsed(r, 'analytics/response.html')
        assert str(resp.description) in r.content

        # Verify there is no secret area visible for non-analyzers.
        pq = PyQuery(r.content)
        secretarea = pq('dl.secret')
        eq_(len(secretarea), 0)

        jane = ProfileFactory(user__email='*****@*****.**').user
        jane.groups.add(Group.objects.get(name='analyzers'))

        self.client_login_user(jane)
        r = self.client.get(reverse('response_view', args=(resp.id,)))

        eq_(200, r.status_code)
        self.assertTemplateUsed(r, 'analytics/response.html')
        assert str(resp.description) in r.content

        # Verify the secret area is there.
        pq = PyQuery(r.content)
        secretarea = pq('dl.secret')
        eq_(len(secretarea), 1)

        # Verify there is an mlt section in the secret area.
        mlt = pq('dd#mlt')
        eq_(len(mlt), 1)
コード例 #28
0
ファイル: test_views.py プロジェクト: rlr/fjord
 def test_date_start_valueerror(self):
     # https://bugzilla.mozilla.org/show_bug.cgi?id=898584
     url = reverse('dashboard')
     r = self.client.get(url, {
         'date_start': '0001-01-01',
     })
     eq_(r.status_code, 200)
コード例 #29
0
ファイル: test_utils.py プロジェクト: rlr/fjord
    def test_edge_cases(self):
        test_data = [
            (None, 72, None),
            ('abcdefghijkl\nfoo bar', 8, 'abcdefgh\nijkl\nfoo bar'),
        ]

        for arg, width, expected in test_data:
            eq_(wrap_with_paragraphs(arg, width), expected)
コード例 #30
0
ファイル: test_views.py プロジェクト: rlr/fjord
    def test_search_format_atom(self):
        """Atom output works"""
        url = reverse('dashboard')
        # Text search
        r = self.client.get(url, {'q': u'apple', 'format': 'atom'})
        eq_(r.status_code, 200)

        assert 'http://www.w3.org/2005/Atom' in r.content