def test_exclude_category_and_descendants(self): parent = CategoryFactory() child = CategoryFactory(parent=parent) categories = [parent, child, *CategoryFactory.create_batch(3)] _ = create_bookings_with_set_of_categories(categories, n=20) bookings_qs = Booking.objects.all() excluded_categories = [parent, child] _filter = ListViewFilterFactory(excluded_categories=[parent]) in_set, out_set = _filter.filter_bookings(bookings_qs) self.assertEqual( in_set.count() + out_set.count(), 20, "not all bookings are part of output" ) for booking in in_set: # The bookings in the in_set should have no category in common # with included_categories self.assertEqual( len(set(booking.material.categories.all()) & set(excluded_categories)), 0, ) for booking in out_set: # The bookings in the in_set should have at least one category in common # with included_categories self.assertGreaterEqual( len(set(booking.material.categories.all()) & set(excluded_categories)), 1, )
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_category_ancestors(self): base = CategoryFactory() child = CategoryFactory(parent=base) grandchild = CategoryFactory(parent=child) self.assertTrue(base in grandchild.get_ancestors()) self.assertTrue(child in grandchild.get_ancestors()) self.assertFalse(child in child.get_ancestors()) self.assertFalse(grandchild in child.get_ancestors())
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_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_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 setUp(self): super().setUp() self.material = MaterialFactory( name="beschuiten (rol)", location__name="in the barn", categories=[CategoryFactory()], )
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_can_view_material_details_modal_game_view(self): # Tests the material details modal from the booking game page. booking = BookingFactory(material__categories=[CategoryFactory()]) # Bob is a logged in user bob = booking.requester self.create_pre_authenticated_session(bob) # Bob opens the event page self.browser.get(self.live_server_url + booking.game.event.get_absolute_url()) # Bob finds the preloaded booking game_view_page = GameViewPage(self) booking_id = game_view_page.get_newest_booking_id() self.assertEqual(booking_id, booking.pk) # Bob clicks on the material name in the booking game_view_page.open_catalog_modal(booking_id) # Bob sees the details for the booked material catalog_view_page = CatalogViewPage(self) catalog_view_page.verify_material_attributes( game_view_page.get_catalog_modal(), booking.material ) # Bob clicks the category in the modal... game_view_page.get_catalog_modal().find_elements( By.CSS_SELECTOR, ".category-list a" )[0].click() # ... to show the material in the catalog self.wait_for( lambda: self.assertCSSElementExists( ".catalog-masonry", msg="no masonry with materials was found on the page", ) ) # Bob clicks the category filter that is active to show all materials self.browser.find_element( By.CSS_SELECTOR, "button[name=categories].btn-secondary" ).click() # Bob finds beschuiten (rol) on the page as well data_attr = f"/catalog/{self.material.pk}/modal" selector = f"[data-catalog-item='{data_attr}']" self.wait_for( lambda: self.assertCSSElementExists( selector, "material was not found", ) ) # Bob inspects the properties of the beschuiten (rol) self.browser.find_element(By.CSS_SELECTOR, selector).click() catalog_view_page.verify_material_attributes( game_view_page.get_catalog_modal(), self.material )
def test_no_filter_attributes(self): categories = CategoryFactory.create_batch(2) _ = create_bookings_with_set_of_categories(categories, n=20) bookings_qs = Booking.objects.all() _filter = ListViewFilterFactory( included_categories=None, excluded_categories=None, gm=None ) in_set, out_set = _filter.filter_bookings(bookings_qs) self.assertEqual( in_set.count() + out_set.count(), 20, "not all bookings are part of output" ) # All bookings should be part of in_set self.assertEqual(in_set.count(), 20, "not all bookings are part of in_set")
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_include_and_exclude_same_category(self): categories = CategoryFactory.create_batch(2) _ = create_bookings_with_set_of_categories(categories, n=20) bookings_qs = Booking.objects.all() _filter = ListViewFilterFactory( included_categories=[categories[0]], excluded_categories=categories ) in_set, out_set = _filter.filter_bookings(bookings_qs) self.assertEqual( in_set.count() + out_set.count(), 20, "not all bookings are part of output" ) for booking in in_set: # categories[0] is both in included and excluded categories we have chosen # to put it in out-set then. self.assertNotIn(categories[0], booking.material.categories.all())
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_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_filters_pipeline(self): categories = CategoryFactory.create_batch(4) _ = create_bookings_with_set_of_categories(categories, n=30) bookings_qs = Booking.objects.all() filters = [ ListViewFilterFactory(included_categories=categories[0:2], gm=False), ListViewFilterFactory(included_categories=[categories[3]], gm=True), ] lists = ListView(filters=filters).get_lists(bookings_qs) self.assertEqual( sum([len(bookings) for lv, bookings in lists]), 30, "not all bookings are part of output", ) if len(lists) > len(filters): left_over_lv, left_over_bookings = lists[-1] for booking in left_over_bookings: # The bookings are not both gm=false and in category 0 or 1 self.assertFalse( not booking.material.gm and any( [ cat in categories[0:2] for cat in booking.material.categories.all() ] ) ) # The bookings are not both gm=false and in category 0 or 1 self.assertFalse( booking.material.gm and any( [ cat == categories[3] for cat in booking.material.categories.all() ] ) ) # Check that all lists are sorted for lv, bookings in lists: check_sorted_bookings(self, bookings)
def test_can_view_material_details_modal_list_view(self): # Test the material details model from the booking list page. booking = BookingFactory(material__categories=[CategoryFactory()]) # Bob is a logged in user bob = booking.requester self.create_pre_authenticated_session(bob) # Bob opens the event page self.browser.get(self.live_server_url + booking.game.event.get_absolute_url()) # Bob switches to the list view game_view_page = GameViewPage(self) game_view_page.switch_to_list_view() # Bob finds the preloaded booking list_view_page = ListViewPage(self) booking_id = list_view_page.get_newest_booking_id() self.assertEqual(booking_id, booking.pk) # Bob clicks on the material name in the booking game_view_page.open_catalog_modal(booking_id) # Bob sees the details for the booked material catalog_view_page = CatalogViewPage(self) catalog_view_page.verify_material_attributes( list_view_page.get_catalog_modal(), booking.material ) # Bob clicks the category in the modal... list_view_page.get_catalog_modal().find_elements( By.CSS_SELECTOR, ".category-list a" )[0].click() # ... to show the material in the catalog self.wait_for( lambda: self.assertCSSElementExists( ".catalog-masonry", msg="no masonry with materials was found on the page", ) )
def test_include_category(self): categories = CategoryFactory.create_batch(4) _ = create_bookings_with_set_of_categories(categories, n=20) bookings_qs = Booking.objects.all() included_categories = categories[0:2] _filter = ListViewFilterFactory(included_categories=included_categories) in_set, out_set = _filter.filter_bookings(bookings_qs) self.assertEqual( in_set.count() + out_set.count(), 20, "not all bookings are part of output" ) for booking in in_set: # The bookings in the in_set should have at least one category in common # with included_categories self.assertGreaterEqual( len(set(booking.material.categories.all()) & set(included_categories)), 1, ) for booking in out_set: # The bookings in the in_set should have no category in common with # included_categories self.assertEqual( len(set(booking.material.categories.all()) & set(included_categories)), 0, )