def post(self, **kw): self.form = ThemeForm(self.get_dict(**kw), request=self.request) return self.form
class TestThemeForm(amo.tests.TestCase): fixtures = ['base/user_2519'] def setUp(self): self.populate() self.request = mock.Mock() self.request.groups = () self.request.amo_user = mock.Mock() self.request.amo_user.is_authenticated.return_value = True def populate(self): self.cat = Category.objects.create(application=amo.FIREFOX.id, type=amo.ADDON_PERSONA, name='xxxx') License.objects.create(id=amo.LICENSE_CC_BY.id) def get_dict(self, **kw): data = { 'name': 'new name', 'slug': 'special-slug', 'category': self.cat.id, 'accentcolor': '#003366', 'textcolor': '#C0FFEE', 'description': 'new description', 'tags': 'tag1, tag2, tag3', 'license': amo.LICENSE_CC_BY.id, 'agreed': True, 'header_hash': 'b4ll1n', 'footer_hash': '5w4g' } data.update(**kw) return data def post(self, **kw): self.form = ThemeForm(self.get_dict(**kw), request=self.request) return self.form def test_name_unique(self): # A theme cannot share the same name as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, name='harry-potter') for name in ('Harry-Potter', ' harry-potter ', 'harry-potter'): self.post(name=name) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['This name is already in use. ' 'Please choose another.']}) def test_name_required(self): self.post(name='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['This field is required.']}) def test_name_length(self): self.post(name='a' * 51) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['Ensure this value has at most ' '50 characters (it has 51).']}) def test_slug_unique(self): # A theme cannot share the same slug as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, slug='harry-potter') for slug in ('Harry-Potter', ' harry-potter ', 'harry-potter'): self.post(slug=slug) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['This slug is already in use. ' 'Please choose another.']}) def test_slug_required(self): self.post(slug='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['This field is required.']}) def test_slug_length(self): self.post(slug='a' * 31) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['Ensure this value has at most ' '30 characters (it has 31).']}) def test_description_optional(self): self.post(description='') eq_(self.form.is_valid(), True, self.form.errors) def test_description_length(self): self.post(description='a' * 501) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'description': ['Ensure this value has at most ' '500 characters (it has 501).']}) def test_categories_required(self): self.post(category='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'category': ['This field is required.']}) def test_license_required(self): self.post(license='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'license': ['A license must be selected.']}) def test_header_hash_required(self): self.post(header_hash='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'header_hash': ['This field is required.']}) def test_footer_hash_required(self): self.post(footer_hash='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'footer_hash': ['This field is required.']}) def test_accentcolor_optional(self): self.post(accentcolor='') eq_(self.form.is_valid(), True, self.form.errors) def test_accentcolor_invalid(self): self.post(accentcolor='#BALLIN') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'accentcolor': ['This must be a valid hex color code, ' 'such as #000000.']}) def test_textcolor_optional(self): self.post(textcolor='') eq_(self.form.is_valid(), True, self.form.errors) def test_textcolor_invalid(self): self.post(textcolor='#BALLIN') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'textcolor': ['This must be a valid hex color code, ' 'such as #000000.']}) def get_img_urls(self): return ( reverse('devhub.personas.upload_persona', args=['persona_header']), reverse('devhub.personas.upload_persona', args=['persona_footer']) ) def test_img_attrs(self): header_url, footer_url = self.get_img_urls() self.post() eq_(self.form.fields['header'].widget.attrs, {'data-allowed-types': 'image/jpeg|image/png', 'data-upload-url': header_url}) eq_(self.form.fields['footer'].widget.attrs, {'data-allowed-types': 'image/jpeg|image/png', 'data-upload-url': footer_url}) @mock.patch('addons.tasks.make_checksum') @mock.patch('addons.tasks.create_persona_preview_images') @mock.patch('addons.tasks.save_persona_image') def test_success(self, save_persona_image_mock, create_persona_preview_images_mock, make_checksum_mock): if not hasattr(Image.core, 'jpeg_encoder'): raise SkipTest make_checksum_mock.return_value = 'hashyourselfbeforeyoucrashyourself' self.request.amo_user = UserProfile.objects.get(pk=2519) data = self.get_dict() header_url, footer_url = self.get_img_urls() # Upload header image. img = open(get_image_path('persona-header.jpg'), 'rb') r_ajax = self.client.post(header_url, {'upload_image': img}) data.update(header_hash=json.loads(r_ajax.content)['upload_hash']) # Upload footer image. img = open(get_image_path('persona-footer.jpg'), 'rb') r_ajax = self.client.post(footer_url, {'upload_image': img}) data.update(footer_hash=json.loads(r_ajax.content)['upload_hash']) # Populate and save form. self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() addon = Addon.objects.filter(type=amo.ADDON_PERSONA).order_by('-id')[0] persona = addon.persona # Test for correct Addon and Persona values. eq_(unicode(addon.name), data['name']) eq_(addon.slug, data['slug']) self.assertSetEqual(addon.categories.values_list('id', flat=True), [self.cat.id]) self.assertSetEqual(addon.tags.values_list('tag_text', flat=True), data['tags'].split(', ')) eq_(persona.persona_id, 0) eq_(persona.license, data['license']) eq_(persona.accentcolor, data['accentcolor'].lstrip('#')) eq_(persona.textcolor, data['textcolor'].lstrip('#')) eq_(persona.author, self.request.amo_user.username) eq_(persona.display_username, self.request.amo_user.name) assert not persona.dupe_persona v = addon.versions.all() eq_(len(v), 1) eq_(v[0].version, '0') # Test for header, footer, and preview images. dst = os.path.join(user_media_path('addons'), str(addon.id)) header_src = os.path.join(settings.TMP_PATH, 'persona_header', u'b4ll1n') footer_src = os.path.join(settings.TMP_PATH, 'persona_footer', u'5w4g') eq_(save_persona_image_mock.mock_calls, [mock.call(src=header_src, full_dst=os.path.join(dst, 'header.png')), mock.call(src=footer_src, full_dst=os.path.join(dst, 'footer.png'))]) create_persona_preview_images_mock.assert_called_with( src=header_src, full_dst=[os.path.join(dst, 'preview.png'), os.path.join(dst, 'icon.png')], set_modified_on=[addon]) @mock.patch('addons.tasks.create_persona_preview_images') @mock.patch('addons.tasks.save_persona_image') @mock.patch('addons.tasks.make_checksum') def test_dupe_persona(self, make_checksum_mock, mock1, mock2): """ Submitting persona with checksum already in db should be marked duplicate. """ make_checksum_mock.return_value = 'cornhash' self.request.amo_user = UserProfile.objects.get(pk=2519) self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() self.post(name='whatsinaname', slug='metalslug') eq_(self.form.is_valid(), True, self.form.errors) self.form.save() personas = Persona.objects.order_by('addon__name') eq_(personas[0].checksum, personas[1].checksum) eq_(personas[1].dupe_persona, personas[0]) eq_(personas[0].dupe_persona, None)
class TestThemeForm(amo.tests.TestCase): fixtures = ['base/user_2519'] def setUp(self): super(TestThemeForm, self).setUp() self.populate() self.request = mock.Mock() self.request.groups = () self.request.user = mock.Mock() self.request.user.is_authenticated.return_value = True def populate(self): self.cat = Category.objects.create(application=amo.FIREFOX.id, type=amo.ADDON_PERSONA, name='xxxx') License.objects.create(id=amo.LICENSE_CC_BY.id) def get_dict(self, **kw): data = { 'name': 'new name', 'slug': 'special-slug', 'category': self.cat.id, 'accentcolor': '#003366', 'textcolor': '#C0FFEE', 'description': 'new description', 'tags': 'tag1, tag2, tag3', 'license': amo.LICENSE_CC_BY.id, 'agreed': True, 'header_hash': 'b4ll1n', 'footer_hash': '5w4g' } data.update(**kw) return data def post(self, **kw): self.form = ThemeForm(self.get_dict(**kw), request=self.request) return self.form def test_name_unique(self): # A theme cannot share the same name as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, name='harry-potter') for name in ('Harry-Potter', ' harry-potter ', 'harry-potter'): self.post(name=name) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['This name is already in use. ' 'Please choose another.']}) def test_name_required(self): self.post(name='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['This field is required.']}) def test_name_length(self): self.post(name='a' * 51) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'name': ['Ensure this value has at most ' '50 characters (it has 51).']}) def test_slug_unique(self): # A theme cannot share the same slug as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, slug='harry-potter') for slug in ('Harry-Potter', ' harry-potter ', 'harry-potter'): self.post(slug=slug) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['This slug is already in use. ' 'Please choose another.']}) def test_slug_required(self): self.post(slug='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['This field is required.']}) def test_slug_length(self): self.post(slug='a' * 31) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'slug': ['Ensure this value has at most ' '30 characters (it has 31).']}) def test_description_optional(self): self.post(description='') eq_(self.form.is_valid(), True, self.form.errors) def test_description_length(self): self.post(description='a' * 501) eq_(self.form.is_valid(), False) eq_(self.form.errors, {'description': ['Ensure this value has at most ' '500 characters (it has 501).']}) def test_categories_required(self): self.post(category='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'category': ['This field is required.']}) def test_license_required(self): self.post(license='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'license': ['A license must be selected.']}) def test_header_hash_required(self): self.post(header_hash='') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'header_hash': ['This field is required.']}) def test_footer_hash_optional(self): self.post(footer_hash='') eq_(self.form.is_valid(), True, self.form.errors) def test_accentcolor_optional(self): self.post(accentcolor='') eq_(self.form.is_valid(), True, self.form.errors) def test_accentcolor_invalid(self): self.post(accentcolor='#BALLIN') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'accentcolor': ['This must be a valid hex color code, ' 'such as #000000.']}) def test_textcolor_optional(self): self.post(textcolor='') eq_(self.form.is_valid(), True, self.form.errors) def test_textcolor_invalid(self): self.post(textcolor='#BALLIN') eq_(self.form.is_valid(), False) eq_(self.form.errors, {'textcolor': ['This must be a valid hex color code, ' 'such as #000000.']}) def get_img_urls(self): return ( reverse('devhub.personas.upload_persona', args=['persona_header']), reverse('devhub.personas.upload_persona', args=['persona_footer']) ) def test_img_attrs(self): header_url, footer_url = self.get_img_urls() self.post() eq_(self.form.fields['header'].widget.attrs, {'data-allowed-types': 'image/jpeg|image/png', 'data-upload-url': header_url}) eq_(self.form.fields['footer'].widget.attrs, {'data-allowed-types': 'image/jpeg|image/png', 'data-upload-url': footer_url}) @mock.patch('addons.tasks.make_checksum') @mock.patch('addons.tasks.create_persona_preview_images') @mock.patch('addons.tasks.save_persona_image') def test_success(self, save_persona_image_mock, create_persona_preview_images_mock, make_checksum_mock): if not hasattr(Image.core, 'jpeg_encoder'): raise SkipTest make_checksum_mock.return_value = 'hashyourselfbeforeyoucrashyourself' self.request.user = UserProfile.objects.get(pk=2519) data = self.get_dict() header_url, footer_url = self.get_img_urls() # Upload header image. img = open(get_image_path('persona-header.jpg'), 'rb') r_ajax = self.client.post(header_url, {'upload_image': img}) data.update(header_hash=json.loads(r_ajax.content)['upload_hash']) # Upload footer image. img = open(get_image_path('persona-footer.jpg'), 'rb') r_ajax = self.client.post(footer_url, {'upload_image': img}) data.update(footer_hash=json.loads(r_ajax.content)['upload_hash']) # Populate and save form. self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() addon = Addon.objects.filter(type=amo.ADDON_PERSONA).order_by('-id')[0] persona = addon.persona # Test for correct Addon and Persona values. eq_(unicode(addon.name), data['name']) eq_(addon.slug, data['slug']) self.assertSetEqual(addon.categories.values_list('id', flat=True), [self.cat.id]) self.assertSetEqual(addon.tags.values_list('tag_text', flat=True), data['tags'].split(', ')) eq_(persona.persona_id, 0) eq_(persona.license, data['license']) eq_(persona.accentcolor, data['accentcolor'].lstrip('#')) eq_(persona.textcolor, data['textcolor'].lstrip('#')) eq_(persona.author, self.request.user.username) eq_(persona.display_username, self.request.user.name) assert not persona.dupe_persona v = addon.versions.all() eq_(len(v), 1) eq_(v[0].version, '0') # Test for header, footer, and preview images. dst = os.path.join(user_media_path('addons'), str(addon.id)) header_src = os.path.join(settings.TMP_PATH, 'persona_header', u'b4ll1n') footer_src = os.path.join(settings.TMP_PATH, 'persona_footer', u'5w4g') eq_(save_persona_image_mock.mock_calls, [mock.call(src=header_src, full_dst=os.path.join(dst, 'header.png')), mock.call(src=footer_src, full_dst=os.path.join(dst, 'footer.png'))]) create_persona_preview_images_mock.assert_called_with( src=header_src, full_dst=[os.path.join(dst, 'preview.png'), os.path.join(dst, 'icon.png')], set_modified_on=[addon]) @mock.patch('addons.tasks.create_persona_preview_images') @mock.patch('addons.tasks.save_persona_image') @mock.patch('addons.tasks.make_checksum') def test_dupe_persona(self, make_checksum_mock, mock1, mock2): """ Submitting persona with checksum already in db should be marked duplicate. """ make_checksum_mock.return_value = 'cornhash' self.request.user = UserProfile.objects.get(pk=2519) self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() self.post(name='whatsinaname', slug='metalslug') eq_(self.form.is_valid(), True, self.form.errors) self.form.save() personas = Persona.objects.order_by('addon__name') eq_(personas[0].checksum, personas[1].checksum) eq_(personas[1].dupe_persona, personas[0]) eq_(personas[0].dupe_persona, None)
class TestThemeForm(amo.tests.TestCase): fixtures = ["base/user_2519"] def setUp(self): self.populate() self.request = mock.Mock() self.request.groups = () self.request.amo_user = mock.Mock() self.request.amo_user.is_authenticated.return_value = True def populate(self): self.cat = Category.objects.create(application=amo.FIREFOX.id, type=amo.ADDON_PERSONA, name="xxxx") License.objects.create(id=amo.LICENSE_CC_BY.id) def get_dict(self, **kw): data = { "name": "new name", "slug": "special-slug", "category": self.cat.id, "accentcolor": "#003366", "textcolor": "#C0FFEE", "description": "new description", "tags": "tag1, tag2, tag3", "license": amo.LICENSE_CC_BY.id, "agreed": True, "header_hash": "b4ll1n", "footer_hash": "5w4g", } data.update(**kw) return data def post(self, **kw): self.form = ThemeForm(self.get_dict(**kw), request=self.request) return self.form def test_name_unique(self): # A theme cannot share the same name as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, name="harry-potter") for name in ("Harry-Potter", " harry-potter ", "harry-potter"): self.post(name=name) eq_(self.form.is_valid(), False) eq_(self.form.errors, {"name": ["This name is already in use. " "Please choose another."]}) def test_name_required(self): self.post(name="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"name": ["This field is required."]}) def test_name_length(self): self.post(name="a" * 51) eq_(self.form.is_valid(), False) eq_(self.form.errors, {"name": ["Ensure this value has at most " "50 characters (it has 51)."]}) def test_slug_unique(self): # A theme cannot share the same slug as another theme's. Addon.objects.create(type=amo.ADDON_PERSONA, slug="harry-potter") for slug in ("Harry-Potter", " harry-potter ", "harry-potter"): self.post(slug=slug) eq_(self.form.is_valid(), False) eq_(self.form.errors, {"slug": ["This slug is already in use. " "Please choose another."]}) def test_slug_required(self): self.post(slug="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"slug": ["This field is required."]}) def test_slug_length(self): self.post(slug="a" * 31) eq_(self.form.is_valid(), False) eq_(self.form.errors, {"slug": ["Ensure this value has at most " "30 characters (it has 31)."]}) def test_description_optional(self): self.post(description="") eq_(self.form.is_valid(), True, self.form.errors) def test_description_length(self): self.post(description="a" * 501) eq_(self.form.is_valid(), False) eq_(self.form.errors, {"description": ["Ensure this value has at most " "500 characters (it has 501)."]}) def test_categories_required(self): self.post(category="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"category": ["This field is required."]}) def test_license_required(self): self.post(license="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"license": ["A license must be selected."]}) def test_header_hash_required(self): self.post(header_hash="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"header_hash": ["This field is required."]}) def test_footer_hash_required(self): self.post(footer_hash="") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"footer_hash": ["This field is required."]}) def test_accentcolor_optional(self): self.post(accentcolor="") eq_(self.form.is_valid(), True, self.form.errors) def test_accentcolor_invalid(self): self.post(accentcolor="#BALLIN") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"accentcolor": ["This must be a valid hex color code, " "such as #000000."]}) def test_textcolor_optional(self): self.post(textcolor="") eq_(self.form.is_valid(), True, self.form.errors) def test_textcolor_invalid(self): self.post(textcolor="#BALLIN") eq_(self.form.is_valid(), False) eq_(self.form.errors, {"textcolor": ["This must be a valid hex color code, " "such as #000000."]}) def get_img_urls(self): return ( reverse("devhub.personas.upload_persona", args=["persona_header"]), reverse("devhub.personas.upload_persona", args=["persona_footer"]), ) def test_img_attrs(self): header_url, footer_url = self.get_img_urls() self.post() eq_( self.form.fields["header"].widget.attrs, {"data-allowed-types": "image/jpeg|image/png", "data-upload-url": header_url}, ) eq_( self.form.fields["footer"].widget.attrs, {"data-allowed-types": "image/jpeg|image/png", "data-upload-url": footer_url}, ) @mock.patch("addons.tasks.make_checksum") @mock.patch("addons.tasks.create_persona_preview_images") @mock.patch("addons.tasks.save_persona_image") def test_success(self, save_persona_image_mock, create_persona_preview_images_mock, make_checksum_mock): if not hasattr(Image.core, "jpeg_encoder"): raise SkipTest make_checksum_mock.return_value = "hashyourselfbeforeyoucrashyourself" self.request.amo_user = UserProfile.objects.get(pk=2519) data = self.get_dict() header_url, footer_url = self.get_img_urls() # Upload header image. img = open(get_image_path("persona-header.jpg"), "rb") r_ajax = self.client.post(header_url, {"upload_image": img}) data.update(header_hash=json.loads(r_ajax.content)["upload_hash"]) # Upload footer image. img = open(get_image_path("persona-footer.jpg"), "rb") r_ajax = self.client.post(footer_url, {"upload_image": img}) data.update(footer_hash=json.loads(r_ajax.content)["upload_hash"]) # Populate and save form. self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() addon = Addon.objects.filter(type=amo.ADDON_PERSONA).order_by("-id")[0] persona = addon.persona # Test for correct Addon and Persona values. eq_(unicode(addon.name), data["name"]) eq_(addon.slug, data["slug"]) self.assertSetEqual(addon.categories.values_list("id", flat=True), [self.cat.id]) self.assertSetEqual(addon.tags.values_list("tag_text", flat=True), data["tags"].split(", ")) eq_(persona.persona_id, 0) eq_(persona.license, data["license"]) eq_(persona.accentcolor, data["accentcolor"].lstrip("#")) eq_(persona.textcolor, data["textcolor"].lstrip("#")) eq_(persona.author, self.request.amo_user.username) eq_(persona.display_username, self.request.amo_user.name) assert not persona.dupe_persona v = addon.versions.all() eq_(len(v), 1) eq_(v[0].version, "0") # Test for header, footer, and preview images. dst = os.path.join(user_media_path("addons"), str(addon.id)) header_src = os.path.join(settings.TMP_PATH, "persona_header", u"b4ll1n") footer_src = os.path.join(settings.TMP_PATH, "persona_footer", u"5w4g") eq_( save_persona_image_mock.mock_calls, [ mock.call(src=header_src, full_dst=os.path.join(dst, "header.png")), mock.call(src=footer_src, full_dst=os.path.join(dst, "footer.png")), ], ) create_persona_preview_images_mock.assert_called_with( src=header_src, full_dst=[os.path.join(dst, "preview.png"), os.path.join(dst, "icon.png")], set_modified_on=[addon], ) @mock.patch("addons.tasks.create_persona_preview_images") @mock.patch("addons.tasks.save_persona_image") @mock.patch("addons.tasks.make_checksum") def test_dupe_persona(self, make_checksum_mock, mock1, mock2): """ Submitting persona with checksum already in db should be marked duplicate. """ make_checksum_mock.return_value = "cornhash" self.request.amo_user = UserProfile.objects.get(pk=2519) self.post() eq_(self.form.is_valid(), True, self.form.errors) self.form.save() self.post(name="whatsinaname", slug="metalslug") eq_(self.form.is_valid(), True, self.form.errors) self.form.save() personas = Persona.objects.order_by("addon__name") eq_(personas[0].checksum, personas[1].checksum) eq_(personas[1].dupe_persona, personas[0]) eq_(personas[0].dupe_persona, None)