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, [])
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)
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'))
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()
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)
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, })
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)
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])
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']
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/')
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.'))
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)
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)
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')
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)
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"))
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)
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)
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
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])
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')
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))
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'))
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)
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)
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)
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)
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)
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)
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