def test_shop_url(self): lendable_material = MaterialFactory(lendable=True) self.client.force_login(UserFactory()) response = self.client.get(lendable_material.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_detail.html") self.assertTemplateUsed(response, "catalog/material_card.html") self.assertContains(response, lendable_material.get_shop_url())
def setUp(self): super().setUp() self.material = MaterialFactory( name="beschuiten (rol)", location__name="in the barn", categories=[CategoryFactory()], )
def test_edit_rate_class_add_material(self): rate_class = RateClassFactory() material = MaterialFactory(rate_class=None) # Add the material to the rate class through the form self.run_form(rate_class, [material]) # Verify that the material is now associated to the rate class material.refresh_from_db() self.assertEqual(material.rate_class, rate_class)
def test_redirects_to_login(self): material = MaterialFactory() response = self.client.get(material.get_absolute_url()) self.assertRedirects( response, reverse(settings.LOGIN_URL) + "?next=" + material.get_absolute_url(), )
def test_material_edit_link_no_perm(self): material = MaterialFactory() self.client.force_login(UserFactory()) response = self.client.get(material.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_detail.html") self.assertTemplateUsed(response, "catalog/material_card.html") self.assertNotContains( response, reverse("admin:booking_material_change", args=[material.pk]))
def test_material_edit_link(self, mock_has_perm): mock_has_perm.return_value = True material = MaterialFactory() user = UserFactory() self.client.force_login(user) response = self.client.get(material.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_detail.html") self.assertTemplateUsed(response, "catalog/material_card.html") self.assertContains( response, reverse("admin:booking_material_change", args=[material.pk])) mock_has_perm.assert_any_call(user, "booking.change_material", None)
def test_typeahead_thumbprint_not_none(self): materials = MaterialFactory.create_batch(3) last_material = MaterialFactory() self.assertNotEqual(materials[0].last_modified, last_material.last_modified) event = EventFactory() self.client.force_login(UserFactory()) response = self.client.get(event.get_absolute_url()) self.assertEqual( response.context["typeahead_thumbprint"], last_material.last_modified.isoformat(), "typeahead thumbprint is not correct", )
def test_delete_material_with_bookings(self): material = MaterialFactory() material_name = material.name booking = BookingFactory(material=material) material.delete() booking.refresh_from_db() self.assertEqual(Material.objects.count(), 0, "material was not deleted") self.assertEqual(Booking.objects.count(), 1, "booking was deleted") self.assertEqual(booking.material, None, "booking still refers to material") self.assertEqual( booking.custom_material, material_name, "booking does not have material name", )
def test_edit_rate_class_reassign_material(self): # Create a rate class and material rate_class = RateClassFactory() material = MaterialFactory() old_rate_class = material.rate_class # Add the material to the rate class through the form self.run_form(rate_class, [material]) material.refresh_from_db() # Verify that the rate class for the material was updated self.assertEqual(material.rate_class, rate_class) # Verify that the reverse relation holds as well self.assertTrue(material in rate_class.materials.all()) # Verify that the material is no longer associated to the old rate class old_rate_class.refresh_from_db() self.assertFalse(material in old_rate_class.materials.all())
def test_json_format(self): materials = MaterialFactory.create_batch(10) response = self.client.get("/booking/api/material?format=json") content = str(response.content, encoding="utf8") json_response = json.loads(content) for item in json_response: material = Material.objects.get(pk=int(item["id"])) self.assertEqual(item["name"], material.name) self.assertEqual(item["gm"], material.gm) for category in material.categories.all(): self.assertTrue(category.name in item["categories"]) self.assertEqual( material.images.count(), len(item["images"]), "not all images are included", ) for image_url in item["images"]: mimetype, encoding = mimetypes.guess_type(image_url) self.assertTrue( mimetype and mimetype.startswith("image"), "url does not seem image" ) self.assertTrue( "testserver" in image_url, "url does not contain domain" ) self.assertEqual(item["catalogUrl"], f"/catalog/{material.pk}/modal")
def test_delete_category_keeps_materials(self): category = CategoryFactory() material = MaterialFactory() material.categories.add(category) category.delete() self.assertEqual(Material.objects.count(), 1) self.assertEqual(Category.objects.count(), 0)
def test_materials_listed(self): materials = MaterialFactory.create_batch(5) self.client.force_login(UserFactory()) response = self.client.get(reverse("catalog:catalog")) self.assertTemplateUsed(response, "catalog/material_list.html") for material in materials: self.assertContainsMaterialOnce(response, material)
def test_materials_filter_category(self): category = CategoryFactory() other_category = CategoryFactory() materials_in_category = MaterialFactory.create_batch( 5, categories=[category]) materials_other_category = MaterialFactory.create_batch( 5, categories=[other_category]) self.client.force_login(UserFactory()) response = self.client.get(category.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_list.html") for material in materials_in_category: self.assertContainsMaterialOnce(response, material) for material in materials_other_category: self.assertNotContains(response, str(material)) # Check that the category filter buttons are in the response self.assertContains(response, str(category)) self.assertContains(response, str(other_category))
def test_uses_material_card(self): material = MaterialFactory(categories=[CategoryFactory()]) self.client.force_login(UserFactory()) response = self.client.get( reverse("catalog:material_modal", kwargs={"pk": material.pk})) self.assertTemplateUsed(response, "catalog/material_card.html") self.assertContains( response, material.name) # Check whether template rendered correctly.
def test_details_on_page(self): material = MaterialFactory(categories=[CategoryFactory()]) self.client.force_login(UserFactory()) response = self.client.get(material.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_detail.html") self.assertTemplateUsed(response, "catalog/material_card.html") self.assertContains(response, material.name) if material.gm: self.assertContains(response, "GM") self.assertContains(response, material.stock) for category in material.categories.all(): self.assertContains(response, category.name) self.assertContains(response, material.description) self.assertContains(response, material.location.name) for attachment in material.attachments.all(): self.assertContains(response, attachment.attachment.url) self.assertContains(response, attachment.description) for alias in material.aliases.all(): self.assertContains(response, alias.name)
def test_category_material_filter_parent(self): base = CategoryFactory() child = CategoryFactory(parent=base) grandchild = CategoryFactory(parent=child) material1 = MaterialFactory(categories=[child]) self.assertTrue(material1 in Material.objects.filter( categories__in=child.get_descendants(include_self=True))) self.assertTrue(material1 in Material.objects.filter( categories__in=base.get_descendants(include_self=True))) self.assertFalse(material1 in Material.objects.filter( categories__in=grandchild.get_descendants(include_self=True)))
def test_category_tree_hierarchy(self): parent = CategoryFactory(name="parent") child = CategoryFactory(name="child", parent=parent) grandchild = CategoryFactory(name="grandchild", parent=child) _ = MaterialFactory(categories=[grandchild]) response = self.client.get("/booking/api/material?format=woocommerce") content = response.content.decode("utf-8") csv_reader = csv.DictReader(io.StringIO(content)) category_csv = next(csv_reader)["tax:product_cat"] self.assertEqual(category_csv, "parent > child > grandchild")
def test_edit_rate_class_remove_material(self): rate_class = RateClassFactory() materials = MaterialFactory.create_batch(5, rate_class=rate_class) # Only keep the first 4 materials associated to the rate class self.run_form(rate_class, materials[:4]) for material in materials: material.refresh_from_db() # Verify that the first 4 materials are still associated for material in materials[:4]: self.assertEqual(material.rate_class, rate_class) # Verify that the 5th is no longer associated self.assertEqual(materials[4].rate_class, None)
def test_description_can_have_html_entities(self): material = MaterialFactory(description="→") self.client.force_login(UserFactory()) response = self.client.get(reverse("catalog:catalog")) self.assertTemplateUsed(response, "catalog/material_list.html") self.assertNotContains( response, "→", msg_prefix="the material description was escaped") self.assertContains( response, "→", msg_prefix="the material description does not match")
def test_create_rate_class_with_materials(self): rate_class = RateClassFactory.build() # do not save to DB self.assertFalse( RateClass.objects.all()) # verify that it is not in DB materials = MaterialFactory.create_batch(3, rate_class=None) self.run_form(rate_class, materials) # Verify that the rate class has been saved self.assertEqual(list(RateClass.objects.all()), [rate_class]) for material in materials: material.refresh_from_db() # Verify that all materials were associated for material in materials: self.assertEqual(material.rate_class, rate_class)
def test_get_shop_url(self): material_lendable = MaterialFactory(lendable=True) self.assertEqual( material_lendable.get_shop_url(), f"https://example.com/?p={material_lendable.sku}", ) material_non_lendable = MaterialFactory(lendable=False) self.assertEqual(material_non_lendable.get_shop_url(), None)
def test_csv_format(self): materials = MaterialFactory.create_batch(10) response = self.client.get("/booking/api/material?format=woocommerce") self.assertEqual( response.get("Content-Disposition"), 'attachment; filename="materials.csv"' ) self.assertEqual(response.status_code, 200) content = response.content.decode("utf-8") # Test if all materials are included in CSV + a header self.assertEqual( len(content.splitlines()), len(materials) + 1, "not all materials are part of csv", ) csv_reader = csv.DictReader(io.StringIO(content)) # Verify material attributes for row in csv_reader: material = Material.objects.get(pk=int(row["sku"]) - 2000) self.assertEqual(row["post_title"], material.name) self.assertEqual(row["post_name"], material.name) if material.lendable: self.assertEqual(row["tax:product_visibility"], "visible") self.assertEqual(row["post_status"], "publish") else: self.assertEqual( row["tax:product_visibility"], "exclude-from-catalog|exclude-from-search", ) self.assertEqual(row["post_status"], "private") if material.stock_value is not None: self.assertAlmostEqual(float(row["stock"]), material.stock_value) else: self.assertEqual(row["stock"], "") self.check_post_content(row["post_content"], material) if material.rate_class is not None: self.assertEqual( row["regular_price"], str(material.rate_class.rate.amount) ) else: self.assertEqual(row["regular_price"], str(0.00)) for category in material.categories.all(): self.assertTrue(category.name in row["tax:product_cat"]) self.check_images(row["images"], material) if material.stock_unit is not None: self.assertEqual(row["meta:stock_unit"], material.stock_unit) else: self.assertEqual(row["meta:stock_unit"], "")
def test_category_tree_multiple(self): parent = CategoryFactory(name="parent") child = CategoryFactory(name="child", parent=parent) _ = MaterialFactory(categories=[child, parent]) response = self.client.get("/booking/api/material?format=woocommerce") content = response.content.decode("utf-8") csv_reader = csv.DictReader(io.StringIO(content)) category_csv = next(csv_reader)["tax:product_cat"] self.assertTrue( category_csv == "parent > child|parent" or category_csv == "parent|parent > child" )
def test_catalog_descendant_categories_included(self): parent_category = CategoryFactory() materials_parent_category = MaterialFactory.create_batch( 5, categories=[parent_category]) child_category = CategoryFactory(parent=parent_category) materials_child_category = MaterialFactory.create_batch( 5, categories=[child_category]) grandchild_category = CategoryFactory(parent=child_category) materials_grandchild_category = MaterialFactory.create_batch( 5, categories=[grandchild_category]) self.client.force_login(UserFactory()) response = self.client.get(parent_category.get_absolute_url()) self.assertTemplateUsed(response, "catalog/material_list.html") for material in [ *materials_parent_category, *materials_child_category, *materials_grandchild_category, ]: self.assertContainsMaterialOnce(response, material) response = self.client.get(child_category.get_absolute_url()) for material in [ *materials_child_category, *materials_grandchild_category, ]: self.assertContainsMaterialOnce(response, material) for material in materials_parent_category: self.assertNotContains(response, str(material)) response = self.client.get(grandchild_category.get_absolute_url()) for material in materials_grandchild_category: self.assertContainsMaterialOnce(response, material) for material in [ *materials_parent_category, *materials_child_category ]: self.assertNotContains(response, str(material))
def test_can_navigate_catalog_page(self, mock_get_paginate_by): mock_get_paginate_by.return_value = 2 category = CategoryFactory() # Note there is also the self.material, so 6 materials in total materials = MaterialFactory.create_batch(5, categories=[category]) # Get the materials sorted sorted_materials = sorted( list(Material.objects.all()), key=lambda m: str(m).lower() ) def verify_material_order(catalog_view_page, i): # Get element from page item = catalog_view_page.get_catalog_item(i % mock_get_paginate_by()) # Get text text = catalog_view_page.get_catalog_item_text(item) self.assertEqual( text.lower(), str(sorted_materials[i]).lower(), f"material {i} is not sorted", ) # Bob is a logged in user bob = UserFactory() self.create_pre_authenticated_session(bob) # Bob opens the catalog page self.browser.get(self.live_server_url + reverse("catalog:catalog")) catalog_view_page = CatalogViewPage(self) # The first page contains the first two materials in order verify_material_order(catalog_view_page, 0) verify_material_order(catalog_view_page, 1) # Bob finds 3 pages in the catalog self.assertEqual(catalog_view_page.get_page_count(), 3) # Bob can navigate to page 2 catalog_view_page.navigate_to_page(2) # The second page contains the second two materials in order verify_material_order(catalog_view_page, 2) verify_material_order(catalog_view_page, 3) # Bob can navigate to page 3 catalog_view_page.navigate_to_page(3) # The third page contains the third two materials in order verify_material_order(catalog_view_page, 4) verify_material_order(catalog_view_page, 5)
def test_navigation_search_material_and_material_alias_from_catalog(self): self.browser.set_window_size(1024, 768) material = MaterialFactory() # Bob is a logged in user bob = UserFactory() self.create_pre_authenticated_session(bob) # Bob opens the catalog page self.browser.get(self.live_server_url + reverse("catalog:catalog")) catalog_view_page = CatalogViewPage(self) self.check_if_typeahead_loaded() # Bob clicks the search bar and enters the name of the material search_input = self.browser.find_element(By.ID, "navSearch") search_input.send_keys(material.name) search_input.send_keys(Keys.ENTER) # Bob sees the details for the typed material catalog_view_page = CatalogViewPage(self) catalog_view_page.verify_material_attributes( self.browser.find_element(By.ID, "catalogModal"), material ) # Bob closes the modal by pressing escape ActionChains(self.browser).send_keys(Keys.ESCAPE).perform() # Bob clicks the search bar and enters the alias of the material search_input = self.browser.find_element(By.ID, "navSearch") for _ in range(len(material.name)): search_input.send_keys(Keys.BACK_SPACE) search_input.send_keys(str(material.aliases.first())) search_input.send_keys(Keys.ENTER) # Choose the suggestion and submit form # Bob sees the details for the typed material self.wait_for( lambda: catalog_view_page.verify_material_attributes( self.browser.find_element(By.ID, "catalogModal"), material ) )
def setUp(self): super().setUp() self.active_event = EventFactory() self.materials = MaterialFactory.create_batch(size=10) MaterialFactory(name="beschuiten (rol)") MaterialFactory(name="EHBO doos")
def test_events_in_context(self): material = MaterialFactory() event = EventFactory() self.client.force_login(UserFactory()) response = self.client.get(material.get_absolute_url()) self.assertEqual(list(response.context["events"]), [event])
def test_get_sku(self): material = MaterialFactory() self.assertEqual( material.sku, material.id + 2365, )
def test_get_shop_url_no_setting(self): material_lendable = MaterialFactory(lendable=True) self.assertEqual(material_lendable.get_shop_url(), None) material_non_lendable = MaterialFactory(lendable=False) self.assertEqual(material_non_lendable.get_shop_url(), None)