def test_update_item(self): """ Update an item on an shopcart """ # create a known item shopcart = self._create_shopcarts(1)[0] item = ItemFactory() resp = self.app.post("/shopcarts/{}/items".format(shopcart.id), json=item.serialize(), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_201_CREATED) data = resp.get_json() logging.debug(data) item_id = data["id"] data["item_name"] = "XXXX" # send the update back resp = self.app.put("/shopcarts/{}/items/{}".format( shopcart.id, item_id), json=data, content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_200_OK) # retrieve it back resp = self.app.get("/shopcarts/{}/items/{}".format( shopcart.id, item_id), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_200_OK) data = resp.get_json() logging.debug(data) self.assertEqual(data["id"], item_id) self.assertEqual(data["shopcart_id"], shopcart.id) self.assertEqual(data["item_name"], "XXXX")
def test_simple_change(self): item = ItemFactory(name="Not name") # Load the Change Item Page ItemAdmin.confirm_change = True response = self.client.get(f"/admin/market/item/{item.id}/change/") # Should be asked for confirmation self.assertTrue(response.context_data.get("confirm_change")) self.assertIn("_confirm_change", response.rendered_content) # Click "Save And Continue" data = { "id": item.id, "name": "name", "price": 2.0, "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_continue": True, } response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should be shown confirmation page self._assertSubmitHtml( rendered_content=response.rendered_content, save_action="_continue", multipart_form=True, ) # Should have cached the unsaved item cached_item = cache.get(CACHE_KEYS["object"]) self.assertIsNotNone(cached_item) # Should not have saved the changes yet self.assertEqual(Item.objects.count(), 1) item.refresh_from_db() self.assertEqual(item.name, "Not name") # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should not have redirected to changelist self.assertEqual(response.url, f"/admin/market/item/{item.id}/change/") # Should have saved item self.assertEqual(Item.objects.count(), 1) saved_item = Item.objects.all().first() self.assertEqual(saved_item.name, data["name"]) self.assertEqual(saved_item.price, data["price"]) self.assertEqual(saved_item.currency, data["currency"]) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key))
def test_ex2_list_v2_items_db_queries(client, django_assert_num_queries): ItemFactory.create_batch(10) # Two queries # COUNT # SELECT with django_assert_num_queries(2): response = client.get('/api/v2/inventory/items/') assert response.status_code == 200
def test_checkout_shopcart(self): """ Checkout a Shopcart REAL """ shopcart = self._create_shopcarts(1)[0] item = ItemFactory() resp = self.app.post("/shopcarts/{}/items".format(shopcart.id), json=item.serialize(), content_type=CONTENT_TYPE_JSON) self.assertEqual(resp.status_code, status.HTTP_201_CREATED) resp2 = self.app.put("/shopcarts/{}".format(shopcart.id), json=item.serialize(), content_type=CONTENT_TYPE_JSON) self.assertEqual(resp2.status_code, status.HTTP_204_NO_CONTENT)
def test_add_item(self): """ Add an item to a shopcart """ shopcart = self._create_shopcarts(1)[0] item = ItemFactory() resp = self.app.post("/shopcarts/{}/items".format(shopcart.id), json=item.serialize(), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_201_CREATED) data = resp.get_json() logging.debug(data) self.assertEqual(data["shopcart_id"], shopcart.id) self.assertIsNotNone(data["id"]) self.assertEqual(data["item_name"], item.item_name) self.assertEqual(data["item_quantity"], item.item_quantity) self.assertEqual(data["item_price"], item.item_price)
def test_delete_shopcart(self): """ Delete a shopcart """ shopcart = self._create_shopcarts(1)[0] item = ItemFactory() resp = self.app.post("/shopcarts/{}/items".format(shopcart.id), json=item.serialize(), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_201_CREATED) data = resp.get_json() logging.debug(data) item_id = data["id"] # send delete request resp = self.app.delete("/shopcarts/{}".format(shopcart.id), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
def test_cannot_confirm_for_models_with_validator_on_model_field_if_validator_fails( self, ): # ItemSale.currency has a validator on it shop = ShopFactory() item = ItemFactory() InventoryFactory(shop=shop, item=item, quantity=10) transaction = TransactionFactory(shop=shop) data = { "transaction": transaction.id, "item": item.id, "quantity": 1, "currency": "FAKE", "total": 10.00, "_confirm_add": True, "_save": True, } response = self.client.post(reverse("admin:market_itemsale_add"), data) # Should show form with error and not confirmation page self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/itemsale/change_form.html", "admin/market/change_form.html", "admin/change_form.html", ] self.assertEqual(response.template_name, expected_templates) self.assertEqual(ItemSale.objects.count(), 0) self.assertIn("error", str(response.rendered_content)) self.assertIn("Invalid Currency", str(response.rendered_content)) # Should still ask for confirmation self.assertIn(CONFIRM_ADD, response.rendered_content)
def test_post_add_with_confirm_add(self): item = ItemFactory() shop = ShopFactory() data = { "shop": shop.id, "item": item.id, "quantity": 5, "_confirm_add": True, "_continue": True, } response = self.client.post(reverse("admin:market_inventory_add"), data) # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/inventory/change_confirmation.html", "admin/market/change_confirmation.html", "admin/change_confirmation.html", ] self.assertEqual(response.template_name, expected_templates) form_data = {"shop": str(shop.id), "item": str(item.id), "quantity": str(5)} self._assertSimpleFieldFormHtml( rendered_content=response.rendered_content, fields=form_data ) self._assertSubmitHtml( rendered_content=response.rendered_content, save_action="_continue" ) # Should not have been added yet self.assertEqual(Inventory.objects.count(), 0)
def test_all_item_attributes_in_xml_string(): item = ItemFactory() xml_string = object_to_xml_string(item).decode("UTF-8") for key in item.__dict__.keys(): assert key in xml_string assert isinstance(item.image, list) for key in item.image[0].__dict__.keys(): assert key in xml_string assert isinstance(item.extralink, list) for key in item.extralink[0].__dict__.keys(): assert key in xml_string assert isinstance(item.text, list) for key in item.text[0].__dict__.keys(): assert key in xml_string assert isinstance(item.coordinate, list) for key in item.coordinate[0].__dict__.keys(): assert key in xml_string assert isinstance(item.scontact, list) for key in item.scontact[0].__dict__.keys(): assert key in xml_string
def item_data(): item = ItemFactory.build() return { "external_id": item.external_id, "name": item.name, "value": item.value, }
def test_validate_xml_against_dtd(): # DTD downloaded from http://img.cromet.fi/dtds/transferdata.dtd path_to_current_file = os.path.realpath(__file__) current_directory = os.path.dirname(path_to_current_file) dtd = etree.DTD( os.path.join(current_directory, "test_data", "transferdata.dtd")) items = ItemFactory.create_batch(2) assert dtd.validate(create_element_tree(items))
def test_get_item_list(self): """ Get an item from a shopcart """ # create a known item shopcart = self._create_shopcarts(1)[0] item = ItemFactory() resp = self.app.post("/shopcarts/{}/items".format(shopcart.id), json=item.serialize(), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_201_CREATED) data = resp.get_json() logging.debug(data) shopcart_id = data["id"] # retrieve it back resp = self.app.get("/shopcarts/{}/items".format(shopcart.id), content_type="application/json") self.assertEqual(resp.status_code, status.HTTP_200_OK) data = resp.get_json() logging.debug(data)
def setUp(self): # Load the Change Item Page ItemAdmin.confirm_change = True ItemAdmin.fields = ["name", "price", "file", "image", "currency"] ItemAdmin.save_as = True ItemAdmin.save_as_continue = True self.image_path = "screenshot.png" f = SimpleUploadedFile( name="test_file.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) i = SimpleUploadedFile( name="test_image.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) self.item = ItemFactory(name="Not name", file=f, image=i) return super().setUp()
def test_cannot_confirm_for_models_with_clean_overridden_if_clean_fails( self): shop = ShopFactory() item = ItemFactory() InventoryFactory(shop=shop, item=item, quantity=1) transaction = TransactionFactory(shop=shop) # Asking to buy more than the shop has in stock data = { "transaction": transaction.id, "item": item.id, "quantity": 9, "currency": "USD", "total": 10.00, "_confirm_add": True, "_save": True, } response = self.client.post(reverse("admin:market_itemsale_add"), data) # Should not have been added yet self.assertEqual(ItemSale.objects.count(), 0) # Ensure it shows the form and not the confirmation page self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/itemsale/change_form.html", "admin/market/change_form.html", "admin/change_form.html", ] self.assertEqual(response.template_name, expected_templates) self.assertTrue("error" in str(response.content)) self.assertTrue("Shop does not have enough of the item stocked" in str( response.content)) # Should still be asking for confirmation self.assertIn(CONFIRM_ADD, response.rendered_content) # Fix the issue by buying only what shop has in stock data["quantity"] = 1 # _confirm_add would still be in the POST data response = self.client.post(reverse("admin:market_itemsale_add"), data) # Should show confirmation page # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/itemsale/change_confirmation.html", "admin/market/change_confirmation.html", "admin/change_confirmation.html", ] self.assertEqual(response.template_name, expected_templates) self._assertSubmitHtml(rendered_content=response.rendered_content)
def test_no_add_permissions(self): user = User.objects.create_user(username="******", is_staff=True) self.client.force_login(user) item = ItemFactory() shop = ShopFactory() data = {"shop": shop.id, "item": item.id, "quantity": 5, "_confirm_add": True} response = self.client.post(reverse("admin:market_inventory_add"), data) # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 403) self.assertTrue(isinstance(response, HttpResponseForbidden)) # Should not have been added self.assertEqual(Inventory.objects.count(), 0)
def test_post_change_with_confirm_change(self): item = ItemFactory(name="item") data = { "name": "name", "price": 2.0, "currency": Item.VALID_CURRENCIES[0], "id": item.id, "_confirm_change": True, "csrfmiddlewaretoken": "fake token", "_save": True, } response = self.client.post(f"/admin/market/item/{item.id}/change/", data) # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/item/change_confirmation.html", "admin/market/change_confirmation.html", "admin/change_confirmation.html", ] self.assertEqual(response.template_name, expected_templates) form_data = { "name": "name", "price": str(2.0), # "id": str(item.id), "currency": Item.VALID_CURRENCIES[0][0], } self._assertSimpleFieldFormHtml( rendered_content=response.rendered_content, fields=form_data ) self._assertSubmitHtml( rendered_content=response.rendered_content, multipart_form=True ) # Hasn't changed item yet item.refresh_from_db() self.assertEqual(item.name, "item")
def main(num_manufacturers, num_items_per_man, num_orders): mans = ManufacturerFactory.create_batch(num_manufacturers) print(f"Created {num_manufacturers} Manufacturers") items = list( chain.from_iterable([ ItemFactory.create_batch(num_items_per_man, manufacturer=man) for man in mans ])) print(f"Created {len(items)} Items") users = UserFactory.create_batch(50) for _ in range(0, num_orders): num_items = random.randint(5, 20) user = random.choice(users) OrderFactory.create(user=user, items=random.sample(items, num_items)) print(f"Created {num_orders} Orders")
def test_can_confirm_for_models_with_validator_on_model_field( self, _mock_clean): # ItemSale.currency has a validator on it item = ItemFactory() transaction = TransactionFactory() data = { "transaction": transaction.id, "item": item.id, "quantity": 1, "currency": "USD", "total": 10.00, "_confirm_add": True, "_save": True, } response = self.client.post(reverse("admin:market_itemsale_add"), data) # Should not have been added yet self.assertEqual(ItemSale.objects.count(), 0) # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 200) expected_templates = [ "admin/market/itemsale/change_confirmation.html", "admin/market/change_confirmation.html", "admin/change_confirmation.html", ] self.assertEqual(response.template_name, expected_templates) self._assertSubmitHtml(rendered_content=response.rendered_content) # Confirmation page would not have the _confirm_add sent on submit del data["_confirm_add"] # Selecting to "Yes, I'm sure" on the confirmation page # Would post to the same endpoint response = self.client.post(reverse("admin:market_itemsale_add"), data) self.assertEqual(response.status_code, 302) self.assertEqual(response.url, "/admin/market/itemsale/") self.assertEqual(ItemSale.objects.count(), 1) # Ensure that the date and timestamp saved correctly item_sale = ItemSale.objects.first() self.assertEqual(item_sale.transaction, transaction) self.assertEqual(item_sale.item, item) self.assertEqual(item_sale.currency, "USD")
def test_update_existing_item(api_client, item_data): # GIVEN cart = CartFactory.create() item = ItemFactory.create(cart=cart) api_client.cookies[SESSION_COOKIE_KEY] = cart.pk # WHEN response = api_client.post( reverse("item-create"), data={ "external_id": item.external_id, "name": item_data["name"], }, ) # THEN assert Item.objects.get( external_id=item.external_id).name == item_data["name"] assert response.status_code == status.HTTP_204_NO_CONTENT
def test_confirmation_fields_set_with_confirm_add(self): self.assertEqual(InventoryAdmin.confirmation_fields, ["quantity"]) item = ItemFactory() shop = ShopFactory() # Don't set quantity - let it default data = {"shop": shop.id, "item": item.id, "_confirm_add": True} response = self.client.post(reverse("admin:market_inventory_add"), data) # No confirmation needed self.assertEqual(response.status_code, 302) # Should have been added self.assertEqual(Inventory.objects.count(), 1) new_inventory = Inventory.objects.all().first() self.assertEqual(new_inventory.shop, shop) self.assertEqual(new_inventory.item, item) self.assertEqual( new_inventory.quantity, Inventory._meta.get_field("quantity").default )
def test_handles_to_field_not_allowed(self): item = ItemFactory() shop = ShopFactory() data = { "shop": shop.id, "item": item.id, "quantity": 5, "_confirm_add": True, TO_FIELD_VAR: "shop", } response = self.client.post(reverse("admin:market_inventory_add"), data) # Ensure not redirected (confirmation page does not redirect) self.assertEqual(response.status_code, 400) self.assertTrue(isinstance(response, HttpResponseBadRequest)) self.assertEqual(response.reason_phrase, "Bad Request") self.assertEqual( response.context.get("exception_value"), "The field shop cannot be referenced.", ) # Should not have been added self.assertEqual(Inventory.objects.count(), 0)
def test_fieldsets(client, method, get_fieldset, action): reload(item_admin) admin = item_admin.ItemAdmin fs = get_fieldset(admin) # set fieldsets via one of the methods method(admin, fs) admin_instance = admin(admin_site=AdminSite(), model=Item) request = RequestFactory().request assert admin_instance.get_fieldsets(request) == fs user = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") client.force_login(user) url = "/admin/market/item/add/" image_path = "screenshot.png" f2 = SimpleUploadedFile( name="new_file.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) i2 = SimpleUploadedFile( name="new_image.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) data = { "name": "new name", "price": 2, "currency": "USD", "image": i2, "file": f2, action: True, "_save": True, } for f in admin.readonly_fields: if f in data.keys(): del data[f] if action == CONFIRM_CHANGE: url = "/admin/market/item/1/change/" f = SimpleUploadedFile( name="old_file.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) i = SimpleUploadedFile( name="old_image.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) item = ItemFactory(name="old name", price=1, currency="CAD", file=f, image=i) data["id"] = item.id cache_item = Item() for f in ["name", "price", "currency", "image", "file"]: if f not in admin.readonly_fields: setattr(cache_item, f, data[f]) cache.set(CACHE_KEYS["object"], cache_item) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data[action] data[CONFIRMATION_RECEIVED] = True response = client.post(url, data=data) # Should have redirected to changelist # assert response.status_code == 302 assert response.url == "/admin/market/item/" # Should have saved item assert Item.objects.count() == 1 saved_item = Item.objects.all().first() for f in ["name", "price", "currency"]: if f not in admin.readonly_fields: assert getattr(saved_item, f) == data[f] if "file" not in admin.readonly_fields: assert "new_file" in saved_item.file.name if "image" not in admin.readonly_fields: assert "new_image" in saved_item.image.name reload(item_admin)
class TestConfirmationUsingFileCache(AdminConfirmTestCase): def setUp(self): # Load the Change Item Page ItemAdmin.confirm_change = True ItemAdmin.fields = ["name", "price", "file", "image", "currency"] ItemAdmin.save_as = True ItemAdmin.save_as_continue = True self.image_path = "screenshot.png" f = SimpleUploadedFile( name="test_file.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) i = SimpleUploadedFile( name="test_image.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) self.item = ItemFactory(name="Not name", file=f, image=i) return super().setUp() def test_save_as_continue_true_should_not_redirect_to_changelist(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = True # Upload new image and remove file i2 = SimpleUploadedFile( name="test_image2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], image=i2, ) file_cache = FileCache() file_cache.set(format_cache_key(model="Item", field="image"), i2) cache.set(CACHE_KEYS["object"], cache_item) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, f"/admin/market/item/{self.item.id + 1}/change/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.file) self.assertEqual(new_item.image.name.count("test_image2"), 1) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_save_as_continue_false_should_redirect_to_changelist(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Upload new image and remove file i2 = SimpleUploadedFile( name="test_image2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], image=i2, ) file_cache = FileCache() file_cache.set(format_cache_key(model="Item", field="image"), i2) cache.set(CACHE_KEYS["object"], cache_item) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.file) self.assertEqual(new_item.image.name.count("test_image2"), 1) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_saveasnew_without_any_file_changes_should_save_new_instance_without_files( self, ): item = self.item # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "image": "", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], ) cache.set(CACHE_KEYS["object"], cache_item) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, f"/admin/market/item/{self.item.id + 1}/change/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) # In Django (by default), the save as new does not transfer over the files self.assertFalse(new_item.file) self.assertFalse(new_item.image) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_add_with_upload_file_should_save_new_instance_with_files(self): # Upload new file f2 = SimpleUploadedFile( name="test_file2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Request.POST data = { "name": "name", "price": 2.0, "image": "", "file": f2, "currency": Item.VALID_CURRENCIES[0][0], "_confirm_add": True, "_save": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], file=f2 ) cache.set(CACHE_KEYS["object"], cache_item) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_add"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post("/admin/market/item/add/", data=data) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item self.item.refresh_from_db() self.assertEqual(self.item.name, "Not name") self.assertEqual(self.item.file.name.count("test_file"), 1) self.assertEqual(self.item.image.name.count("test_image2"), 0) self.assertEqual(self.item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=self.item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertIsNotNone(new_item.file) self.assertFalse(new_item.image) self.assertRegex(new_item.file.name, r"test_file2.*\.jpg$") # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_add_without_cached_post_should_save_new_instance_with_file(self): # Upload new file f2 = SimpleUploadedFile( name="test_file2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Request.POST data = { "name": "name", "price": 2.0, "image": "", "file": f2, "currency": Item.VALID_CURRENCIES[0][0], "_confirm_add": True, "_save": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], file=f2 ) cache.set(CACHE_KEYS["object"], cache_item) # Make sure there's no post cached post cache.delete(CACHE_KEYS["post"]) # Click "Yes, I'm Sure" del data["_confirm_add"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post("/admin/market/item/add/", data=data) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item self.item.refresh_from_db() self.assertEqual(self.item.name, "Not name") self.assertEqual(self.item.file.name.count("test_file"), 1) self.assertEqual(self.item.image.name.count("test_image2"), 0) self.assertEqual(self.item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=self.item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.image) # Able to save the cached file since cached object was there even though cached post was not self.assertRegex(new_item.file.name, r"test_file2.*\.jpg$") # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_add_without_cached_object_should_save_new_instance_but_not_have_file(self): # Request.POST data = { "name": "name", "price": 2.0, "image": "", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_add": True, "_save": True, } # Make sure there's no post cached obj cache.delete(CACHE_KEYS["object"]) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_add"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post("/admin/market/item/add/", data=data) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item self.item.refresh_from_db() self.assertEqual(self.item.name, "Not name") self.assertEqual(self.item.file.name.count("test_file"), 1) self.assertEqual(self.item.image.name.count("test_image2"), 0) self.assertEqual(self.item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=self.item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.image) # FAILED to save the file, because cached item was not there self.assertFalse(new_item.file) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_add_without_any_cache_should_save_new_instance_but_not_have_file(self): # Request.POST data = { "name": "name", "price": 2.0, "image": "", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_add": True, "_save": True, } # Make sure there's no cache cache.delete(CACHE_KEYS["object"]) cache.delete(CACHE_KEYS["post"]) # Click "Yes, I'm Sure" del data["_confirm_add"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post("/admin/market/item/add/", data=data) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should not have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item self.item.refresh_from_db() self.assertEqual(self.item.name, "Not name") self.assertEqual(self.item.file.name.count("test_file"), 1) self.assertEqual(self.item.image.name.count("test_image2"), 0) self.assertEqual(self.item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=self.item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.image) # FAILED to save the file, because cached item was not there self.assertFalse(new_item.file) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_change_without_cached_post_should_save_file_changes(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Upload new image and remove file i2 = SimpleUploadedFile( name="test_image2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "image": i2, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], image=i2, ) file_cache = FileCache() file_cache.set(format_cache_key(model="Item", field="image"), i2) cache.set(CACHE_KEYS["object"], cache_item) # Ensure no cached post cache.delete(CACHE_KEYS["post"]) # Click "Yes, I'm Sure" del data["_confirm_change"] # Image would have been in FILES and not in POST del data["image"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) # Should have cleared `file` since clear was selected self.assertFalse(new_item.file) self.assertIsNotNone(new_item.image) # Saved cached file from cached obj even if cached post was missing self.assertIn("test_image2", new_item.image.name) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_change_without_cached_object_should_save_but_without_file_changes(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Ensure no cached obj cache.delete(CACHE_KEYS["object"]) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.file) # FAILED to save image self.assertFalse(new_item.image) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_change_without_any_cache_should_save_but_not_have_file_changes(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_saveasnew": True, } # Ensure no cache cache.delete(CACHE_KEYS["object"]) cache.delete(CACHE_KEYS["post"]) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/2/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should not have changed existing item item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertEqual(item.file.name.count("test_file"), 1) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have saved new item self.assertEqual(Item.objects.count(), 2) new_item = Item.objects.filter(id=item.id + 1).first() self.assertIsNotNone(new_item) self.assertEqual(new_item.name, data["name"]) self.assertEqual(new_item.price, data["price"]) self.assertEqual(new_item.currency, data["currency"]) self.assertFalse(new_item.file) # FAILED to save image self.assertFalse(new_item.image) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_change_without_changing_file_should_save_changes(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "image": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_save": True, } # Set cache cache_item = Item( name=data["name"], price=data["price"], currency=data["currency"], ) cache.get(CACHE_KEYS["object"], cache_item) cache.get(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/1/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should have changed existing item self.assertEqual(Item.objects.count(), 1) item.refresh_from_db() self.assertEqual(item.name, "name") # Should have cleared if requested self.assertFalse(item.file.name) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) @mock.patch("admin_confirm.admin.CACHE_TIMEOUT", 1) def test_old_cache_should_not_be_used(self): item = self.item # Upload new image and remove file i2 = SimpleUploadedFile( name="test_image2.jpg", content=open(self.image_path, "rb").read(), content_type="image/jpeg", ) # Click "Save And Continue" data = { "id": item.id, "name": "name", "price": 2.0, "image": i2, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_continue": True, } response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should be shown confirmation page self._assertSubmitHtml( rendered_content=response.rendered_content, save_action="_continue", multipart_form=True, ) # Should have cached the unsaved item cached_item = cache.get(CACHE_KEYS["object"]) self.assertIsNotNone(cached_item) # Should not have saved the changes yet self.assertEqual(Item.objects.count(), 1) item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertIsNotNone(item.file) self.assertIsNotNone(item.image) # Wait for cache to time out time.sleep(1) # Check that it did time out cached_item = cache.get(CACHE_KEYS["object"]) self.assertIsNone(cached_item) # Click "Yes, I'm Sure" del data["_confirm_change"] data["image"] = "" data[CONFIRMATION_RECEIVED] = True response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should not have redirected to changelist self.assertEqual(response.url, f"/admin/market/item/{item.id}/change/") # Should have saved item self.assertEqual(Item.objects.count(), 1) saved_item = Item.objects.all().first() self.assertEqual(saved_item.name, data["name"]) self.assertEqual(saved_item.price, data["price"]) self.assertEqual(saved_item.currency, data["currency"]) self.assertFalse(saved_item.file) # SHOULD not have saved image since it was in the old cache self.assertNotIn("test_image2", saved_item.image) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_cache_with_incorrect_model_should_not_be_used(self): item = self.item # Load the Change Item Page ItemAdmin.save_as_continue = False # Request.POST data = { "id": item.id, "name": "name", "price": 2.0, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_save": True, } # Set cache to incorrect model cache_obj = Shop(name="ShopName") cache.set(CACHE_KEYS["object"], cache_obj) cache.set(CACHE_KEYS["post"], data) # Click "Yes, I'm Sure" del data["_confirm_change"] data[CONFIRMATION_RECEIVED] = True with mock.patch.object(ItemAdmin, "message_user") as message_user: response = self.client.post( f"/admin/market/item/{self.item.id}/change/", data=data ) # Should show message to user with correct obj and path message_user.assert_called_once() message = message_user.call_args[0][1] self.assertIn("/admin/market/item/1/change/", message) self.assertIn(data["name"], message) self.assertNotIn("You may edit it again below.", message) # Should have redirected to changelist self.assertEqual(response.url, "/admin/market/item/") # Should have changed existing item self.assertEqual(Item.objects.count(), 1) item.refresh_from_db() self.assertEqual(item.name, "name") # Should have cleared if requested self.assertFalse(item.file.name) self.assertEqual(item.image.name.count("test_image2"), 0) self.assertEqual(item.image.name.count("test_image"), 1) # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key)) def test_form_without_files_should_not_use_cache(self): cache.delete_many(CACHE_KEYS.values()) shop = ShopFactory() # Click "Save And Continue" data = { "id": shop.id, "name": "name", "_confirm_change": True, "_continue": True, } response = self.client.post(f"/admin/market/shop/{shop.id}/change/", data=data) # Should be shown confirmation page self._assertSubmitHtml( rendered_content=response.rendered_content, save_action="_continue" ) # Should not have set cache since not multipart form for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key))
def item(self, db): return ItemFactory()
def test_file_and_image_change(self): item = ItemFactory(name="Not name") # Select files image_path = "screenshot.png" f = SimpleUploadedFile( name="test_file.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) i = SimpleUploadedFile( name="test_image.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) item.file = f item.image = i item.save() # Load the Change Item Page ItemAdmin.confirm_change = True ItemAdmin.fields = ["name", "price", "file", "image", "currency"] response = self.client.get(f"/admin/market/item/{item.id}/change/") # Should be asked for confirmation self.assertTrue(response.context_data.get("confirm_change")) self.assertIn("_confirm_change", response.rendered_content) # Upload new image and remove file i2 = SimpleUploadedFile( name="test_image2.jpg", content=open(image_path, "rb").read(), content_type="image/jpeg", ) # Click "Save And Continue" data = { "id": item.id, "name": "name", "price": 2.0, "image": i2, "file": "", "file-clear": "on", "currency": Item.VALID_CURRENCIES[0][0], "_confirm_change": True, "_continue": True, } response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should be shown confirmation page self._assertSubmitHtml( rendered_content=response.rendered_content, save_action="_continue", multipart_form=True, ) # Should have cached the unsaved item cached_item = cache.get(CACHE_KEYS["object"]) self.assertIsNotNone(cached_item) # Should not have saved the changes yet self.assertEqual(Item.objects.count(), 1) item.refresh_from_db() self.assertEqual(item.name, "Not name") self.assertIsNotNone(item.file) self.assertIsNotNone(item.image) # Click "Yes, I'm Sure" del data["_confirm_change"] data["image"] = "" data[CONFIRMATION_RECEIVED] = True response = self.client.post(f"/admin/market/item/{item.id}/change/", data=data) # Should not have redirected to changelist self.assertEqual(response.url, f"/admin/market/item/{item.id}/change/") # Should have saved item self.assertEqual(Item.objects.count(), 1) saved_item = Item.objects.all().first() self.assertEqual(saved_item.name, data["name"]) self.assertEqual(saved_item.price, data["price"]) self.assertEqual(saved_item.currency, data["currency"]) self.assertFalse(saved_item.file) self.assertIsNotNone(saved_item.image) self.assertRegex(saved_item.image.name, r"test_image2.*\.jpg$") # Should have cleared cache for key in CACHE_KEYS.values(): self.assertIsNone(cache.get(key))
def test_item_factory_typing(): instance = ItemFactory() check_dataclass_typing(instance)
def test_item_str(): item = ItemFactory.build() assert str(item) == f"Item {item.external_id}"