Пример #1
0
    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)
Пример #2
0
    def test_response_id_in_qs_authenticated(self):
        """Verify response_id in querystring overrides session id"""
        # Create analyzer and log in.

        jane = AnalyzerProfileFactory(user__email='*****@*****.**').user
        self.client_login_user(jane)

        # Create some feedback which sets the response_id in the
        # session.
        url = reverse('feedback', args=(u'firefox',), locale='en-US')
        r = self.client.post(url, {
            'happy': 0,
            'description': u'Why Firefox not make me sandwiches!',
        }, follow=True)

        # Create another piece of feedback which is not the one we
        # just did.
        feedback = ResponseFactory(description=u'purple horseshoes')

        # Fetch the thank you page with the response_id in the
        # querystring.
        url = reverse('thanks') + '?response_id={0}'.format(feedback.id)
        r = self.client.get(url)

        eq_(r.status_code, 200)
        eq_(r.context['feedback'].id, feedback.id)
        eq_(r.context['suggestions'], [])
Пример #3
0
    def test_urls_product_inferred_platform_fxios(self):
        """Test firefoxdev platform gets inferred"""
        ProductFactory(
            enabled=True,
            display_name=u"Firefox for iOS",
            db_name=u"Firefox for iOS",
            slug=u"fxios",
            on_dashboard=False,
            on_picker=False,
            browser=u"Firefox for iOS",
        )

        # Test that we infer the platform if the products are the
        # same.
        ua = (
            "Mozilla/5.0 (iPod touch; CPU iPhone OS 8_4 like Mac OS X) "
            "AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 "
            "Mobile/12H143 Safari/600.1.4"
        )
        url = reverse("feedback", args=("fxios",))
        resp = self.client.post(
            url,
            {"happy": 1, "description": u"Firefox for iOS rocks!", "url": u"http://mozilla.org/"},
            HTTP_USER_AGENT=ua,
        )

        self.assertRedirects(resp, reverse("thanks"))
        assert models.Response.objects.count() == 1
        feedback = models.Response.objects.latest(field_name="id")
        assert feedback.locale == "en-US"
        assert feedback.product == "Firefox for iOS"
        assert feedback.platform == "iPhone OS 8.4"
        assert feedback.browser == "Firefox for iOS"
        assert feedback.browser_version == "1.0"
        assert feedback.browser_platform == "iPhone OS"
Пример #4
0
    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):
            r = self.client.post(reverse('feedback-api'), data.next())
            eq_(r.status_code, 201)

        # This one should trip the throttle trigger
        r = self.client.post(reverse('feedback-api'), data.next())
        eq_(r.status_code, 429)
Пример #5
0
    def test_double_submit_throttling(self):
        """Verify double-submit throttling."""
        # Make sure there are no responses in the db because we're
        # basing our test on response counts.
        initial_amount = models.Response.objects.count()
        eq_(initial_amount, 0)

        url = reverse('feedback')

        data = {
            'happy': 1,
            'description': u'Double-submit is the best!',
            'url': u'http://mozilla.org/'
        }

        # Post it!
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse('thanks'))
        eq_(models.Response.objects.count(), 1)

        # Post it again! This time it doesn't get to the db.
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse('thanks'))
        eq_(models.Response.objects.count(), 1)

        # Post something different from the same ip address.
        data['description'] = u'Not a double-submit!'
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse('thanks'))
        eq_(models.Response.objects.count(), 2)
    def test_update_survey(self):
        survey = SurveyFactory()

        data = {
            'id': survey.id,
            'name': 'rehanrocks',
            'description': survey.description,
            'enabled': survey.enabled
        }

        resp = self.client.post(
            reverse('hb_surveys_update', args=(survey.id,)),
            data
        )
        assert resp.status_code == 403

        jane = AnalyzerProfileFactory().user
        self.client_login_user(jane)

        resp = self.client.post(
            reverse('hb_surveys_update', args=(survey.id,)),
            data
        )
        assert resp.status_code == 302

        # Make sure it's in the survey list
        resp = self.client.get(reverse('hb_surveys'))
        assert resp.status_code == 200
        assert data['name'] in resp.content
Пример #7
0
    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'), 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'), data)
        eq_(r.status_code, 400)
Пример #8
0
    def test_unicode_in_description(self):
        """Description should accept unicode data"""
        url = reverse("feedback", args=(u"firefox",))
        r = self.client.post(url, {"url": "http://mozilla.org/", "happy": 0, "description": u"\u2713 this works"})

        self.assertRedirects(r, reverse("thanks"))
        assert models.Response.objects.count() == 1
Пример #9
0
    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))
        assert r.status_code == 201

        # Second time and back off!
        r = self.client.post(
            reverse('feedback-api'),
            content_type='application/json',
            data=json.dumps(data))
        assert r.status_code == 429
Пример #10
0
    def test_dashboard_atom_links(self):
        """Test dashboard atom links are correct"""
        r = self.client.get(reverse('dashboard'))
        eq_(200, r.status_code)
        assert '/en-US/?format=atom' in r.content

        r = self.client.get(
            reverse('dashboard'),
            {'happy': 1})
        eq_(200, r.status_code)
        pq = PyQuery(r.content)
        pq = pq('link[type="application/atom+xml"]')
        qs = QueryDict(pq[0].attrib['href'].split('?')[1])
        eq_(qs['happy'], u'1')
        eq_(qs['format'], u'atom')

        r = self.client.get(
            reverse('dashboard'),
            {'product': 'Firefox', 'version': '20.0.0'})
        eq_(200, r.status_code)
        pq = PyQuery(r.content)
        pq = pq('link[type="application/atom+xml"]')
        qs = QueryDict(pq[0].attrib['href'].split('?')[1])
        eq_(qs['product'], u'Firefox')
        eq_(qs['version'], u'20.0.0')
Пример #11
0
    def test_valid_happy(self):
        """Submitting a valid happy form creates an item in the DB.

        Additionally, it should redirect to the Thanks page.
        """
        amount = models.Response.objects.count()

        url = reverse('feedback')
        r = self.client.post(url, {
            'happy': 1,
            'description': u'Firefox rocks!',
            'url': u'http://mozilla.org/'
        })

        self.assertRedirects(r, reverse('thanks'))
        eq_(amount + 1, models.Response.objects.count())

        feedback = models.Response.objects.latest(field_name='id')
        eq_(u'Firefox rocks!', feedback.description)
        eq_(u'http://mozilla.org/', feedback.url)
        eq_(True, feedback.happy)

        # This comes from the client.post url.
        eq_(u'en-US', feedback.locale)
        # Note: This comes from the user agent from the LocalizingClient
        eq_(u'Firefox', feedback.product)
        eq_(u'stable', feedback.channel)
        eq_(u'14.0.1', feedback.version)
Пример #12
0
    def test_reject_non_firefox(self):
        """Using non-Firefox browser lands you on download-firefox page."""
        # TODO: This test might need to change when the router starts routing.
        url = reverse("feedback")

        for ua in (
            ("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; " "Trident/5.0)"),
            (
                "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 "
                "(KHTML, like Gecko) Chrome/24.0.1312.68 Safari/537.17"
            ),
            (
                "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus "
                "Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 "
                "Mobile Safari/534.30"
            ),
            (
                "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Xoom Build/IMM76) "
                "AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 "
                "Safari/534.30"
            ),
            (
                "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.22 (KHTML, like "
                "Gecko) Chrome/25.0.1364.97 Safari/537.22"
            ),
        ):

            r = self.client.get(url, HTTP_USER_AGENT=ua)
            self.assertRedirects(r, reverse("download-firefox"))
Пример #13
0
    def test_unicode_in_url(self):
        """URL should accept unicode data"""
        url = reverse("feedback", args=("firefox.desktop.stable",))
        r = self.client.post(url, {"url": u"http://mozilla.org/\u2713", "happy": 0, "description": u"foo"})

        self.assertRedirects(r, reverse("thanks"))
        eq_(models.Response.objects.count(), 1)
Пример #14
0
    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,)))

        assert r.status_code == 200
        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')
        assert len(secretarea) == 0

        jane = AnalyzerProfileFactory().user
        self.client_login_user(jane)

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

        assert r.status_code == 200
        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')
        assert len(secretarea) == 1

        # Verify there is an mlt section in the secret area.
        mlt = pq('dd#mlt')
        assert len(mlt) == 1
Пример #15
0
    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)
Пример #16
0
    def test_urls_product_no_inferred_platform(self):
        """Test setting product from the url and platform non-inference"""
        prod = ProductFactory(
            display_name=u'Someprod',
            db_name=u'Someprod',
            slug=u'someprod',
            enabled=True,
        )

        amount = models.Response.objects.count()

        # The UA is for a different browser than what the user is
        # leaving feedback for, so we should not infer the platform.
        ua = 'Mozilla/5.0 (Windows NT 6.0; rv:14.0) Gecko/20100101 Firefox/14.0.1'  # noqa
        url = reverse('feedback', args=(prod.slug,))
        resp = self.client.post(
            url,
            {
                'happy': 1,
                'description': u'Firefox rocks FFA!',
                'url': u'http://mozilla.org/'
            },
            HTTP_USER_AGENT=ua)

        self.assertRedirects(resp, reverse('thanks'))
        eq_(amount + 1, models.Response.objects.count())
        feedback = models.Response.objects.latest(field_name='id')
        eq_(u'en-US', feedback.locale)
        eq_(u'Someprod', feedback.product)
        eq_(u'', feedback.platform)
Пример #17
0
    def test_valid_happy(self):
        """Submitting a valid happy form creates an item in the DB.

        Additionally, it should redirect to the Thanks page.
        """
        amount = models.Response.objects.count()

        url = reverse("feedback", args=(u"firefox",))
        r = self.client.post(url, {"happy": 1, "description": u"Firefox rocks!", "url": u"http://mozilla.org/"})

        self.assertRedirects(r, reverse("thanks"))
        assert amount + 1 == models.Response.objects.count()

        feedback = models.Response.objects.latest(field_name="id")
        assert u"Firefox rocks!" == feedback.description
        assert u"http://mozilla.org/" == feedback.url
        assert True == feedback.happy

        # This comes from the client.post url.
        assert u"en-US" == feedback.locale
        # Note: This comes from the user agent from the LocalizingClient
        assert u"Firefox" == feedback.product
        assert u"14.0.1" == feedback.version

        # Make sure it doesn't create an email record
        assert models.ResponseEmail.objects.count() == 0

        # Make sure it doesn't create a context record
        assert models.ResponseContext.objects.count() == 0
Пример #18
0
    def test_valid_sad(self):
        """Submitting a valid sad form creates an item in the DB.

        Additionally, it should redirect to the Thanks page.
        """
        amount = models.Response.objects.count()

        url = reverse('feedback')
        r = self.client.post(url, {
            'happy': 0,
            'description': u"Firefox doesn't make me sandwiches. :("
        })

        self.assertRedirects(r, reverse('thanks'))
        eq_(amount + 1, models.Response.objects.count())

        feedback = models.Response.objects.latest(field_name='id')
        eq_(u"Firefox doesn't make me sandwiches. :(", feedback.description)
        eq_(u'', feedback.url)
        eq_(False, feedback.happy)

        # This comes from the client.post url.
        eq_(u'en-US', feedback.locale)
        # Note: This comes from the user agent from the LocalizingClient
        eq_(u'Firefox', feedback.product)
        eq_(u'stable', feedback.channel)
        eq_(u'14.0.1', feedback.version)
Пример #19
0
    def test_whitespace_description(self):
        """Descriptions with just whitespace get thrown out"""
        url = reverse("feedback", args=(u"firefox",))
        r = self.client.post(url, {"url": "http://mozilla.org/", "happy": 0, "description": u"      "})

        self.assertRedirects(r, reverse("thanks"))
        assert models.Response.objects.count() == 0
Пример #20
0
    def test_composed_prodchan(self):
        # Test with product and channel
        data = {
            "happy": True,
            "description": u"Great!",
            "product": u"Firefox OS",
            "channel": u"stable",
            "version": u"1.1",
            "platform": u"Firefox OS",
            "locale": "en-US",
        }

        r = self.client.post(reverse("api-post-feedback"), data)
        eq_(r.status_code, 201)

        feedback = models.Response.uncached.latest(field_name="id")
        eq_(feedback.prodchan, u"firefoxos.stable")

        # Test with a product, but no channel
        data = {
            "happy": True,
            "description": u"Great!",
            "product": u"Firefox OS",
            "version": u"1.1",
            "platform": u"Firefox OS",
            "locale": "en-US",
        }

        r = self.client.post(reverse("api-post-feedback"), data)
        eq_(r.status_code, 201)

        feedback = models.Response.uncached.latest(field_name="id")
        eq_(feedback.prodchan, u"firefoxos.unknown")
Пример #21
0
    def test_products_and_versions(self):
        self.create_basic_data()

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox'})
        json_data = json.loads(resp.content)
        assert json_data['count'] == 2
        assert len(json_data['results']) == 2

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox,Firefox for Android'})
        json_data = json.loads(resp.content)
        assert json_data['count'] == 3
        assert len(json_data['results']) == 3

        # version without product gets ignored
        resp = self.client.get(reverse('feedback-api'),
                               {'versions': '30.0'})
        json_data = json.loads(resp.content)
        assert json_data['count'] == 3
        assert len(json_data['results']) == 3

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox',
                                'versions': '30.0'})
        json_data = json.loads(resp.content)
        assert json_data['count'] == 1
        assert len(json_data['results']) == 1
Пример #22
0
    def test_throttle(self):
        # This test is a little goofy. Essentially we figure out what
        # the throttle trigger is, post that many times, then post
        # once more to see if it gets throttled. So if the trigger is
        # 100, then we post 101 times which seems kind of excessive
        # in a test.

        # Get the trigger so that we can post that many times + 1
        # to test throttling
        trigger = settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["anon"]
        trigger = int(trigger.split("/")[0])

        data = {
            "happy": True,
            "description": u"Great!",
            "product": u"Firefox OS",
            "channel": u"stable",
            "version": u"1.1",
            "platform": u"Firefox OS",
            "locale": "en-US",
        }

        # Now hit the api a fajillion times making sure things got
        # created
        for i in range(trigger):
            r = self.client.post(reverse("api-post-feedback"), data)
            eq_(r.status_code, 201)

        # This one should trip the throttle trigger
        r = self.client.post(reverse("api-post-feedback"), data)
        eq_(r.status_code, 429)
Пример #23
0
    def test_urls_locale(self):
        """Test setting locale from the locale part of the url"""
        try:
            count = models.Response.objects.count()

            # Hard-coded url so we're guaranteed to get /es/.
            url = reverse('feedback', args=(u'firefox',), locale='es')
            resp = self.client.post(url, {
                'happy': 1,
                'description': u'Firefox rocks for es!',
                'url': u'http://mozilla.org/'
            })

            self.assertRedirects(resp, reverse('thanks'))
            eq_(count + 1, models.Response.objects.count())
            feedback = models.Response.objects.latest(field_name='id')
            eq_(u'es', feedback.locale)
            eq_(u'Firefox', feedback.product)
            eq_(u'14.0.1', feedback.version)

        finally:
            # FIXME - We have to do another request to set the
            # LocalizingClient back to en-US otherwise it breaks all
            # tests ever. This is goofy-pants since it should get
            # reset in test teardown.
            resp = self.client.get('/en-US/feedback/')
Пример #24
0
    def test_throttle(self):
        # This test is a little goofy. Essentially we figure out what
        # the throttle trigger is, post that many times, then post
        # once more to see if it gets throttled. So if the trigger is
        # 100, then we post 101 times which seems kind of excessive
        # in a test.

        # Get the trigger so that we can post that many times + 1
        # to test throttling
        trigger = settings.REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['anon']
        trigger = int(trigger.split('/')[0])

        data = {
            'happy': True,
            'description': u'Great!',
            'product': u'Firefox OS',
            'channel': u'stable',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
        }

        # Now hit the api a fajillion times making sure things got
        # created
        for i in range(trigger):
            r = self.client.post(reverse('api-post-feedback'), data)
            eq_(r.status_code, 201)

        # This one should trip the throttle trigger
        r = self.client.post(reverse('api-post-feedback'), data)
        eq_(r.status_code, 429)
Пример #25
0
    def test_composed_prodchan(self):
        # Test with product and channel
        data = {
            'happy': True,
            'description': u'Great!',
            'product': u'Firefox OS',
            'channel': u'stable',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
        }

        r = self.client.post(reverse('feedback-api'), data)
        eq_(r.status_code, 201)

        feedback = models.Response.uncached.latest(field_name='id')
        eq_(feedback.prodchan, u'firefoxos.stable')

        # Test with a product, but no channel
        data = {
            'happy': True,
            'description': u'Great! Hazzah!',
            'product': u'Firefox OS',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
        }

        r = self.client.post(reverse('feedback-api'), data)
        eq_(r.status_code, 201)

        feedback = models.Response.uncached.latest(field_name='id')
        eq_(feedback.prodchan, u'firefoxos.unknown')
Пример #26
0
    def test_throttled(self):
        """Verify that posts are throttled."""
        # Make sure there are no responses in the db because we're
        # basing our test on response counts.
        initial_amount = models.Response.objects.count()
        eq_(initial_amount, 0)

        url = reverse('feedback')

        # Toss 100 responses in.
        for i in range(100):
            r = self.client.post(url, {
                'happy': 1,
                'description': u'{0} Firefox rocks! {0}'.format(i),
                'url': u'http://mozilla.org/'
            })
        eq_(models.Response.objects.count(), 100)

        # The 101st should be throttled, so there should only be 100
        # responses in the db.
        r = self.client.post(url, {
            'happy': 1,
            'description': u'Firefox rocks!',
            'url': u'http://mozilla.org/'
        })
        eq_(models.Response.objects.count(), 100)

        # Make sure we still went to the Thanks page.
        self.assertRedirects(r, reverse('thanks'))
Пример #27
0
    def test_products_and_versions(self):
        self.create_basic_data()

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox'})
        json_data = json.loads(resp.content)
        eq_(json_data['count'], 2)
        eq_(len(json_data['results']), 2)

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox,Firefox for Android'})
        json_data = json.loads(resp.content)
        eq_(json_data['count'], 3)
        eq_(len(json_data['results']), 3)

        # version without product gets ignored
        resp = self.client.get(reverse('feedback-api'),
                               {'versions': '30.0'})
        json_data = json.loads(resp.content)
        eq_(json_data['count'], 3)
        eq_(len(json_data['results']), 3)

        resp = self.client.get(reverse('feedback-api'),
                               {'products': 'Firefox',
                                'versions': '30.0'})
        json_data = json.loads(resp.content)
        eq_(json_data['count'], 1)
        eq_(len(json_data['results']), 1)
Пример #28
0
    def test_double_submit_throttling(self):
        """Verify double-submit throttling."""
        # Make sure there are no responses in the db because we're
        # basing our test on response counts.
        initial_amount = models.Response.objects.count()
        assert initial_amount == 0

        url = reverse("feedback", args=(u"firefox",))

        data = {"happy": 1, "description": u"Double-submit is the best!", "url": u"http://mozilla.org/"}

        # Post it!
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse("thanks"))
        assert models.Response.objects.count() == 1

        # Post it again! This time it doesn't get to the db.
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse("thanks"))
        assert models.Response.objects.count() == 1

        # Post something different from the same ip address.
        data["description"] = u"Not a double-submit!"
        r = self.client.post(url, data)
        self.assertRedirects(r, reverse("thanks"))
        assert models.Response.objects.count() == 2
Пример #29
0
    def test_missing_data(self):
        data = {}

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

        json_data = json.loads(resp.content)
        eq_(json_data['msg'],
            'missing fields: answer, channel, locale, platform, poll, '
            'product, version')

        data = {
            'locale': 'es'
        }

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

        json_data = json.loads(resp.content)
        eq_(json_data['msg'],
            'missing fields: answer, channel, platform, poll, '
            'product, version')
Пример #30
0
    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'))
Пример #31
0
    def test_minimal_data(self):
        """Minimum amount of data required"""
        survey = SurveyFactory.create()
        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))

        assert resp.status_code == 201
Пример #32
0
    def test_picker_with_disabled_products(self):
        ProductFactory(display_name=u'ProductFoo',
                       slug=u'productfoo',
                       enabled=True)
        ProductFactory(display_name=u'ProductBar',
                       slug=u'productbar',
                       enabled=False)

        cache.clear()

        resp = self.client.get(reverse('feedback'))

        eq_(resp.status_code, 200)

        # This is on the picker
        self.assertContains(resp, 'ProductFoo')
        self.assertContains(resp, 'productfoo')

        # This is not on the picker
        self.assertNotContains(resp, 'ProductBar')
        self.assertNotContains(resp, 'productbar')
Пример #33
0
    def test_old_responses(self):
        # Make sure we can't see responses from > 180 days ago
        cutoff = datetime.today() - timedelta(days=180)
        ResponseFactory(description='Young enough--Party!',
                        created=cutoff + timedelta(days=1))
        ResponseFactory(description='Too old--Get off my lawn!',
                        created=cutoff - timedelta(days=1))
        self.refresh()

        resp = self.client.get(
            reverse('feedback-api'), {
                'date_start':
                (cutoff - timedelta(days=1)).strftime('%Y-%m-%d'),
                'date_end': (cutoff + timedelta(days=1)).strftime('%Y-%m-%d')
            })
        json_data = json.loads(resp.content)
        results = json_data['results']
        assert len(results) == 1

        assert 'Young enough--Party!' in resp.content
        assert 'Too old--Get off my lawn!' not in resp.content
Пример #34
0
    def test_minimal(self):
        data = {
            'happy': True,
            'description': u'Great!',
            'product': u'Firefox OS'
        }

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

        feedback = models.Response.objects.latest(field_name='id')
        assert feedback.happy is True
        assert feedback.description == data['description']
        assert feedback.product == data['product']

        # Fills in defaults
        assert feedback.url == u''
        assert feedback.api == 1
        assert feedback.user_agent == u''
Пример #35
0
 def test_invalid_search(self):
     url = reverse('dashboard')
     # Invalid values for happy shouldn't filter
     r = self.client.get(url, {'happy': 'fish'})
     eq_(r.status_code, 200)
     pq = PyQuery(r.content)
     eq_(len(pq('li.opinion')), 7)
     # Unknown parameters should be ignored.
     r = self.client.get(url, {'apples': 'oranges'})
     eq_(r.status_code, 200)
     pq = PyQuery(r.content)
     eq_(len(pq('li.opinion')), 7)
     # A broken date range search shouldn't affect anything
     # Why this? Because this is the thing the fuzzer found.
     r = self.client.get(url, {
         'date_end': '/etc/shadow\x00',
         'date_start': '/etc/passwd\x00'
     })
     eq_(r.status_code, 200)
     pq = PyQuery(r.content)
     eq_(len(pq('li.opinion')), 7)
Пример #36
0
    def test_picker_with_not_on_picker_products(self):
        ProductFactory(display_name=u'ProductFoo',
                       slug=u'productfoo',
                       on_picker=True)
        ProductFactory(display_name=u'ProductBar',
                       slug=u'productbar',
                       on_picker=False)

        cache.clear()

        resp = self.client.get(reverse('picker'))

        assert resp.status_code == 200

        # This is on the picker
        assert 'ProductFoo' in resp.content
        assert 'productfoo' in resp.content

        # This is not on the picker
        assert 'ProductBar' not in resp.content
        assert 'productbar' not in resp.content
Пример #37
0
    def test_fjord_authorization_token(self):
        """Verify auth will use Fjord-Authorization header if Authorization
        isn't there

        """
        token = TokenFactory()
        flavor = AlertFlavorFactory(name='Foo', slug='fooflavor')
        flavor.allowed_tokens.add(token)

        qs = {
            'flavors': flavor.slug
        }
        resp = self.client.get(
            reverse('alerts-api') + '?' + urllib.urlencode(qs),
            HTTP_FJORD_AUTHORIZATION='token ' + token.token
        )

        assert resp.status_code == 200
        assert (
            json.loads(resp.content) ==
            {u'count': 0, u'total': 0, u'alerts': []}
        )
Пример #38
0
    def test_zero_fill(self):
        """If a day in a date range has no data, it should be zero filled."""
        # Note that we request a date range that includes 3 days without data.
        url = reverse('dashboard')
        start = (datetime.now() - timedelta(days=9))
        end = (datetime.now() - timedelta(days=3))

        r = self.client.get(
            url, {
                'date_start': start.strftime('%Y-%m-%d'),
                'date_end': end.strftime('%Y-%m-%d'),
            })
        # The histogram data is of the form [d, v], where d is a number of
        # milliseconds since the epoch, and v is the value at that time stamp.
        dates = [d[0] for d in r.context['histogram'][0]['data']]
        dates = [datetime.fromtimestamp(d / 1000) for d in dates]
        days = [d.day for d in dates]

        d = start
        while d <= end:
            assert d.day in days, "Day %s has no data." % d.day
            d += timedelta(days=1)
Пример #39
0
    def test_max(self):
        token = TokenFactory()
        flavor = AlertFlavorFactory(name='Foo', slug='fooflavor')
        flavor.allowed_tokens.add(token)

        alert1 = AlertFactory(summary=u'alert 1', flavor=flavor)
        # We backdate the created so we can verify we're getting the
        # right order of alerts.
        alert1.created = datetime.datetime.now() - datetime.timedelta(days=5)
        alert1.save()

        AlertFactory(summary=u'alert 2', flavor=flavor)

        qs = {'flavors': flavor.slug, 'max': 1}
        resp = self.client.get(reverse('alerts-api') + '?' +
                               urllib.urlencode(qs),
                               HTTP_AUTHORIZATION='token ' + token.token)

        eq_(resp.status_code, 200)
        eq_(
            json.loads(resp.content), {
                u'count':
                1,
                u'total':
                2,
                u'alerts': [{
                    u'id': WHATEVER,
                    u'summary': u'alert 2',
                    u'description': u'the account balance is at $5.',
                    u'flavor': flavor.slug,
                    u'emitter_version': 0,
                    u'emitter_name': u'balance-checker',
                    u'start_time': None,
                    u'end_time': None,
                    u'created': WHATEVER,
                    u'severity': 0,
                    u'links': []
                }]
            })
Пример #40
0
    def test_survey_doesnt_exist(self):
        """If the survey doesn't exist, kick up an error"""
        data = {
            'experiment_version': '1',
            'response_version': 1,
            'person_id': 'joemamma',
            'survey_id': 'foosurvey',
            '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'],
            [u'Object with name=foosurvey does not exist.'])
Пример #41
0
    def test_add_product(self):
        jane = AnalyzerProfileFactory().user
        self.client_login_user(jane)

        data = {
            'enabled': True,
            'display_name': 'Rehan',
            'display_description': '*the* Rehan',
            'db_name': 'rehan',
            'slug': 'rehan',
            'on_dashboard': True,
            'on_picker': True,
            'browser': '',
            'browser_data_browser': '',
            'notes': ''
        }

        resp = self.client.post(reverse('analytics_products'),
                                data,
                                follow=True)
        assert resp.status_code == 200
        assert data['display_name'] in resp.content
Пример #42
0
    def test_monitor_view(self):
        """Tests for the monitor view."""
        # TODO: When we add a mocking framework, we can mock this
        # properly.
        test_memcached = views.test_memcached
        try:
            with self.settings(
                SHOW_STAGE_NOTICE=True,
                CACHES={
                    'default': {
                        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                        'LOCATION': ['localhost:11211', 'localhost2:11211']
                        }
                    }):

                # Mock the test_memcached function so it always returns
                # True.
                views.test_memcached = lambda host, port: True

                # TODO: Replace when we get a mock library.
                def mock_rabbitmq():
                    class MockRabbitMQ(object):
                        def connect(self):
                            return True
                    return lambda *a, **kw: MockRabbitMQ()
                views.establish_connection = mock_rabbitmq()

                # Request /services/monitor and make sure it returns
                # HTTP 200 and that there aren't errors on the page.
                resp = self.client.get(reverse('services-monitor'))
                errors = [line for line in resp.content.splitlines()
                          if 'ERROR' in line]

                eq_(resp.status_code, 200, '%s != %s (%s)' % (
                    resp.status_code, 200, repr(errors)))

        finally:
            views.test_memcached = test_memcached
Пример #43
0
    def test_with_context_20_pairs(self):
        data = {
            'happy': True,
            'description': u'Great!',
            'product': u'Firefox OS',
            'channel': u'stable',
            'version': u'1.1',
            'platform': u'Firefox OS',
            'locale': 'en-US',
            'email': '*****@*****.**',
        }

        for i in range(25):
            data['foo%02d' % i] = str(i)

        r = self.client.post(reverse('feedback-api'), data)
        eq_(r.status_code, 201)

        context = models.ResponseContext.objects.latest(field_name='id')
        data = sorted(context.data.items())
        eq_(len(data), 20)
        eq_(data[0], ('foo00', '0'))
        eq_(data[-1], ('foo19', '19'))
Пример #44
0
    def test_deprecated_firefox_for_android_minimal(self):
        """Test the minimal post data from FfA works."""
        data = {
            '_type': 1,
            'description': u'This is how to make it better...',
            'device': 'Stone tablet',
            'manufacturer': 'Rosetta'
        }

        ua = 'Mozilla/5.0 (Android; Tablet; rv:24.0) Gecko/24.0 Firefox/24.0'

        r = self.client.post(reverse('feedback'), data, HTTP_USER_AGENT=ua)
        assert r.status_code == 302
        feedback = models.Response.objects.latest(field_name='id')
        assert feedback.happy is True
        assert feedback.url == u''
        assert feedback.description == data['description']

        # This comes from the client.post url.
        assert u'en-US' == feedback.locale
        # Note: This comes from the user agent from the LocalizingClient
        assert u'Firefox for Android' == feedback.product
        assert u'24.0' == feedback.version
Пример #45
0
    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])
Пример #46
0
    def test_country_unknown(self):
        """This is a stopgap fix for handling 'unknown' value for country"""
        survey = SurveyFactory.create()

        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': 'ou812?',
            'variation_id': '1',
            'country': 'unknown'
        }
        resp = self.client.post(reverse('heartbeat-api'),
                                content_type='application/json',
                                data=json.dumps(data))

        assert resp.status_code == 201
        ans = Answer.objects.latest('id')
        assert ans.country == 'UNK'
Пример #47
0
    def test_links(self):
        token = TokenFactory()
        flavor = AlertFlavorFactory(name='Foo', slug='fooflavor')
        flavor.allowed_tokens.add(token)

        alert = AlertFactory(summary=u'alert 1', flavor=flavor)
        link = LinkFactory(alert=alert)

        qs = {'flavors': flavor.slug}
        resp = self.client.get(reverse('alerts-api') + '?' +
                               urllib.urlencode(qs),
                               HTTP_AUTHORIZATION='token ' + token.token)

        eq_(resp.status_code, 200)
        eq_(
            json.loads(resp.content), {
                u'count':
                1,
                u'total':
                1,
                u'alerts': [{
                    u'id': WHATEVER,
                    u'summary': u'alert 1',
                    u'description': u'the account balance is at $5.',
                    u'flavor': flavor.slug,
                    u'emitter_version': 0,
                    u'emitter_name': u'balance-checker',
                    u'start_time': None,
                    u'end_time': None,
                    u'created': WHATEVER,
                    u'severity': 0,
                    u'links': [{
                        u'name': link.name,
                        u'url': link.url
                    }]
                }]
            })
Пример #48
0
    def test_get_suggestions(self):
        url = reverse('feedback', args=(u'firefox', ))
        desc = u'slow browser please speed improve i am wait speed improv 2'

        # Post some basic feedback that meets the SUMO Suggest
        # Provider standards and follow through to the Thank You
        # page. This triggers the suggestions and docs should be
        # in the session.
        resp = self.client.post(url, {
            'happy': 0,
            'description': desc,
        },
                                follow=True)

        feedback_id = self.client.session['response_id']
        session_key = SUMO_SUGGEST_SESSION_KEY.format(feedback_id)

        # Verify we get the right number of docs from the SUMO Suggest
        # API and that the urls start with SUMO_HOST.
        docs = self.client.session[session_key]
        assert 0 < len(docs) <= 3
        for doc in docs:
            assert doc['url'].startswith(SUMO_HOST)

        # Note: Since SUMO content changes, we can't check specific
        # strings since we don't really know what it's going to
        # return.

        links = resp.jinja_context['suggestions']
        assert links[0].provider == 'sumosuggest'
        assert links[0].provider_version == 1

        # Verify that the first link has non-empty summary, url and
        # description.
        assert links[0].summary
        assert links[0].url
        assert links[0].description
Пример #49
0
    def test_empty_tr(self):
        feedback_responses = ResponseFactory.create_batch(5)

        jane = AnalyzerProfileFactory().user
        self.client_login_user(jane)

        data = {
            'locales': [],
            'products': [],
            'versions': [],
            'keywords': [],
            'url_exists': None
        }
        resp = self.client.post(
            reverse('triggerrule-match'),
            content_type='application/json',
            data=json.dumps(data)
        )
        assert resp.status_code == 200
        # Note: This matches everything because it's an empty rule.
        assert (
            [item['id'] for item in json.loads(resp.content)['results']] ==
            [fr.id for fr in reversed(feedback_responses)]
        )
Пример #50
0
    def test_contents(self):
        fr = ResponseFactory()

        jane = AnalyzerProfileFactory().user
        self.client_login_user(jane)

        data = {
            'locales': [],
            'products': [],
            'versions': [],
            'keywords': [],
            'url_exists': None
        }
        resp = self.client.post(
            reverse('triggerrule-match'),
            content_type='application/json',
            data=json.dumps(data)
        )
        assert resp.status_code == 200
        content = json.loads(resp.content)
        assert (
            content['results'] ==
            [
                {
                    u'id': int(fr.id),
                    u'created': fr.created.strftime(u'%Y-%m-%dT%H:%M:%S'),
                    u'description': fr.description,
                    u'happy': fr.happy,
                    u'locale': fr.locale,
                    u'product': fr.product,
                    u'platform': fr.platform,
                    u'url': fr.url,
                    u'version': fr.version
                }
            ]
        )
Пример #51
0
    def test_deprecated_firefox_for_android_minimal(self):
        """Test the minimal post data from FfA works."""
        data = {
            '_type': 1,
            'description': u'This is how to make it better...',
            'device': 'Stone tablet',
            'manufacturer': 'Rosetta'
            }

        ua = 'Mozilla/5.0 (Android; Tablet; rv:24.0) Gecko/24.0 Firefox/24.0'

        r = self.client.post(reverse('feedback'), data, HTTP_USER_AGENT=ua)
        eq_(r.status_code, 302)
        feedback = models.Response.objects.latest(field_name='id')
        eq_(feedback.happy, True)
        eq_(feedback.url, u'')
        eq_(feedback.description, data['description'])

        # This comes from the client.post url.
        eq_(u'en-US', feedback.locale)
        # Note: This comes from the user agent from the LocalizingClient
        eq_(u'Firefox for Android', feedback.product)
        eq_(u'stable', feedback.channel)
        eq_(u'24.0.0', feedback.version)
Пример #52
0
    def test_deprecated_firefox_for_android_sad_is_sad(self):
        data = {
            '_type': 2,
            'description': u'This is how to make it better...',
            'add_url': 1,
            'url': u'http://mozilla.org/',
            'device': 'Stone tablet',
            'manufacturer': 'Rosetta'
        }

        ua = 'Mozilla/5.0 (Android; Tablet; rv:24.0) Gecko/24.0 Firefox/24.0'

        r = self.client.post(reverse('feedback'), data, HTTP_USER_AGENT=ua)
        eq_(r.status_code, 302)
        feedback = models.Response.objects.latest(field_name='id')
        eq_(feedback.happy, False)
        eq_(feedback.url, data['url'])
        eq_(feedback.description, data['description'])

        # This comes from the client.post url.
        eq_(u'en-US', feedback.locale)
        # Note: This comes from the user agent from the LocalizingClient
        eq_(u'Firefox for Android', feedback.product)
        eq_(u'24.0', feedback.version)
Пример #53
0
 def test_firefox_os_view(self):
     """Firefox OS returns correct view"""
     # Specifying fxos as the product in the url
     url = reverse('feedback', args=(u'fxos', ))
     r = self.client.get(url)
     assert template_used(r, 'feedback/fxos_feedback.html')
Пример #54
0
 def test_android_view(self):
     """Android returns correct view"""
     url = reverse('feedback', args=(u'android', ))
     r = self.client.get(url)
     assert template_used(r, 'feedback/android_feedback.html')
Пример #55
0
 def test_text_search_unicode(self):
     """Unicode in the search field shouldn't kick up errors"""
     url = reverse('dashboard')
     # Text search
     r = self.client.get(url, {'q': u'\u2713'})
     eq_(r.status_code, 200)
Пример #56
0
 def test_frontpage_index_missing(self):
     """If index is missing, show es_down template."""
     self.teardown_indexes()
     resp = self.client.get(reverse('dashboard'))
     self.assertTemplateUsed(resp, 'analytics/es_down.html')
Пример #57
0
 def test_sad_redirect(self):
     r = self.client.get(reverse('sad-redirect'))
     self.assertRedirects(r, reverse('feedback') + '?happy=0')
Пример #58
0
 def test_happy_redirect(self):
     r = self.client.get(reverse('happy-redirect'))
     self.assertRedirects(r, reverse('feedback') + '?happy=1')
Пример #59
0
    def test_picker_no_products(self):
        resp = self.client.get(reverse('feedback'))

        assert resp.status_code == 200
        assert template_used(resp, 'feedback/picker.html')
        assert 'No products available.' in resp.content
Пример #60
0
    def test_picker_no_products(self):
        resp = self.client.get(reverse('feedback'))

        eq_(resp.status_code, 200)
        self.assertTemplateUsed(resp, 'feedback/picker.html')
        assert 'No products available.' in resp.content