def test_same_codes(): shop1 = factories.get_shop(True, "EUR") shop2 = factories.get_shop(True, "USD") dc1 = Coupon.objects.create(code="TEST") dc2 = Coupon.objects.create(code="TEST") BasketCampaign.objects.create(name="test1", active=True, shop_id=shop1.id, coupon_id=dc1.id) with pytest.raises(ValidationError): BasketCampaign.objects.create(name="test1", active=True, shop_id=shop1.id, coupon_id=dc2.id) BasketCampaign.objects.create(name="test2", active=True, shop_id=shop2.id, coupon_id=dc2.id) with pytest.raises(ValidationError): BasketCampaign.objects.create(name="test2", active=True, shop_id=shop2.id, coupon_id=dc1.id) # Disable one campaigns for dc1 and you should be able to set the code to different campaign again dc3 = Coupon.objects.create(code="TEST") BasketCampaign.objects.filter(coupon=dc1).update(active=False) BasketCampaign.objects.create(name="test1", active=True, shop_id=shop1.id, coupon_id=dc3.id) # Try to reactivate the campaign for shop1 c = BasketCampaign.objects.filter(coupon=dc1).first() assert c.active == False with pytest.raises(ValidationError): c.active = True c.save() # Try to sneak one duplicate code by saving the coupon dc4 = Coupon.objects.create(code="TEST1") BasketCampaign.objects.create(name="test4", active=True, shop_id=shop2.id, coupon_id=dc4.id) with pytest.raises(ValidationError): dc4.code = "TEST" dc4.save()
def test_happy_hours_admin_edit_view_over_midnight(rf, staff_user, admin_user): shop = factories.get_default_shop() shop.staff_members.add(staff_user) factories.get_shop(identifier="shop2", enabled=True) assert Shop.objects.count() == 2 # Staff user gets shop automatically from_hour = datetime.time(hour=21, minute=0) to_hour = datetime.time(hour=3, minute=0) data = { "name": "Happiest Hour 2pm", "weekdays": [1], # Tue "from_hour": from_hour, "to_hour": to_hour } request = apply_request_middleware(rf.post("/", data=data), user=staff_user, shop=shop) set_shop(request, shop) assert request.shop == shop view_func = HappyHourEditView.as_view() response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 302 happy_hour = HappyHour.objects.first() assert happy_hour is not None assert happy_hour.shops.first() == shop assert happy_hour.time_ranges.count() == 2 # Since happy hour starts and ends on different day assert happy_hour.time_ranges.filter(weekday=1).exists() assert happy_hour.time_ranges.filter(weekday=1, from_hour=from_hour, to_hour=datetime.time(23, 59)).exists() assert happy_hour.time_ranges.filter(weekday=2, from_hour=datetime.time(0), to_hour=to_hour).exists() _assert_view_get(rf, happy_hour, shop, staff_user) # Viewing the edit should also still work
def test_manufacturer_admin_multishop_shop(rf, staff_user, admin_user, superuser): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop1 = factories.get_shop(identifier="shop1", enabled=True) shop2 = factories.get_shop(identifier="shop2", enabled=True) shop1.staff_members.add(staff_user) shop2.staff_members.add(staff_user) assert Manufacturer.objects.count() == 0 user = admin_user if superuser else staff_user request = apply_request_middleware(rf.post("/", data=dict(name="Manuf shop2")), user=user, shop=shop2) set_shop(request, shop2) view_func = ManufacturerEditView.as_view() response = view_func(request) assert response.status_code == 302 if superuser: assert Manufacturer.objects.first().shops.count() == 0 else: assert Manufacturer.objects.first().shops.first() == shop2 for view_class in (ManufacturerEditView, ManufacturerListView): view_instance = view_class() view_instance.request= request assert view_instance.get_queryset().count() == 1 if superuser: assert view_instance.get_queryset().first().shops.count() == 0 else: assert view_instance.get_queryset().first().shops.count() == 1 assert view_instance.get_queryset().first().shops.first() == shop2 request = apply_request_middleware(rf.post("/", data=dict(name="Manuf shop1")), user=user, shop=shop1) set_shop(request, shop1) view_func = ManufacturerEditView.as_view() response = view_func(request) assert response.status_code == 302 if superuser: assert Manufacturer.objects.last().shops.count() == 0 else: assert Manufacturer.objects.last().shops.first() == shop1 for view_class in (ManufacturerEditView, ManufacturerListView): view_instance = view_class() view_instance.request= request assert view_instance.get_queryset().count() == (2 if superuser else 1) if superuser: assert view_instance.get_queryset().first().shops.count() == 0 assert view_instance.get_queryset().last().shops.count() == 0 else: assert view_instance.get_queryset().first().shops.count() == 1 assert view_instance.get_queryset().first().shops.first() == shop1
def test_edit_shared_file(admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop1 = factories.get_shop(identifier="shop1", enabled=True) shop2 = factories.get_shop(identifier="shop2", enabled=True) folder1 = Folder.objects.create(name="folder1") folder2 = Folder.objects.create(name="folder2") file = File.objects.create(original_filename="test.jpg", folder=folder1) # Shared file file_count = File.objects.count() assert force_text(file) == "test.jpg" response = _mbv_command(shop1, admin_user, {"action": "rename_file", "id": file.pk, "name": "test.tiff"}) assert not response["success"] response = _mbv_command(shop1, admin_user, {"action": "move_file", "file_id": file.pk, "folder_id": folder2.pk}) assert not response["success"] assert File.objects.get(pk=file.pk).folder == folder1 response = _mbv_command(shop1, admin_user, {"action": "delete_file", "id": file.pk}) assert not response["success"] # Let's make sure rename works when only one shop owns the file media_file = MediaFile.objects.create(file=file) media_file.shops.add(shop1) response = _mbv_command(shop1, admin_user, {"action": "rename_file", "id": file.pk, "name": "test.tiff"}) assert response["success"] file = File.objects.get(pk=file.pk) assert force_text(file) == "test.tiff" # Let's move the file to different folder response = _mbv_command(shop1, admin_user, {"action": "move_file", "file_id": file.pk, "folder_id": folder2.pk}) assert response["success"] assert File.objects.get(pk=file.pk).folder == folder2 # Then add second shop for the file and let's check and # renaming should be disabled again. media_file.shops.add(shop2) response = _mbv_command(shop1, admin_user, {"action": "rename_file", "id": file.pk, "name": "test.tiff"}) assert not response["success"] response = _mbv_command(shop1, admin_user, {"action": "delete_file", "id": file.pk}) assert not response["success"] response = _mbv_command(shop2, admin_user, {"action": "rename_file", "id": file.pk, "name": "test.tiff"}) assert not response["success"] response = _mbv_command(shop2, admin_user, {"action": "delete_file", "id": file.pk}) assert not response["success"] # Finally remove the file as shop2 media_file.shops.remove(shop1) response = _mbv_command(shop1, admin_user, {"action": "delete_file", "id": file.pk}) assert response["error"] == "File matching query does not exist." response = _mbv_command(shop2, admin_user, {"action": "delete_file", "id": file.pk}) assert response["success"] assert File.objects.count() == file_count - 1
def test_happy_hours_admin_edit_view(rf, staff_user, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop = factories.get_default_shop() shop.staff_members.add(staff_user) factories.get_shop(identifier="shop2", enabled=True) assert Shop.objects.count() == 2 # Staff user gets shop automatically data = { "name": "Happiest Hour 2pm", "weekdays": [6], # Sun "from_hour": datetime.time(hour=14, minute=0), "to_hour": datetime.time(hour=14, minute=0) } request = apply_request_middleware(rf.post("/", data=data), user=staff_user, shop=shop) set_shop(request, shop) assert request.shop == shop view_func = HappyHourEditView.as_view() response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 302 happy_hour1 = HappyHour.objects.first() assert happy_hour1 is not None assert happy_hour1.shops.first() == shop assert happy_hour1.time_ranges.count() == 1 # Since happy hour starts and ends on same day # Test with superuser and with different shop shop2 = factories.get_shop(enabled=True) request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop2) set_shop(request, shop2) view_func = HappyHourEditView.as_view() response = view_func(request) assert response.status_code == 302 assert HappyHour.objects.count() == 2 happy_hour2 = HappyHour.objects.exclude(id=happy_hour1.pk).first() assert happy_hour1 != happy_hour2 assert happy_hour2.shops.count() == 1 assert happy_hour2.shops.filter(id=shop2.pk).first() # Staff user can only view coupon codes since that has the right shop _assert_view_get(rf, happy_hour1, shop, staff_user) _assert_view_get(rf, happy_hour2, shop, staff_user, True) # Superuser can see both if needed, but only when right shop is active _assert_view_get(rf, happy_hour1, shop, admin_user) _assert_view_get(rf, happy_hour2, shop, admin_user, True) _assert_view_get(rf, happy_hour2, shop2, admin_user)
def test_exceptions_admin_edit_view(rf, staff_user, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop = factories.get_default_shop() shop.staff_members.add(staff_user) factories.get_shop(identifier="shop2", enabled=True) assert Shop.objects.count() == 2 # Staff user gets shop automatically data = { "name": "No deals in next 2 days!", "start_datetime": datetime.datetime(year=2018, month=11, day=9), "end_datetime": datetime.datetime(year=2018, month=11, day=11), } request = apply_request_middleware(rf.post("/", data=data), user=staff_user, shop=shop) set_shop(request, shop) assert request.shop == shop view_func = AvailabilityExceptionEditView.as_view() response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 302 exception1 = AvailabilityException.objects.first() assert exception1 is not None assert exception1.shops.first() == shop # Test with superuser and with different shop shop2 = factories.get_shop(enabled=True) request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop2) set_shop(request, shop2) view_func = AvailabilityExceptionEditView.as_view() response = view_func(request) assert response.status_code == 302 assert AvailabilityException.objects.count() == 2 exception2 = AvailabilityException.objects.exclude(id=exception1.pk).first() assert exception1 != exception2 assert exception2.shops.count() == 1 assert exception2.shops.filter(id=shop2.pk).exists() # Staff user can only view coupon codes since that has the right shop _assert_view_get(rf, exception1, shop, staff_user) _assert_view_get(rf, exception2, shop, staff_user, True) # Superuser can see both if needed, but only when right shop is active _assert_view_get(rf, exception1, shop, admin_user) _assert_view_get(rf, exception2, shop, admin_user, True) _assert_view_get(rf, exception2, shop2, admin_user)
def _test_happy_hours_delete_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) happy_hour_name = "The Hour %s" % index happy_hour = HappyHour.objects.create(name=happy_hour_name) happy_hour.shops = [shop] extra_happy_hour= HappyHour.objects.create(name="Extra Hour %s" % index) extra_happy_hour.shops = [shop] assert HappyHour.objects.filter(name=happy_hour_name).exists() view_func = HappyHourDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request, pk=happy_hour.pk) if hasattr(response, "render"): response.render() assert response.status_code == 302 assert not HappyHour.objects.filter(name=happy_hour_name).exists() # Make sure that this staff can't remove other people discounts other_exceptions = HappyHour.objects.exclude(shops=shop) exception_count = other_exceptions.count() for coupon in other_exceptions: view_func = HappyHourDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) with pytest.raises(Http404): response = view_func(request, pk=coupon.pk) if hasattr(response, "render"): response.render() assert exception_count == HappyHour.objects.exclude(shops=shop).count()
def _test_happy_hours_list_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) happy_hour = HappyHour.objects.create(name="After Work %s" % index) happy_hour.shops = [shop] view_func = HappyHourListView.as_view() request = apply_request_middleware( rf.get("/", { "jq": json.dumps({"perPage": 100, "page": 1}) }), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 200 view_instance = HappyHourListView() view_instance.request = request assert request.shop == shop assert view_instance.get_queryset().count() == 1 data = json.loads(view_instance.get(request).content.decode("UTF-8")) assert len(data["items"]) == 1
def test_category_tour(browser, admin_user, live_server, settings): shop = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") admin_user_2 = factories.create_random_user(is_staff=True, is_superuser=True) admin_user_2.set_password("password") admin_user_2.save() shop.staff_members.add(admin_user) shop.staff_members.add(admin_user_2) for user in [admin_user, admin_user_2]: initialize_admin_browser_test(browser, live_server, settings, username=user.username, tour_complete=False) wait_until_condition(browser, lambda x: x.is_text_present("Welcome!")) browser.visit(live_server + "/sa/categories/new") wait_until_condition(browser, lambda x: x.is_text_present("Add a new product category"), timeout=30) wait_until_condition(browser, lambda x: x.is_element_present_by_css(".shepherd-button.btn-primary")) click_element(browser, ".shepherd-button.btn-primary") wait_until_condition(browser, lambda x: not x.is_element_present_by_css(".shepherd-button")) wait_until_condition(browser, lambda x: is_tour_complete(shop, "category", user)) # check whether the tour is shown again browser.visit(live_server + "/sa/categories/new") wait_until_condition(browser, lambda x: not x.is_text_present("Add a new product category")) browser.visit(live_server + "/logout") browser.visit(live_server + "/sa") assert is_tour_complete(shop2, "category", user) is False
def test_set_non_shop_member_customer(rf): """ Set some customer to the basket that is not member of the shop """ with override_settings(**CORE_BASKET_SETTINGS): shop = factories.get_shop(False) assert shop != factories.get_default_shop() user = factories.create_random_user() request = apply_request_middleware(rf.get("/"), user=user) basket = get_basket(request, "basket") basket.customer = get_person_contact(user) assert basket.shop == factories.get_default_shop() person = factories.create_random_person() person.shops.add(shop) company = factories.create_random_company() company.add_to_shop(shop) for customer in [person, company]: with pytest.raises(ValidationError) as exc: basket_commands.handle_set_customer(request, basket, customer) assert exc.value.code == "invalid_customer_shop" assert basket.customer == get_person_contact(user)
def _test_exception_delete_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) exception_name = "Exception %s" % index exception = AvailabilityException.objects.create( name=exception_name, start_datetime=now(), end_datetime=now()) exception.shops = [shop] extra_exception = AvailabilityException.objects.create( name="Extra Exception %s" % index, start_datetime=now(), end_datetime=now()) extra_exception.shops = [shop] assert AvailabilityException.objects.filter(name=exception_name).exists() view_func = AvailabilityExceptionDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request, pk=exception.pk) if hasattr(response, "render"): response.render() assert response.status_code == 302 assert not AvailabilityException.objects.filter(name=exception_name).exists() # Make sure that this staff can't remove other people discounts other_exceptions = AvailabilityException.objects.exclude(shops=shop) exception_count = other_exceptions.count() for coupon in other_exceptions: view_func = AvailabilityExceptionDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) with pytest.raises(Http404): response = view_func(request, pk=coupon.pk) if hasattr(response, "render"): response.render() assert exception_count == AvailabilityException.objects.exclude(shops=shop).count()
def _test_coupon_code_list_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) coupon_code = CouponCode.objects.create(code="%s" % index) coupon_code.shops = [shop] view_func = CouponCodeListView.as_view() request = apply_request_middleware( rf.get("/", { "jq": json.dumps({"perPage": 100, "page": 1}) }), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 200 view_instance = CouponCodeListView() view_instance.request = request assert request.shop == shop assert view_instance.get_queryset().count() == 1 data = json.loads(view_instance.get(request).content.decode("UTF-8")) assert len(data["items"]) == 1 coupon_code_data = [item for item in data["items"] if item["_id"] == coupon_code.pk][0] assert coupon_code_data["usages"] == 0
def _test_coupon_code_delete_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) code = "code-%s" % index coupon = CouponCode.objects.create(code=code) coupon.shops = [shop] extra_coupon = CouponCode.objects.create(code="extra-coupon-%s" % index) extra_coupon.shops = [shop] assert CouponCode.objects.filter(code=code).exists() view_func = CouponCodeDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request, pk=coupon.pk) if hasattr(response, "render"): response.render() assert response.status_code == 302 assert not CouponCode.objects.filter(code=code).exists() # Make sure that this staff can't remove other people discounts other_coupons = CouponCode.objects.exclude(shops=shop) coupon_count = other_coupons.count() for coupon in other_coupons: view_func = CouponCodeDeleteView.as_view() request = apply_request_middleware(rf.post("/"), user=staff_user, shop=shop) set_shop(request, shop) with pytest.raises(Http404): response = view_func(request, pk=coupon.pk) if hasattr(response, "render"): response.render() assert coupon_count == CouponCode.objects.exclude(shops=shop).count()
def test_product_tour(browser, admin_user, live_server, settings): shop = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") admin_user_2 = factories.create_random_user(is_staff=True, is_superuser=True) admin_user_2.set_password("password") admin_user_2.save() product = factories.get_default_product() shop_product = product.get_shop_instance(shop) shop.staff_members.add(admin_user) shop.staff_members.add(admin_user_2) for user in [admin_user, admin_user_2]: initialize_admin_browser_test(browser, live_server, settings, username=user.username, tour_complete=False) wait_until_condition(browser, lambda x: x.is_text_present("Welcome!")) browser.visit(live_server + "/sa/products/%d/" % shop_product.pk) wait_until_condition(browser, lambda x: x.is_text_present(shop_product.product.name)) # as this is added through javascript, add an extra timeout wait_until_condition(browser, lambda x: x.is_text_present("You are adding a product."), timeout=30) wait_until_condition(browser, lambda x: x.is_element_present_by_css(".shepherd-button.btn-primary")) click_element(browser, ".shepherd-button.btn-primary") category_targets = [ "a.shepherd-enabled[href='#basic-information-section']", "a.shepherd-enabled[href='#additional-details-section']", "a.shepherd-enabled[href='#manufacturer-section']", "a.shepherd-enabled[href*='-additional-section']", "a.shepherd-enabled[href='#product-media-section']", "a.shepherd-enabled[href='#product-images-section']", "a.shepherd-enabled[href='#contact-group-pricing-section']", "a.shepherd-enabled[href='#contact-group-discount-section']" ] # Scroll top before starting to click. For some reason the first # item is not found without this. For Firefox or Chrome the browser # does not do any extra scroll which could hide the first item. # Steps are scrollTo false on purpose since the scrollTo true is the # config which does not work in real world. browser.execute_script("window.scrollTo(0,0)") for target in category_targets: try: wait_until_condition(browser, lambda x: x.is_element_present_by_css(target)) browser.find_by_css(".shepherd-button.btn-primary").last.click() except ElementNotInteractableException: move_to_element(browser, ".shepherd-button.btn-primary") wait_until_condition(browser, lambda x: x.is_element_present_by_css(target)) browser.find_by_css(".shepherd-button.btn-primary").last.click() wait_until_condition(browser, lambda x: is_tour_complete(shop, "product", user)) # check whether the tour is shown again browser.visit(live_server + "/sa/products/%d/" % shop_product.pk) wait_until_condition(browser, lambda x: not x.is_text_present("You are adding a product."), timeout=20) assert is_tour_complete(shop2, "product", user) is False browser.visit(live_server + "/logout") browser.visit(live_server + "/sa")
def test_media_view_images(rf): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop1 = factories.get_shop(identifier="shop1", enabled=True) shop1_staff1 = _create_random_staff(shop1) shop1_staff2 = _create_random_staff(shop1) shop2 = factories.get_shop(identifier="shop2", enabled=True) shop2_staff = _create_random_staff(shop2) # Let's agree this folder is created by for example carousel # so it would be shared with all the shops. folder = Folder.objects.create(name="Root") assert MediaFolder.objects.count() == 0 path = "/%s" % folder.name File.objects.create(name="normalfile", folder=folder) # Shared between shops # Let's create 4 images for shop 1 _mbv_upload(shop1, shop1_staff1, path=path) _mbv_upload(shop1, shop1_staff1, path=path) _mbv_upload(shop1, shop1_staff2, path=path) _mbv_upload(shop1, shop1_staff2, path=path) assert MediaFile.objects.count() == 4 # Let's create 3 images for shop 2 _mbv_upload(shop2, shop2_staff, path=path) _mbv_upload(shop2, shop2_staff, path=path) _mbv_upload(shop2, shop2_staff, path=path) assert MediaFile.objects.count() == 7 # All files were created to same folder and while uploading # the each shop declared that they own the folder. assert Folder.objects.count() == 1 assert MediaFolder.objects.count() == 1 assert MediaFolder.objects.filter(shops=shop1).exists() assert shop1.media_folders.count() == 1 assert shop1.media_files.count() == 4 assert MediaFolder.objects.filter(shops=shop2).exists() assert shop2.media_folders.count() == 1 assert shop2.media_files.count() == 3 # Now let's make sure that each staff can view the folder # and all the files she should see. _check_that_staff_can_see_folder(rf, shop1, shop1_staff1, folder, 5) _check_that_staff_can_see_folder(rf, shop1, shop1_staff2, folder, 5) _check_that_staff_can_see_folder(rf, shop2, shop2_staff, folder, 4)
def test_discount_admin_edit_view(rf, staff_user, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop = factories.get_default_shop() shop.staff_members.add(staff_user) factories.get_shop(identifier="shop2") assert Shop.objects.count() == 2 # Staff user gets shop automatically product = factories.create_product("test", shop=shop) discount_percentage = 20 data = {"product": product.pk, "discount_percentage": discount_percentage} request = apply_request_middleware(rf.post("/", data=data), user=staff_user, shop=shop) set_shop(request, shop) assert request.shop == shop view_func = DiscountEditView.as_view() response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 302 discount1 = Discount.objects.first() assert discount1.shops.first() == shop # Test with superuser and with different shop shop2 = factories.get_shop(enabled=True) request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop2) set_shop(request, shop2) view_func = DiscountEditView.as_view() response = view_func(request) assert response.status_code == 302 assert Discount.objects.count() == 2 discount2 = Discount.objects.exclude(id=discount1.pk).first() assert discount1 != discount2 assert discount2.shops.count() == 1 assert discount2.shops.filter(id=shop2.pk).exists() # Staff user can only view discount1 since that has the right shop _assert_view_get(rf, discount1, shop, staff_user) _assert_view_get(rf, discount2, shop, staff_user, True) # Superuser can see both if needed, but only when right shop is active _assert_view_get(rf, discount1, shop, admin_user) _assert_view_get(rf, discount2, shop, admin_user, True) _assert_view_get(rf, discount2, shop2, admin_user)
def test_coupon_codes_admin_edit_view(rf, staff_user, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop = factories.get_default_shop() shop.staff_members.add(staff_user) factories.get_shop(identifier="shop2", enabled=True) assert Shop.objects.count() == 2 # Staff user gets shop automatically data = {"code": "potus"} request = apply_request_middleware(rf.post("/", data=data), user=staff_user, shop=shop) set_shop(request, shop) assert request.shop == shop view_func = CouponCodeEditView.as_view() response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 302 coupon1 = CouponCode.objects.first() assert coupon1.shops.first() == shop # Test with superuser and with different shop shop2 = factories.get_shop(enabled=True) request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop2) set_shop(request, shop2) assert request.shop == shop2 view_func = CouponCodeEditView.as_view() response = view_func(request) assert response.status_code == 302 assert CouponCode.objects.count() == 2 coupon2 = CouponCode.objects.exclude(id=coupon1.pk).first() assert coupon1 != coupon2 assert coupon2.shops.count() == 1 assert coupon2.shops.filter(id=shop2.pk).exists() # Staff user can only view coupon codes for his shop _assert_view_get(rf, coupon1, shop, staff_user) _assert_view_get(rf, coupon2, shop, staff_user, True) # Superuser can see both if needed, but only when right shop is active _assert_view_get(rf, coupon1, shop, admin_user) _assert_view_get(rf, coupon2, shop, admin_user, True) _assert_view_get(rf, coupon2, shop2, admin_user)
def test_resource_injection(client): """ Test that the GDPR warning is injected into the front template when enabled """ activate("en") shop = factories.get_default_shop() client = SmartClient() index_url = reverse("E-Commerce:index") response = client.get(index_url) assert "gdpr-consent-warn-bar" not in response.content.decode("utf-8") # create a GDPR setting for the shop shop_gdpr = GDPRSettings.get_for_shop(shop) shop_gdpr.cookie_banner_content = "my cookie banner content" shop_gdpr.cookie_privacy_excerpt = " my cookie privacyexcerpt" shop_gdpr.enabled = True shop_gdpr.save() # the contents should be injected in the html response = client.get(index_url) response_content = response.content.decode("utf-8") assert "gdpr-consent-warn-bar" in response_content assert shop_gdpr.cookie_banner_content in response_content assert shop_gdpr.cookie_privacy_excerpt in response_content # create cookie categories cookie_category = GDPRCookieCategory.objects.create( shop=shop, always_active=True, cookies="cookie1,cookie2,_cookie3", name="RequiredCookies", how_is_used="to make the site work" ) default_active_cookie_category = GDPRCookieCategory.objects.create( shop=shop, always_active=False, default_active=True, cookies="analyticsCookie", name="Analytics", how_is_used="to track users" ) response, soup = client.response_and_soup(index_url) response_content = response.content.decode("utf-8") assert "gdpr-consent-warn-bar" in response_content assert cookie_category.cookies in response_content assert cookie_category.name in response_content assert cookie_category.how_is_used in response_content default_active_input = soup.find("input", {"name": "cookie_category_%d" % default_active_cookie_category.pk}) assert default_active_input.has_attr("checked") # make sure no other shop has this with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop2 = factories.get_shop(identifier="shop2", status=ShopStatus.DISABLED, domain="shop2") response = client.get(index_url, HTTP_HOST=shop2.domain) response_content = response.content.decode("utf-8") assert "gdpr-consent-warn-bar" not in response_content
def test_admin_script_list(rf, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop1 = factories.get_shop(identifier="shop-1", enabled=True) shop2 = factories.get_shop(identifier="shop-2", enabled=True) shop1.staff_members.add(admin_user) shop2.staff_members.add(admin_user) script_shop1 = Script.objects.create(shop=shop1, event_identifier="order_received", name="SHOP 1", enabled=True) script_shop2 = Script.objects.create(shop=shop2, event_identifier="order_received", name="SHOP 2", enabled=True) view = ScriptEditView.as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) set_shop(request, shop2) with pytest.raises(Http404): response = view(request, pk=script_shop1.id) response = view(request, pk=script_shop2.id) assert response.status_code == 200
def test_home_tour(browser, admin_user, live_server, settings): shop = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") admin_user_2 = factories.create_random_user(is_staff=True, is_superuser=True) admin_user_2.set_password("password") admin_user_2.save() shop.staff_members.add(admin_user) shop.staff_members.add(admin_user_2) for user in [admin_user, admin_user_2]: initialize_admin_browser_test(browser, live_server, settings, username=user.username, tour_complete=False) wait_until_condition(browser, lambda x: x.is_text_present("Welcome!")) browser.visit(live_server + "/sa/home") wait_until_condition(browser, lambda x: x.is_text_present("Hi, new shop owner!"), timeout=30) wait_until_condition(browser, lambda x: x.is_element_present_by_css(".shepherd-button.btn-primary")) click_element(browser, ".shepherd-button.btn-primary") category_targets = [ ".shepherd-enabled[data-target-id='category-1'", ".shepherd-enabled[data-target-id='category-2'", ".shepherd-enabled[data-target-id='category-3'", ".shepherd-enabled[data-target-id='category-5'", ".shepherd-enabled[data-target-id='category-9'", ".shepherd-enabled[data-target-id='category-4'", ".shepherd-enabled[data-target-id='category-6'", ".shepherd-enabled[data-target-id='category-7'", ".shepherd-enabled[data-target-id='category-8'", ".shepherd-enabled#site-search", ".shepherd-enabled.shop-btn.visit-store", ] for target in category_targets: wait_until_condition(browser, lambda x: x.is_element_present_by_css(target)) move_to_element(browser, ".shepherd-button.btn-primary") browser.find_by_css(".shepherd-button.btn-primary").last.click() wait_until_condition(browser, lambda x: x.is_text_present("We're done!"), timeout=30) move_to_element(browser, ".shepherd-button.btn-primary") browser.find_by_css(".shepherd-button.btn-primary").last.click() wait_until_condition(browser, lambda x: is_tour_complete(shop, "home", user)) # check whether the tour is shown again browser.visit(live_server + "/sa/home") wait_until_condition(browser, lambda x: not x.is_text_present("Hi, new shop owner!")) browser.visit(live_server + "/logout") browser.visit(live_server + "/sa") wait_until_condition(browser, lambda x: not x.is_text_present("Hi, new shop owner!")) assert is_tour_complete(shop2, "home", user) is False
def test_manufacturer_admin_simple_shop(rf, staff_user, admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=False): shop1 = factories.get_default_shop() shop1.staff_members.add(staff_user) factories.get_shop(identifier="shop2") assert Manufacturer.objects.count() == 0 # staff user request = apply_request_middleware(rf.post("/", data=dict(name="Manuf 1")), user=staff_user) view_func = ManufacturerEditView.as_view() response = view_func(request) assert response.status_code == 302 assert Manufacturer.objects.first().shops.first() == shop1 # superuser request = apply_request_middleware(rf.post("/", data=dict(name="Manuf 2")), user=admin_user) view_func = ManufacturerEditView.as_view() response = view_func(request) assert response.status_code == 302 assert Manufacturer.objects.count() == 2 assert Manufacturer.objects.last().shops.first() == shop1
def test_edit_shared_folder(admin_user): with override_settings(E-Commerce_ENABLE_MULTIPLE_SHOPS=True): shop1 = factories.get_shop(identifier="shop1", enabled=True) shop2 = factories.get_shop(identifier="shop2", enabled=True) folder = Folder.objects.create(name="Test folder") # Shared folder folder_count = Folder.objects.count() response = _mbv_command(shop1, admin_user, {"action": "rename_folder", "id": folder.pk, "name": "Space"}) assert not response["success"] response = _mbv_command(shop1, admin_user, {"action": "delete_folder", "id": folder.pk}) assert not response["success"] # Let's make sure rename works when only one shop owns the folder media_folder = MediaFolder.objects.create(folder=folder) media_folder.shops.add(shop1) response = _mbv_command(shop1, admin_user, {"action": "rename_folder", "id": folder.pk, "name": "Space"}) assert response["success"] assert Folder.objects.get(pk=folder.pk).name == "Space" # Then add second shop for the folder and let's check and # renaming should be disabled again. media_folder.shops.add(shop2) response = _mbv_command(shop1, admin_user, {"action": "rename_folder", "id": folder.pk, "name": "Space"}) assert not response["success"] response = _mbv_command(shop1, admin_user, {"action": "delete_folder", "id": folder.pk}) assert not response["success"] response = _mbv_command(shop2, admin_user, {"action": "delete_folder", "id": folder.pk}) assert not response["success"] # Finally remove the folder as shop2 media_folder.shops.remove(shop1) response = _mbv_command(shop1, admin_user, {"action": "delete_folder", "id": folder.pk}) assert response["error"] == "Folder matching query does not exist." response = _mbv_command(shop2, admin_user, {"action": "delete_folder", "id": folder.pk}) assert response["success"] assert Folder.objects.count() == folder_count - 1
def test_basket_with_custom_shop(rf): """ Set a different shop for basket """ with override_settings(**CORE_BASKET_SETTINGS): shop1 = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") user = factories.create_random_user() request = apply_request_middleware(rf.get("/"), user=user, shop=shop1) basket_class = cached_load("E-Commerce_BASKET_CLASS_SPEC") basket = basket_class(request, "basket", shop=shop2) assert basket.shop == shop2 product_shop2 = factories.create_product("product_shop2", shop2, factories.get_default_supplier(), 10) line = basket.add_product(factories.get_default_supplier(), shop2, product_shop2, 1) assert line.shop == shop2
def test_run_multishop(): shop1 = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") event = get_initialized_test_event() step = Step(actions=[AddOrderLogEntry({ "order": {"variable": "order"}, "message": {"constant": "It Works."}, "message_identifier": {"constant": "test_run"}, })], next=StepNext.STOP) script = Script(event_identifier=event.identifier, name="Test Script", shop=shop2, enabled=True) script.set_steps([step]) script.save() # runs for shop1 - no script exists event.run(shop1) assert not event.variable_values["order"].log_entries.filter(identifier="test_run").exists() # run for shop2 - ok event.run(shop2) assert event.variable_values["order"].log_entries.filter(identifier="test_run").exists() script.delete()
def test_dashbord_tour(browser, admin_user, live_server, settings): shop = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") admin_user_2 = factories.create_random_user(is_staff=True, is_superuser=True) admin_user_2.set_password("password") admin_user_2.save() shop.staff_members.add(admin_user) shop.staff_members.add(admin_user_2) # test with admin_user 1 initialize_admin_browser_test(browser, live_server, settings, shop=shop, tour_complete=False) wait_until_condition(browser, lambda x: x.is_text_present("Welcome!")) wait_until_condition(browser, lambda x: x.is_text_present("Quicklinks")) wait_until_condition(browser, lambda x: x.is_element_present_by_css("#menu-button")) wait_until_condition(browser, lambda x: x.is_text_present("This is the dashboard for your store."), timeout=30) wait_until_condition(browser, lambda x: x.is_element_present_by_css(".shepherd-button.btn-primary")) click_element(browser, ".shepherd-button.btn-primary") wait_until_condition(browser, lambda x: not x.is_element_present_by_css(".shepherd-button")) wait_until_condition(browser, lambda x: is_tour_complete(shop, "dashboard", admin_user)) browser.visit(live_server + "/logout") browser.visit(live_server + "/sa") # test with admin_user 2 initialize_admin_browser_test(browser, live_server, settings, shop=shop, tour_complete=False, username=admin_user_2.username) wait_until_condition(browser, lambda x: x.is_text_present("Welcome!")) wait_until_condition(browser, lambda x: x.is_element_present_by_css("#menu-button")) wait_until_condition(browser, lambda x: x.is_text_present("This is the dashboard for your store."), timeout=30) wait_until_condition(browser, lambda x: x.is_element_present_by_css(".shepherd-button.btn-primary")) click_element(browser, ".shepherd-button.btn-primary") wait_until_condition(browser, lambda x: not x.is_element_present_by_css(".shepherd-button")) wait_until_condition(browser, lambda x: is_tour_complete(shop, "dashboard", admin_user_2)) # check whether the tour is shown again browser.visit(live_server + "/sa") wait_until_condition(browser, lambda x: not x.is_text_present("This is the dashboard for your store.")) assert is_tour_complete(shop2, "dashboard", admin_user) is False assert is_tour_complete(shop2, "dashboard", admin_user_2) is False
def test_supplier_price_without_selected_supplier(rf): shop = factories.get_shop() supplier1 = Supplier.objects.create(name="Test 1") supplier1.shops = [shop] supplier2 = Supplier.objects.create(name="Test 2") supplier2.shops = [shop] strategy = "E-Commerce.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy" with override_settings(E-Commerce_PRICING_MODULE="supplier_pricing", E-Commerce_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy): customer = AnonymousContact() pricing_mod = get_pricing_module() supplier1_ctx = pricing_mod.get_context_from_data(shop, customer, supplier=supplier1) supplier2_ctx = pricing_mod.get_context_from_data(shop, customer, supplier=supplier2) # Supplied by both suppliers product1_default_price = 10 product1 = factories.create_product("sku1", shop=shop, supplier=supplier1, default_price=product1_default_price) shop_product1 = product1.get_shop_instance(shop) shop_product1.suppliers.add(supplier2) # Both suppliers should get price from shop # product default price assert product1.get_price(supplier1_ctx).amount.value == product1_default_price assert product1.get_price(supplier2_ctx).amount.value == product1_default_price # Now let's add per supplier prices supplier1_price = 7 supplier2_price = 8 SupplierPrice.objects.create(shop=shop, supplier=supplier1, product=product1, amount_value=supplier1_price) SupplierPrice.objects.create(shop=shop, supplier=supplier2, product=product1, amount_value=supplier2_price) assert product1.get_price(supplier1_ctx).amount.value == supplier1_price assert product1.get_price(supplier2_ctx).amount.value == supplier2_price # Now pricing context without defined supplier # should return cheapest price context = pricing_mod.get_context_from_data(shop, customer) assert shop_product1.get_supplier().pk == supplier1.pk assert product1.get_price(context).amount.value == supplier1_price
def test_staff_authentication(): shop = factories.get_shop(True, "USD", enabled=True) staff_user = factories.create_random_user(is_staff=True) staff_user.set_password("randpw") staff_user.save() staff_user.groups = [factories.get_default_permission_group()] shop.staff_members.add(staff_user) assert staff_user in [staff for staff in shop.staff_members.all()] assert shop.status == ShopStatus.ENABLED client = SmartClient() url = reverse("E-Commerce_admin:dashboard") client.login(username=staff_user.username, password="******") response, soup = client.response_and_soup(url) assert response.status_code == 200 shop.status = ShopStatus.DISABLED shop.save() response, soup = client.response_and_soup(url) assert response.status_code == 400 assert "There is no active shop available" in soup.text
def test_suppliers_list(rf, admin_user): shop = factories.get_default_shop() shop2 = factories.get_shop(identifier="shop2") supplier1 = Supplier.objects.create(name="supplier1") supplier2 = Supplier.objects.create(name="supplier1") supplier3 = Supplier.objects.create(name="supplier1") # only supplier 1 has shop supplier1.shops.add(shop) supplier3.shops.add(shop2) list_view = SupplierListView.as_view() staff_user = factories.create_random_user("en", is_staff=True) shop.staff_members.add(staff_user) for user in [admin_user, staff_user]: request = apply_request_middleware(rf.get("/", {"jq": json.dumps({"perPage": 100, "page": 1})}), user=user) response = list_view(request) data = json.loads(response.content.decode("utf-8")) ids = [sup["_id"] for sup in data["items"]] assert supplier1.id in ids assert supplier2.id in ids
def test_usage_limit(rf): default_price = 10 request, product, basket = _init_test_for_product_with_basket(rf, default_price) discounted_price = 4 coupon_code = "TEST!2" shop = request.shop coupon = CouponCode.objects.create(code=coupon_code, active=True) coupon.shops = [shop] discount = Discount.objects.create( active=True, product=product, coupon_code=coupon, discounted_price_value=discounted_price) discount.shops.add(request.shop) # Can not use coupon code that does not exist assert not CouponCode.is_usable(shop, "SIMO", basket.customer) # The coupon code should be usable assert CouponCode.is_usable(shop, coupon_code, basket.customer) assert coupon.can_use_code(shop, basket.customer) # Can not add coupon code that is not active coupon.active = False coupon.save() assert not CouponCode.is_usable(shop, coupon_code, basket.customer) assert not coupon.can_use_code(shop, basket.customer) # Re-activate coupon code coupon.active = True coupon.save() assert CouponCode.is_usable(shop, coupon_code, basket.customer) assert coupon.can_use_code(shop, basket.customer) # Can not use coupon code that is not attached discount.coupon_code = None discount.save() assert not CouponCode.is_usable(shop, coupon_code, basket.customer) # Re-attach discount discount.coupon_code = coupon discount.save() assert CouponCode.is_usable(shop, coupon_code, basket.customer) # Coupon code needs to be attached to current shop shop2 = factories.get_shop(prices_include_tax=True) assert not CouponCode.is_usable(shop2, coupon_code, basket.customer) assert CouponCode.is_usable(shop, coupon_code, basket.customer) coupon.shops.clear() assert not CouponCode.is_usable(shop, coupon_code, basket.customer) assert not coupon.can_use_code(shop, basket.customer) coupon.shops = [shop] assert CouponCode.is_usable(shop, coupon_code, basket.customer) assert coupon.can_use_code(shop, basket.customer) # Coupon code not yet added to basket even if it is usable assert product.get_price_info(request).price == request.shop.create_price(default_price) basket.add_code(coupon) assert product.get_price_info(request).price == request.shop.create_price(discounted_price) order = factories.create_random_order() for x in range(50): coupon.use(order) assert coupon.usage_limit is None assert coupon.usages.count() == 50 assert product.get_price_info(request).price == request.shop.create_price(discounted_price) # Set coupon usage limit 50 coupon.usage_limit = 50 coupon.save() assert not CouponCode.is_usable(shop, coupon.code, order.customer) assert product.get_price_info(request).price == request.shop.create_price(default_price) # Increase limit by 5 coupon.usage_limit = 55 coupon.save() for x in range(5): assert product.get_price_info(request).price == request.shop.create_price(discounted_price) coupon.use(order) assert coupon.usages.count() == 55 assert not CouponCode.is_usable(shop, coupon.code, order.customer) assert product.get_price_info(request).price == request.shop.create_price(default_price)
def _test_discount_list_view(rf, index): shop = factories.get_shop(identifier="shop%s" % index, enabled=True) staff_user = factories.create_random_user(is_staff=True) shop.staff_members.add(staff_user) discount1 = Discount.objects.create(identifier="discount_without_effects_%s" % index) discount1.shops = [shop] discount2 = Discount.objects.create( identifier="discount_with_amount_value_only_%s" % index, discount_amount_value=20, start_datetime=now(), end_datetime=now() + datetime.timedelta(days=2)) discount2.shops = [shop] discount3 = Discount.objects.create( identifier="discount_with_amount_and_discounted_price_%s" % index, discount_amount_value=20, discounted_price_value=4, start_datetime=now(), end_datetime=now() + datetime.timedelta(days=2)) discount3.shops = [shop] discount4 = Discount.objects.create( identifier="test_with_discounted_price_and_percentage_%s" % index, discounted_price_value=4, discount_percentage=0.20, start_datetime=now(), end_datetime=now() + datetime.timedelta(days=2)) discount4.shops = [shop] view_func = DiscountListView.as_view() request = apply_request_middleware( rf.get("/", { "jq": json.dumps({"perPage": 100, "page": 1}) }), user=staff_user, shop=shop) set_shop(request, shop) response = view_func(request) if hasattr(response, "render"): response.render() assert response.status_code == 200 view_instance = DiscountListView() view_instance.request = request assert request.shop == shop assert view_instance.get_queryset().count() == 4 data = json.loads(view_instance.get(request).content.decode("UTF-8")) assert len(data["items"]) == 4 discount1_data = [item for item in data["items"] if item["_id"] == discount1.pk][0] assert discount1_data["discount_effect"] == "-" discount2_data = [item for item in data["items"] if item["_id"] == discount2.pk][0] assert len(discount2_data["discount_effect"].split(",")) == 1 assert "20" in discount2_data["discount_effect"] discount3_data = [item for item in data["items"] if item["_id"] == discount3.pk][0] assert len(discount3_data["discount_effect"].split(",")) == 2 assert "20" in discount3_data["discount_effect"] assert "4" in discount3_data["discount_effect"] discount4_data = [item for item in data["items"] if item["_id"] == discount4.pk][0] assert len(discount4_data["discount_effect"].split(",")) == 2 assert "20" in discount4_data["discount_effect"] assert "4" in discount4_data["discount_effect"]