Пример #1
0
def add_product_image(product):
    media1 = ProductMedia.objects.create(product=product,
                                         kind=ProductMediaKind.IMAGE,
                                         file=get_random_filer_image(),
                                         enabled=True,
                                         public=True)
    media2 = ProductMedia.objects.create(product=product,
                                         kind=ProductMediaKind.IMAGE,
                                         file=get_random_filer_image(),
                                         enabled=True,
                                         public=True)
    product.primary_image = media1
    product.media.add(media2)
    product.save()
def add_product_image(product):
    media1 = ProductMedia.objects.create(product=product,
                                         kind=ProductMediaKind.IMAGE,
                                         file=get_random_filer_image(),
                                         enabled=True,
                                         public=True)
    media2 = ProductMedia.objects.create(product=product,
                                         kind=ProductMediaKind.IMAGE,
                                         file=get_random_filer_image(),
                                         enabled=True,
                                         public=True)
    product.primary_image = media1
    product.media.add(media2)
    product.save()
Пример #3
0
def test_admin_form_part(admin_user):
    factories.get_default_shop()
    client = SmartClient()
    client.login(username=admin_user.username, password="******")

    assert Page.objects.count() == 0
    response, soup = client.response_and_soup(
        reverse("shuup_admin:simple_cms.page.new"))
    assert response.status_code == 200
    payload = extract_form_fields(soup)

    # do some cleaning
    for key in payload.keys():
        if payload[key] is None:
            payload[key] = ""

    # create 9 articles
    for i in range(9):
        payload.update({
            "base-title__en": "My Article %d" % i,
            "base-url__en": "my-article-%d" % i,
            "base-available_from": "0%s/01/2018 00:00:00" % (i + 1),
            "base-available_to": "0%s/01/2019 00:00:00" % (i + 1),
            "base-content__en": "Some content here %d" % i,
            "base-template_name": "shuup_cms_blog/blog_page.jinja",
            "blog-is_blog_article": True,
            "blog-image": factories.get_random_filer_image().pk,
            "blog-small_description__en": "small description %d" % i
        })
        response = client.post(reverse("shuup_admin:simple_cms.page.new"),
                               data=payload)
        assert response.status_code == 302
        assert Page.objects.count() == (i + 1)

        response, soup = client.response_and_soup(
            reverse("shuup:cms_page",
                    kwargs=dict(url=payload["base-url__en"])))
        assert response.status_code == 200
        assert soup.find("div", {"class": "article-features"})

    # update blog image of the last page
    payload.update({
        "blog-image": factories.get_random_filer_image().pk,
    })
    response = client.post(reverse("shuup_admin:simple_cms.page.edit",
                                   kwargs=dict(pk=Page.objects.last().pk)),
                           data=payload)
    assert response.status_code == 302
def test_send_product_media_image(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    image = get_random_filer_image()
    with open(image.path, "rb") as f:
        img_base64 = base64.b64encode(f.read()).decode()
        uri = "data:image/jpeg;base64,{}".format(img_base64)

    media_data = {
        "translations": {"en": {"title": "My image title", "description": "My image description"}},
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri,
        "path": "/what/the/folder",
    }
    response = client.post(
        "/api/shuup/product/%d/add_media/" % product.pk, content_type="application/json", data=json.dumps(media_data)
    )
    assert response.status_code == status.HTTP_201_CREATED
    assert product.media.count() == 1
    product_media = product.media.first()
    assert product_media.title == media_data["translations"]["en"]["title"]
    assert product_media.description == media_data["translations"]["en"]["description"]
    assert product_media.shops.count() == len(media_data["shops"])
    assert set(product_media.shops.all().values_list("pk", flat=True)) >= set(media_data["shops"])
    assert product_media.kind.value == media_data["kind"]
    assert product_media.file.folder.pretty_logical_path == media_data["path"]
    with open(product_media.file.path, "rb") as f:
        assert img_base64 == base64.b64encode(f.read()).decode()
Пример #5
0
def test_summernote_editor_picture(browser, admin_user, live_server, settings):
    activate("en")
    factories.get_default_shop()
    factories.get_default_product_type()
    factories.get_default_sales_unit()
    factories.get_default_tax_class()
    filer_image = factories.get_random_filer_image()

    initialize_admin_browser_test(browser, live_server, settings)
    browser.driver.set_window_size(1920, 1080)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))
    wait_until_condition(browser, condition=lambda x: x.is_text_present("New shop product"))

    img_icon_selector = "#id_base-description__en-editor-wrap i[class='note-icon-picture']"
    move_to_element(browser, img_icon_selector)
    click_element(browser, img_icon_selector)
    wait_until_condition(browser, lambda b: len(b.windows) == 2)

    # change to the media browser window
    browser.windows.current = browser.windows[1]

    # click to select the picture
    wait_until_appeared(browser, "a.file-preview")
    click_element(browser, "a.file-preview")

    # back to the main window
    wait_until_condition(browser, lambda b: len(b.windows) == 1)
    browser.windows.current = browser.windows[0]

    # make sure the image was added to the editor
    wait_until_appeared(
        browser, "#id_base-description__en-editor-wrap .note-editable img[src='%s']" % filer_image.url, timeout=20
    )
Пример #6
0
def test_carousel_create(browser, admin_user, live_server, settings):
    shop = factories.get_default_shop()
    filer_image = factories.get_random_filer_image()
    factories.get_default_category()

    initialize_admin_browser_test(browser, live_server, settings, shop=shop)
    wait_until_condition(browser, lambda x: x.is_text_present("Welcome!"))

    assert not Carousel.objects.exists()

    browser.visit(live_server + "/sa/carousels/new")
    wait_until_condition(browser, lambda x: x.is_text_present("New Carousel"))
    browser.fill("base-name", "Carrot")
    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")

    assert Carousel.objects.count() == 1
    carousel = Carousel.objects.first()

    browser.visit(live_server + "/sa/carousels/%d/" % carousel.pk)
    time.sleep(1)
    wait_until_condition(browser, lambda x: x.is_text_present(carousel.name))
    click_element(browser, "a[href='#slides-section']")
    wait_until_appeared(browser, ".slide-add-new-panel")

    # add 1 slide
    click_element(browser, ".slide-add-new-panel")
    wait_until_condition(browser, lambda x: x.is_text_present("Slide 1"))
    wait_until_appeared(browser, "a[href='#collapse1']")
    click_element(browser, "a[href='#collapse1']")

    browser.find_by_css(
        "#slide_1-en [name='slides-__slide_prefix__-caption__en']").fill(
            "New Slide")
    click_element(browser,
                  "[name='slides-__slide_prefix__-category_link'] + .select2")
    wait_until_appeared(
        browser,
        ".select2-container #select2-id_slides-__slide_prefix__-category_link-results li"
    )
    click_element(
        browser,
        ".select2-container #select2-id_slides-__slide_prefix__-category_link-results li:last-child"
    )

    browser.find_by_css("#slide_1-en [data-dropzone='true']").click()
    wait_until_condition(browser, lambda b: len(b.windows) == 2)
    # change to the media browser window
    browser.windows.current = browser.windows[1]
    # click to select the picture
    wait_until_appeared(browser, "a.file-preview")
    click_element(browser, "a.file-preview")
    # back to the main window
    wait_until_condition(browser, lambda b: len(b.windows) == 1)
    browser.windows.current = browser.windows[0]
    wait_until_appeared(browser, ".dz-image img[alt='%s']" % filer_image.name)

    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")
Пример #7
0
def test_saved_articles(rf):
    shop = factories.get_default_shop()
    articles = []

    # create 3 blog pages
    for i in range(10):
        article = Page.objects.create(
            shop=shop,
            title="Article %d" % i,
            url="blog-%d" % i,
            available_from=(now() - timedelta(days=10)),
            available_to=(now() + timedelta(days=10)),
            content="Content %d" % i,
            template_name="shuup_cms_blog/blog_page.jinja")
        BlogArticle.objects.create(page=article,
                                   is_blog_article=True,
                                   image=factories.get_random_filer_image(),
                                   small_description="description %d" % i)
        articles.append(article)

    user = factories.create_random_user()
    user.set_password("pass")
    contact = get_person_contact(user)

    assert not contact.options
    request = apply_request_middleware(rf.get("/"), user=user)

    # save article #1
    response = AddSavedArticlesView.as_view()(request, pk=articles[0].pk)
    assert response.status_code == 302
    contact.refresh_from_db()
    options = json.loads(contact.options) if isinstance(
        contact.options, str) else contact.options
    assert options["saved_articles"] == [articles[0].pk]

    # save article #3
    response = AddSavedArticlesView.as_view()(request, pk=articles[2].pk)
    assert response.status_code == 302
    contact.refresh_from_db()
    options = json.loads(contact.options) if isinstance(
        contact.options, str) else contact.options
    assert options["saved_articles"] == [articles[0].pk, articles[2].pk]

    # list saved articles
    response = SavedArticlesView.as_view()(request)
    assert response.status_code == 200
    response.render()
    content = response.content.decode("utf-8")
    assert 'data-article="%d"' % articles[0].pk in content
    assert 'data-article="%d"' % articles[2].pk in content

    # removed saved article #3
    response = RemoveSavedArticlesView.as_view()(request, pk=articles[2].pk)
    assert response.status_code == 302
    contact.refresh_from_db()
    options = json.loads(contact.options) if isinstance(
        contact.options, str) else contact.options
    assert options["saved_articles"] == [articles[0].pk]
Пример #8
0
def create_images_for_product(shop, product):
    medias = []
    for _ in range(3):
        product_media = ProductMedia.objects.create(product=product, kind=ProductMediaKind.IMAGE)
        product_media.file = factories.get_random_filer_image()
        product_media.save()
        product_media.shops.add(shop)
        medias.append(product_media)
    return medias
Пример #9
0
def test_thumbnail_cache():
    image1 = factories.get_random_filer_image()
    image2 = factories.get_random_filer_image()
    media = ProductMedia.objects.create(product=factories.get_default_product(), file=image2)

    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(image1)
    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and cached_url == url

    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(media)
    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and cached_url == url

    img_url = "http://www.shuup.com/logo.png"
    cache_key, cached_url = _get_cached_thumbnail_url(img_url, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(img_url)
    cache_key, cached_url = _get_cached_thumbnail_url(img_url, alias=None, generate=True)
    assert cache_key and cached_url == url

    source = Thumbnailer(file=BytesIO(TEST_PNG), name="logo.png")
    source.url = "/media/logo.png"
    cache_key, cached_url = _get_cached_thumbnail_url(source, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(source)
    cache_key, cached_url = _get_cached_thumbnail_url(source, alias=None, generate=True)
    assert cache_key and cached_url == url

    # check whether caches are bumped
    image1.save()
    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and not cached_url

    media.save()
    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and not cached_url

    media.delete()
    image1.delete()
    image2.delete()
Пример #10
0
def test_thumbnail_cache():
    image1 = factories.get_random_filer_image()
    image2 = factories.get_random_filer_image()
    media = ProductMedia.objects.create(product=factories.get_default_product(), file=image2)

    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(image1)
    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and cached_url == url

    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(media)
    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and cached_url == url

    img_url = "http://www.shuup.com/logo.png"
    cache_key, cached_url = _get_cached_thumbnail_url(img_url, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(img_url)
    cache_key, cached_url = _get_cached_thumbnail_url(img_url, alias=None, generate=True)
    assert cache_key and cached_url == url

    source = Thumbnailer(file=BytesIO(TEST_PNG), name="logo.png")
    source.url = '/media/logo.png'
    cache_key, cached_url = _get_cached_thumbnail_url(source, alias=None, generate=True)
    assert cache_key and not cached_url
    url = thumbnail(source)
    cache_key, cached_url = _get_cached_thumbnail_url(source, alias=None, generate=True)
    assert cache_key and cached_url == url

    # check whether caches are bumped
    image1.save()
    cache_key, cached_url = _get_cached_thumbnail_url(image1, alias=None, generate=True)
    assert cache_key and not cached_url

    media.save()
    cache_key, cached_url = _get_cached_thumbnail_url(media, alias=None, generate=True)
    assert cache_key and not cached_url

    media.delete()
    image1.delete()
    image2.delete()
def test_products_all_shops(admin_user):
    shop1 = get_default_shop()
    shop1.logo = get_random_filer_image()
    shop1.save()

    person1 = create_random_person()
    person1.user = admin_user
    person1.save()

    shop2 = Shop.objects.create()
    shop2.favicon = get_random_filer_image()
    shop2.save()
    supplier1 = create_simple_supplier("supplier1")
    supplier2 = create_simple_supplier("supplier2")

    # create 2 products for shop2
    product1 = create_product("product1", shop=shop1, supplier=supplier1)
    product2 = create_product("product2", shop=shop2, supplier=supplier2)
    product3 = create_product("product3", shop=shop2, supplier=supplier1)

    # list all orderable products - 2 just created are for shop2
    request = get_request("/api/shuup/front/shop_products/", admin_user,
                          person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    products = json.loads(response.content.decode("utf-8"))
    assert len(products) == 3

    assert products[0]["product_id"] == product1.id
    assert products[0]["shop"]["id"] == shop1.id
    assert products[0]["shop"]["logo"] == request.build_absolute_uri(
        shop1.logo.url)

    assert products[1]["product_id"] == product2.id
    assert products[1]["shop"]["id"] == shop2.id
    assert products[1]["shop"]["favicon"] == request.build_absolute_uri(
        shop2.favicon.url)

    assert products[2]["product_id"] == product3.id
    assert products[2]["shop"]["id"] == shop2.id
    assert products[2]["shop"]["favicon"] == request.build_absolute_uri(
        shop2.favicon.url)
Пример #12
0
def add_product_image(product, purchased=False):
    media1 = ProductMedia.objects.create(
        product=product,
        kind=ProductMediaKind.IMAGE,
        file=get_random_filer_image(),
        enabled=True,
        public=True,
        purchased=purchased,
    )
    media2 = ProductMedia.objects.create(
        product=product,
        kind=ProductMediaKind.IMAGE,
        file=get_random_filer_image(),
        enabled=True,
        public=True,
        purchased=purchased,
    )
    product.primary_image = media1
    product.media.add(media2)
    product.save()
    return (media1, media2)
Пример #13
0
def create_categories(shop):
    Category.objects.create(
        name="Category 1", status=CategoryStatus.VISIBLE, image=factories.get_random_filer_image())
    category2 = Category.objects.create(
        name="Category 2", description="parent", slug="cat-2", status=CategoryStatus.VISIBLE)
    Category.objects.create(
        name="Category 2.1", description="visible", slug="cat-2-1", status=CategoryStatus.VISIBLE, parent=category2)
    Category.objects.create(
        name="Category 2.2", description="invisible", slug="cat-2-2", status=CategoryStatus.INVISIBLE, parent=category2)

    for category in Category.objects.all():
        category.shops.add(shop)
Пример #14
0
def test_products_all_shops(admin_user):
    shop1 = get_default_shop()
    shop1.logo = get_random_filer_image()
    shop1.save()

    person1 = create_random_person()
    person1.user = admin_user
    person1.save()

    shop2 = Shop.objects.create(status=ShopStatus.ENABLED)
    shop2.favicon = get_random_filer_image()
    shop2.save()
    supplier1 = create_simple_supplier("supplier1")
    supplier2 = create_simple_supplier("supplier2")

    # create 2 products for shop2
    product1 = create_product("product1", shop=shop1, supplier=supplier1)
    product2 = create_product("product2", shop=shop2, supplier=supplier2)
    product3 = create_product("product3", shop=shop2, supplier=supplier1)

    # list all orderable products - 2 just created are for shop2
    request = get_request("/api/shuup/front/shop_products/", admin_user, person1)
    response = FrontShopProductViewSet.as_view({"get": "list"})(request)
    response.render()
    products = json.loads(response.content.decode("utf-8"))
    assert len(products) == 3

    assert products[0]["product_id"] == product1.id
    assert products[0]["shop"]["id"] == shop1.id
    assert products[0]["shop"]["logo"] == request.build_absolute_uri(shop1.logo.url)

    assert products[1]["product_id"] == product2.id
    assert products[1]["shop"]["id"] == shop2.id
    assert products[1]["shop"]["favicon"] == request.build_absolute_uri(shop2.favicon.url)

    assert products[2]["product_id"] == product3.id
    assert products[2]["shop"]["id"] == shop2.id
    assert products[2]["shop"]["favicon"] == request.build_absolute_uri(shop2.favicon.url)
def test_send_product_media_erros(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    media_data = {
        "translations": {
            "en": {
                "title": "My image title",
                "description": "My image description"
            }
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value
    }

    # do not set file or external_url
    response = client.post("/api/shuup/product/%d/add_media/" % product.pk,
                           content_type="application/json",
                           data=json.dumps(media_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    response_data = json.loads(response.content.decode("utf-8"))
    assert "You may set either `file` or `external_url`." in response_data[
        "non_field_errors"]

    # do not set path for file
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)

    media_data = {
        "translations": {
            "en": {
                "title": "My image title",
                "description": "My image description"
            }
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri
    }
    response = client.post("/api/shuup/product/%d/add_media/" % product.pk,
                           content_type="application/json",
                           data=json.dumps(media_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    response_data = json.loads(response.content.decode("utf-8"))
    assert "`path` is required when `file` is set." in response_data[
        "non_field_errors"]
Пример #16
0
def test_carousel_create(browser, admin_user, live_server, settings):
    shop = factories.get_default_shop()
    filer_image = factories.get_random_filer_image()
    factories.get_default_category()

    initialize_admin_browser_test(browser, live_server, settings, shop=shop)
    wait_until_condition(browser, lambda x: x.is_text_present("Welcome!"))

    assert not Carousel.objects.exists()

    browser.visit(live_server + "/sa/carousels/new")
    wait_until_condition(browser, lambda x: x.is_text_present("New Carousel"))
    browser.fill("base-name", "Carrot")
    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")

    assert Carousel.objects.count() == 1
    carousel = Carousel.objects.first()

    browser.visit(live_server + "/sa/carousels/%d/" % carousel.pk)
    wait_until_condition(browser, lambda x: x.is_text_present(carousel.name))
    click_element(browser, "a[href='#slides-section']")
    wait_until_appeared(browser, ".slide-add-new-panel")

    # add 1 slide
    click_element(browser, ".slide-add-new-panel")
    wait_until_condition(browser, lambda x: x.is_text_present("Slide 1"))
    wait_until_appeared(browser, "a[href='#collapse1']")
    click_element(browser, "a[href='#collapse1']")

    browser.find_by_css("#slide_1-en [name='slides-__slide_prefix__-caption__en']").fill("New Slide")
    click_element(browser, "[name='slides-__slide_prefix__-category_link'] + .select2")
    wait_until_appeared(browser, ".select2-container #select2-id_slides-__slide_prefix__-category_link-results li")
    click_element(browser, ".select2-container #select2-id_slides-__slide_prefix__-category_link-results li:last-child")

    browser.find_by_css("#slide_1-en [data-dropzone='true']").click()
    wait_until_condition(browser, lambda b: len(b.windows) == 2)
    # change to the media browser window
    browser.windows.current = browser.windows[1]
    # click to select the picture
    wait_until_appeared(browser, "a.file-preview")
    click_element(browser, "a.file-preview")
    # back to the main window
    wait_until_condition(browser, lambda b: len(b.windows) == 1)
    browser.windows.current = browser.windows[0]
    wait_until_appeared(browser, ".dz-image img[alt='%s']" % filer_image.name)

    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")
Пример #17
0
def test_product_copy(rf, admin_user):
    factories.get_default_attribute_set()
    shop = factories.get_default_shop()
    supplier = factories.get_default_supplier()
    request = apply_request_middleware(rf.get("/", {}), user=admin_user)
    price = 10
    product = factories.create_product("product",
                                       shop=shop,
                                       supplier=supplier,
                                       default_price=price)

    attribute_key = "author"
    attribute_value = "batman"
    product.set_attribute_value(attribute_key, attribute_value)

    media = ProductMedia.objects.create(
        product=product,
        kind=ProductMediaKind.IMAGE,
        file=factories.get_random_filer_image(),
        enabled=True,
        public=True)
    product.primary_image = media
    product.media.add(media)
    product.save()

    category = factories.get_default_category()
    shop_product = product.get_shop_instance(shop)
    shop_product.primary_category = category
    shop_product.save()
    shop_product.categories.set([category])

    assert Product.objects.count() == 1
    view_func = ProductCopyView.as_view()
    response = view_func(request, pk=shop_product.pk)
    if hasattr(response, "render"):
        response.render()

    assert Product.objects.count() == 2
    new_product = Product.objects.first()
    new_shop_product = new_product.get_shop_instance(shop)
    assert new_product
    assert new_product.pk != product.pk
    assert new_product.name == product.name
    assert new_shop_product
    assert new_shop_product.suppliers.first() == shop_product.suppliers.first()
    assert new_shop_product.categories.first(
    ) == shop_product.categories.first()
    assert new_product.media.first().file.pk == product.media.first().file.pk
    assert new_product.get_attribute_value(attribute_key) == attribute_value
Пример #18
0
def get_product(sku, shop):
    product = Product.objects.filter(sku=sku).first()
    if not product:
        product = create_product(sku)
        image = get_random_filer_image()
        media = ProductMedia.objects.create(
            product=product, kind=ProductMediaKind.IMAGE, file=image, enabled=True,
            public=True)
        product.primary_image = media
        product.save()
        assert product.primary_image_id
        sp = ShopProduct.objects.create(
            product=product, shop=shop, visibility=ShopProductVisibility.ALWAYS_VISIBLE
        )
        sp.suppliers.add(get_default_supplier())
    return product
Пример #19
0
def get_product(sku, shop):
    product = Product.objects.filter(sku=sku).first()
    if not product:
        product = create_product(sku)
        image = get_random_filer_image()
        media = ProductMedia.objects.create(
            product=product, kind=ProductMediaKind.IMAGE, file=image, enabled=True,
            public=True)
        product.primary_image = media
        product.save()
        assert product.primary_image_id
        sp = ShopProduct.objects.create(
            product=product, shop=shop, visibility=ShopProductVisibility.ALWAYS_VISIBLE
        )
        sp.suppliers.add(get_default_supplier())
    return product
Пример #20
0
def test_send_product_media_erros(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    media_data = {
        "translations": {
            "en": {"title": "My image title", "description": "My image description"}
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value
    }

    # do not set file or external_url
    response = client.post("/api/shuup/product/%d/add_media/" % product.pk,
                           content_type="application/json",
                           data=json.dumps(media_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    response_data = json.loads(response.content.decode("utf-8"))
    assert "You may set either `file` or `external_url`." in response_data["non_field_errors"]

    # do not set path for file
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)

    media_data = {
        "translations": {
            "en": {"title": "My image title", "description": "My image description"}
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri
    }
    response = client.post("/api/shuup/product/%d/add_media/" % product.pk,
                           content_type="application/json",
                           data=json.dumps(media_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    response_data = json.loads(response.content.decode("utf-8"))
    assert "`path` is required when `file` is set." in response_data["non_field_errors"]
Пример #21
0
def test_summernote_editor_picture(browser, admin_user, live_server, settings):
    activate("en")
    factories.get_default_shop()
    factories.get_default_product_type()
    factories.get_default_sales_unit()
    factories.get_default_tax_class()
    filer_image = factories.get_random_filer_image()
    configuration.set(None, "shuup_product_tour_complete", True)

    initialize_admin_browser_test(browser, live_server, settings)
    browser.driver.set_window_size(1920, 1080)

    url = reverse("shuup_admin:shop_product.new")
    browser.visit("%s%s" % (live_server, url))

    wait_until_appeared(
        browser,
        "#id_base-description__en-editor-wrap button[aria-label='Picture']")
    click_element(
        browser,
        "#id_base-description__en-editor-wrap button[aria-label='Picture']")
    wait_until_condition(browser, lambda b: len(b.windows) == 2)

    # change to the media browser window
    browser.windows.current = browser.windows[1]

    # click to select the picture
    wait_until_appeared(browser, "a.file-preview")
    click_element(browser, "a.file-preview")

    # back to the main window
    wait_until_condition(browser, lambda b: len(b.windows) == 1)
    browser.windows.current = browser.windows[0]

    # make sure the image was added to the editor
    wait_until_appeared(
        browser,
        "#id_base-description__en-editor-wrap .note-editable img[src='%s']" %
        filer_image.url,
        timeout=20)
Пример #22
0
def test_send_product_media_image(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(f.read()).decode()
        uri = "data:image/jpeg;base64,{}".format(img_base64)

    media_data = {
        "translations": {
            "en": {
                "title": "My image title",
                "description": "My image description"
            }
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri,
        "path": "/what/the/folder"
    }
    response = client.post("/api/shuup/product/%d/add_media/" % product.pk,
                           content_type="application/json",
                           data=json.dumps(media_data))
    assert response.status_code == status.HTTP_201_CREATED
    assert product.media.count() == 1
    product_media = product.media.first()
    assert product_media.title == media_data["translations"]["en"]["title"]
    assert product_media.description == media_data["translations"]["en"]["description"]
    assert product_media.shops.count() == len(media_data["shops"])
    assert set(product_media.shops.all().values_list("pk", flat=True)) >= set(media_data["shops"])
    assert product_media.kind.value == media_data["kind"]
    assert product_media.file.folder.pretty_logical_path == media_data["path"]
    with open(product_media.file.path, 'rb') as f:
        assert img_base64 == base64.b64encode(f.read()).decode()
Пример #23
0
def test_opengrah_admin(admin_user):
    shop = factories.get_default_shop()
    client = SmartClient()
    client.login(username=admin_user.username, password="******")

    assert Page.objects.count() == 0
    response, soup = client.response_and_soup(
        reverse("shuup_admin:simple_cms.page.new"))
    assert response.status_code == 200

    # save simple page
    payload = {
        "base-title__en": "My Article",
        "base-url__en": "my-article",
        "base-available_from": "01/01/2018 00:00:00",
        "base-available_to": "01/01/2019 00:00:00",
        "base-content__en": "Some content here",
    }
    response = client.post(reverse("shuup_admin:simple_cms.page.new"),
                           data=payload)
    assert response.status_code == 302
    assert Page.objects.count() == 1
    page = Page.objects.first()

    # check the rendered page in front
    page_url = reverse("shuup:cms_page", kwargs=dict(url=page.url))
    response, soup = client.response_and_soup(page_url)
    assert response.status_code == 200
    assert soup.find("meta",
                     attrs={
                         "property": "og:site_name",
                         "content": shop.public_name
                     })
    assert soup.find("meta", attrs={"property": "og:url"})
    assert soup.find("meta",
                     attrs={
                         "property": "og:title",
                         "content": page.title
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "og:type",
                         "content": "website"
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "og:description",
                         "content": page.content
                     })

    # set some open graph info
    random_image = factories.get_random_filer_image()
    payload.update({
        "opengraph-title__en": "OG Title",
        "opengraph-tags__en": "OG Tags",
        "opengraph-section__en": "OG Section",
        "opengraph-description__en": "OG DESC",
        "opengraph-article_author__en": "OG AuthorName",
        "opengraph-og_type": PageOpenGraphType.Article.value,
        "opengraph-image": random_image.pk,
    })

    response = client.post(reverse("shuup_admin:simple_cms.page.edit",
                                   kwargs=dict(pk=page.pk)),
                           data=payload)
    assert response.status_code == 302
    assert Page.objects.count() == 1
    page = Page.objects.first()
    str(page.open_graph)  # just for coverage
    assert page.open_graph.title == payload["opengraph-title__en"]
    assert page.open_graph.tags == payload["opengraph-tags__en"]
    assert page.open_graph.section == payload["opengraph-section__en"]
    assert page.open_graph.description == payload["opengraph-description__en"]
    assert page.open_graph.og_type.value == payload["opengraph-og_type"]
    assert page.open_graph.article_author == payload[
        "opengraph-article_author__en"]

    # check the rendered page in front
    page_url = reverse("shuup:cms_page", kwargs=dict(url=page.url))
    response, soup = client.response_and_soup(page_url)
    assert response.status_code == 200
    assert soup.find("meta",
                     attrs={
                         "property": "og:title",
                         "content": payload["opengraph-title__en"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "og:type",
                         "content": payload["opengraph-og_type"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "og:description",
                         "content": payload["opengraph-description__en"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "og:type",
                         "content": payload["opengraph-og_type"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:tag",
                         "content": payload["opengraph-tags__en"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:section",
                         "content": payload["opengraph-section__en"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:author",
                         "content": payload["opengraph-article_author__en"]
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:modified_time",
                         "content": page.modified_on.isoformat()
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:published_time",
                         "content": page.available_from.isoformat()
                     })
    assert soup.find("meta",
                     attrs={
                         "property": "article:expiration_time",
                         "content": page.available_to.isoformat()
                     })
    img_node = soup.find("meta", attrs={"property": "og:image"})
    assert img_node.attrs["content"].endswith(random_image.url)
Пример #24
0
def test_plugin():
    shop = factories.get_default_shop()
    set_current_theme(ClassicGrayTheme.identifier, shop)

    blog_one_page = Page.objects.create(
        shop=shop,
        title="Blog One",
        url="blog_one",
        available_from=(now() - timedelta(days=10)),
        available_to=(now() + timedelta(days=10)),
        content="")

    blog_two_page = Page.objects.create(
        shop=shop,
        title="Blog Two",
        url="blog_two",
        available_from=(now() - timedelta(days=10)),
        available_to=(now() + timedelta(days=10)),
        content="")
    # create 10 blog pages
    for page in [blog_one_page, blog_two_page]:
        for i in range(10):
            article = Page.objects.create(
                shop=shop,
                title="Article %d %s" % (i, page.title),
                url="blog-%d-%s" % (i, page.url),
                available_from=(now() - timedelta(days=10)),
                available_to=(now() + timedelta(days=10)),
                content="Content %d" % i,
                template_name="shuup_cms_blog/blog_page.jinja",
                parent=page)
            BlogArticle.objects.create(
                page=article,
                is_blog_article=True,
                image=factories.get_random_filer_image(),
                small_description="description %d" % i)

    # create 3 non blog post pages
    for i in range(3):
        article = Page.objects.create(
            shop=shop,
            title="Nothing %d" % i,
            url="non-%d" % i,
            available_from=(now() - timedelta(days=10)),
            available_to=(now() + timedelta(days=10)),
            content="content %i" % i)

    theme = get_current_theme(shop)
    view_config = ViewConfig(theme=theme,
                             shop=shop,
                             view_name="PageView",
                             draft=True)

    placeholder_name = "cms_page"
    context_one = {"page": blog_one_page}
    context_two = {"page": blog_two_page}

    layout_one = view_config.get_placeholder_layout(PageLayout,
                                                    placeholder_name,
                                                    context=context_one)
    layout_two = view_config.get_placeholder_layout(PageLayout,
                                                    placeholder_name,
                                                    context=context_two)

    assert isinstance(layout_one, PageLayout)
    assert isinstance(layout_two, PageLayout)

    assert layout_one.get_help_text({}) == ""
    assert layout_two.get_help_text({}) == ""

    assert blog_one_page.title in layout_two.get_help_text(context_one)
    assert blog_two_page.title in layout_two.get_help_text(context_two)

    serialized_one = layout_one.serialize()
    serialized_two = layout_two.serialize()

    assert len(serialized_one["rows"]) == 0
    assert len(serialized_two["rows"]) == 0

    assert serialized_one["name"] == placeholder_name
    assert serialized_two["name"] == placeholder_name

    layout_one.begin_column({"sm": 12})
    layout_two.begin_column({"sm": 12})

    layout_one.add_plugin(ShuupCMSBlogArticleListPlugin.identifier,
                          {"blog_page": blog_one_page.pk})
    layout_two.add_plugin(ShuupCMSBlogArticleListPlugin.identifier,
                          {"blog_page": blog_two_page.pk})

    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout_one, context_one),
        layout_one)
    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout_two, context_two),
        layout_two)
    view_config.publish()

    client = SmartClient()
    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": blog_one_page.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 10

    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": blog_two_page.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 10

    article_one = Page.objects.create(
        shop=shop,
        title="Article test",
        url="blog-test",
        available_from=(now() - timedelta(days=10)),
        available_to=(now() + timedelta(days=10)),
        content="Content test",
        template_name=
        "shuup_cms_blog/blog_page.jinja",  # Add an article without a parent
    )
    BlogArticle.objects.create(page=article_one,
                               is_blog_article=True,
                               image=factories.get_random_filer_image(),
                               small_description="description test")
    article_two = Page.objects.create(
        shop=shop,
        title="Article test 2",
        url="blog-test-2",
        available_from=(now() - timedelta(days=10)),
        available_to=(now() + timedelta(days=10)),
        content="Content test 2",
        template_name=
        "shuup_cms_blog/blog_page.jinja",  # Add an article without a parent
    )
    BlogArticle.objects.create(page=article_two,
                               is_blog_article=True,
                               image=factories.get_random_filer_image(),
                               small_description="description test 2")
    view_config = ViewConfig(theme=theme,
                             shop=shop,
                             view_name="PageView",
                             draft=True)

    # No blog page set means that only articles with no parent will be shown
    layout_two.add_plugin(ShuupCMSBlogArticleListPlugin.identifier, {})
    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout_two, context_two),
        layout_two)
    view_config.publish()

    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": blog_two_page.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 2

    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": article_one.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 1
    assert soup.find("div", {
        "class": "article-title"
    }).text == article_two.title

    article_one.soft_delete()  # Delete the article that has no parent
    article_two.soft_delete()  # Delete the article that has no parent

    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": blog_two_page.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 0

    article_with_parent = Page.objects.filter(parent=blog_one_page).first()
    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": article_with_parent.url}))
    assert response.status_code == 200
    assert len(soup.find_all(
        "a",
        {"class": "article-card"})) == 9  # Assert there are 9 articles shown
    article_card_titles = soup.find_all("div", {"class": "article-title"})
    article_card_titles = [title.text for title in article_card_titles]
    # Assert that the current visited article (article_with_parent) is not visible in Related articles
    assert article_with_parent.title not in article_card_titles
Пример #25
0
def test_manufacturer_api(admin_user):
    get_default_shop()
    client = APIClient()
    client.force_authenticate(user=admin_user)
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)
    manufacturer_data = {
        "name": "manu 1",
        "url": "http://www.google.com",
        "logo_path" : "/this/not/needed",
        "logo" : uri
    }
    response = client.post("/api/shuup/manufacturer/",
                           content_type="application/json",
                           data=json.dumps(manufacturer_data))
    assert response.status_code == status.HTTP_201_CREATED
    manufacturer = Manufacturer.objects.first()
    assert manufacturer.name == manufacturer_data["name"]
    assert manufacturer.url == manufacturer_data["url"]
    assert manufacturer.logo.folder.pretty_logical_path == manufacturer_data["logo_path"]
    with open(manufacturer.logo.path, 'rb') as f:
        assert img_base64 == base64.b64encode(f.read()).decode()

    manufacturer_data.pop("logo_path") # Test error when not sending a path


    response = client.post("/api/shuup/manufacturer/",
                           content_type="application/json",
                           data=json.dumps(manufacturer_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    data = json.loads(response.content.decode("utf-8"))
    assert data["non_field_errors"][0] == "Path is required when sending a manufacturer logo."

    manufacturer_data["logo_path"] = "/second/path" # Testing second manufacturer
    manufacturer_data["name"] = "name 2"
    manufacturer_data["url"] = "http://yahoo.com"

    response = client.put("/api/shuup/manufacturer/%d/" % manufacturer.id,
                          content_type="application/json",
                          data=json.dumps(manufacturer_data))
    assert response.status_code == status.HTTP_200_OK
    manufacturer = Manufacturer.objects.first()
    assert manufacturer.name == manufacturer_data["name"]
    assert manufacturer.url == manufacturer_data["url"]
    response = client.get("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert manufacturer.name == data["name"]
    assert manufacturer.url == data["url"]

    response = client.get("/api/shuup/manufacturer/")
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert manufacturer.name == data[0]["name"]
    assert manufacturer.url == data[0]["url"]

    response = client.delete("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert Manufacturer.objects.count() == 0

    # create a product and relate it to a manufacturer
    product = create_product("product with manufacturer")
    manufacturer = Manufacturer.objects.create()
    product.manufacturer = manufacturer
    product.save()

    # shouldn't be possible to delete a manufacturer with a related product
    response = client.delete("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    assert "This object can not be deleted because it is referenced by" in response.content.decode("utf-8")
    assert Manufacturer.objects.count() == 1
def test_product_media_api(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    # create 2 images for product, 1 with contents, other with external url
    image = get_random_filer_image()
    media = ProductMedia.objects.create(product=product,
                                        kind=ProductMediaKind.IMAGE,
                                        file=image,
                                        enabled=True,
                                        public=True)
    media_external = ProductMedia.objects.create(
        product=product,
        kind=ProductMediaKind.IMAGE,
        external_url="http://www.myimage.com/img.gif",
        enabled=True,
        public=True)
    product.primary_image = media
    product.save()

    # get product media
    response = client.get("/api/shuup/product_media/%d/" % media.pk)
    media_data = json.loads(response.content.decode("utf-8"))
    assert media_data["kind"] == media.kind.value
    assert media_data["product"] == product.pk
    assert media_data["public"] == media.public
    assert media_data["id"] == media.pk

    # get external media
    response = client.get("/api/shuup/product_media/%d/" % media_external.pk)
    media_data = json.loads(response.content.decode("utf-8"))
    assert media_data["kind"] == media_external.kind.value
    assert media_data["product"] == product.pk
    assert media_data["public"] == media_external.public
    assert media_data["id"] == media_external.pk
    assert media_data["external_url"] == media_external.external_url

    # update product media
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)

    media_data = {
        "translations": {
            "en": {
                "title": "title 2",
                "description": "desc2"
            }
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri,
        "path": "/what/the/zzzz"
    }
    response = client.put("/api/shuup/product_media/%d/" % media.pk,
                          content_type="application/json",
                          data=json.dumps(media_data))
    assert response.status_code == status.HTTP_200_OK
    media.refresh_from_db()
    assert media.title == media_data["translations"]["en"]["title"]
    assert media.description == media_data["translations"]["en"]["description"]
    assert media.shops.count() == len(media_data["shops"])
    assert set(media.shops.all().values_list("pk", flat=True)) >= set(
        media_data["shops"])
    assert media.kind.value == media_data["kind"]
    assert media.file.folder.pretty_logical_path == media_data["path"]
    with open(media.file.path, 'rb') as f:
        assert img_base64 == base64.b64encode(f.read()).decode()

    media_count = product.media.count()
    # deletes an image
    response = client.delete("/api/shuup/product_media/%d/" % media.pk)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert media_count - 1 == product.media.count()
def test_manufacturer_api(admin_user):
    shop = get_default_shop()
    client = APIClient()
    client.force_authenticate(user=admin_user)
    image = get_random_filer_image()
    with open(image.path, "rb") as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)
    manufacturer_data = {
        "name": "manu 1",
        "url": "http://www.google.com",
        "logo_path": "/this/not/needed",
        "logo": uri
    }
    response = client.post("/api/shuup/manufacturer/",
                           content_type="application/json",
                           data=json.dumps(manufacturer_data))
    assert response.status_code == status.HTTP_201_CREATED
    manufacturer = Manufacturer.objects.first()
    assert manufacturer.name == manufacturer_data["name"]
    assert manufacturer.url == manufacturer_data["url"]
    assert manufacturer.logo.folder.pretty_logical_path == manufacturer_data[
        "logo_path"]
    with open(manufacturer.logo.path, "rb") as f:
        assert img_base64 == base64.b64encode(f.read()).decode()

    manufacturer_data.pop("logo_path")  # Test error when not sending a path

    response = client.post("/api/shuup/manufacturer/",
                           content_type="application/json",
                           data=json.dumps(manufacturer_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    data = json.loads(response.content.decode("utf-8"))
    assert data["non_field_errors"][
        0] == "Path is required when sending a manufacturer logo."

    manufacturer_data[
        "logo_path"] = "/second/path"  # Testing second manufacturer
    manufacturer_data["name"] = "name 2"
    manufacturer_data["url"] = "http://yahoo.com"

    response = client.put(
        "/api/shuup/manufacturer/%d/" % manufacturer.id,
        content_type="application/json",
        data=json.dumps(manufacturer_data),
    )
    assert response.status_code == status.HTTP_200_OK
    manufacturer = Manufacturer.objects.first()
    assert manufacturer.name == manufacturer_data["name"]
    assert manufacturer.url == manufacturer_data["url"]
    response = client.get("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert manufacturer.name == data["name"]
    assert manufacturer.url == data["url"]

    response = client.get("/api/shuup/manufacturer/")
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert manufacturer.name == data[0]["name"]
    assert manufacturer.url == data[0]["url"]

    response = client.delete("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert Manufacturer.objects.count() == 0

    # create a product and relate it to a manufacturer
    product = create_product("product with manufacturer", shop=shop)
    manufacturer = Manufacturer.objects.create()
    product.manufacturer = manufacturer
    product.save()

    # shouldn't be possible to delete a manufacturer with a related product
    response = client.delete("/api/shuup/manufacturer/%d/" % manufacturer.id)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert Manufacturer.objects.count() == 0
    product.refresh_from_db()
    assert product.manufacturer is None
Пример #28
0
def test_carousel_multi_slide(browser, admin_user, live_server, settings):
    shop = factories.get_default_shop()
    filer_image = factories.get_random_filer_image()

    initialize_admin_browser_test(browser, live_server, settings, shop=shop)
    wait_until_condition(browser, lambda x: x.is_text_present("Welcome!"))

    assert not Carousel.objects.exists()

    browser.visit(live_server + "/sa/carousels/new")
    wait_until_condition(browser, lambda x: x.is_text_present("New Carousel"))
    browser.fill("base-name", "Carrot")
    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")

    assert Carousel.objects.count() == 1
    carousel = Carousel.objects.first()

    browser.visit(live_server + "/sa/carousels/%d/" % carousel.pk)
    wait_until_condition(browser, lambda x: x.is_text_present(carousel.name))
    click_element(browser, "a[href='#slides-section']")
    wait_until_appeared(browser, ".slide-add-new-panel")

    # add 4 slides
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")

    wait_until_condition(browser, lambda x: x.is_text_present("Slide 3"))

    # delete slide3
    wait_until_appeared(browser, "a[href='#collapse3']")
    click_element(browser, "a[href='#collapse3']")
    wait_until_appeared(browser, "#collapse3 .btn-remove-slide")
    click_element(browser, "#collapse3 .btn-remove-slide")

    wait_until_condition(browser, lambda x: not x.is_text_present("Slide 3"))
    click_element(browser, "button[form='carousel_form']")

    wait_until_appeared(browser, "a[href='#slides-section'].errors")
    click_element(browser, "a[href='#slides-section']")

    for slide_id in [0, 1, 2]:
        wait_until_appeared(browser, "a[href='#collapse%d']" % (slide_id + 1))
        click_element(browser, "a[href='#collapse%d']" % (slide_id + 1))

        browser.find_by_css("[name='slides-%d-caption__en']" % slide_id).fill("Slide")
        click_element(browser, "[name='slides-%d-category_link'] + .select2" % slide_id)
        wait_until_appeared(browser, ".select2-container #select2-id_slides-%d-category_link-results li" % slide_id)
        click_element(browser, ".select2-container #select2-id_slides-%d-category_link-results li:last-child" % slide_id)

        browser.find_by_css("#id_slides-%d-image__en-dropzone" % slide_id).click()
        wait_until_condition(browser, lambda b: len(b.windows) == 2)
        # change to the media browser window
        browser.windows.current = browser.windows[1]
        # click to select the picture
        wait_until_appeared(browser, "a.file-preview")
        click_element(browser, "a.file-preview")
        # back to the main window
        wait_until_condition(browser, lambda b: len(b.windows) == 1)
        browser.windows.current = browser.windows[0]
        wait_until_appeared(browser, ".dz-image img[alt='%s']" % filer_image.name)

    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")
Пример #29
0
def test_plugin():
    shop = factories.get_default_shop()
    set_current_theme(ClassicGrayTheme.identifier, shop)

    blog_page = Page.objects.create(shop=shop,
                                    title="Blog",
                                    url="blog",
                                    available_from=(now() -
                                                    timedelta(days=10)),
                                    available_to=(now() + timedelta(days=10)),
                                    content="")

    # create 10 blog pages
    for i in range(10):
        article = Page.objects.create(
            shop=shop,
            title="Article %d" % i,
            url="blog-%d" % i,
            available_from=(now() - timedelta(days=10)),
            available_to=(now() + timedelta(days=10)),
            content="Content %d" % i,
            template_name="shuup_cms_blog/blog_page.jinja")
        BlogArticle.objects.create(page=article,
                                   is_blog_article=True,
                                   image=factories.get_random_filer_image(),
                                   small_description="description %d" % i)

    # create 3 non blog post pages
    for i in range(3):
        article = Page.objects.create(
            shop=shop,
            title="Nothing %d" % i,
            url="non-%d" % i,
            available_from=(now() - timedelta(days=10)),
            available_to=(now() + timedelta(days=10)),
            content="content %i" % i)

    theme = get_current_theme(shop)
    view_config = ViewConfig(theme=theme,
                             shop=shop,
                             view_name="PageView",
                             draft=True)

    placeholder_name = "cms_page"
    context = {"page": blog_page}
    layout = view_config.get_placeholder_layout(PageLayout,
                                                placeholder_name,
                                                context=context)
    assert isinstance(layout, PageLayout)
    assert layout.get_help_text({}) == ""
    assert blog_page.title in layout.get_help_text(context)
    serialized = layout.serialize()
    assert len(serialized["rows"]) == 0
    assert serialized["name"] == placeholder_name

    layout.begin_column({"sm": 12})
    layout.add_plugin(ShuupCMSBlogArticleListPlugin.identifier, {})
    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout, context), layout)
    view_config.publish()

    client = SmartClient()
    response, soup = client.response_and_soup(
        reverse("shuup:cms_page", kwargs={"url": blog_page.url}))
    assert response.status_code == 200
    assert len(soup.find_all("a", {"class": "article-card"})) == 10
Пример #30
0
def test_xtheme_editor_form_picture(admin_user, browser, live_server,
                                    settings):
    """
    Test that is is possible to add image fron media browser
    """
    browser = initialize_admin_browser_test(browser, live_server, settings)
    browser.visit(live_server + "/")

    wait_until_condition(browser, lambda x: page_has_loaded(x), timeout=20)
    wait_until_appeared(browser, ".xt-edit-toggle button[type='submit']")
    click_element(browser, ".xt-edit-toggle button[type='submit']")

    placeholder_selector = "#xt-ph-front_content-xtheme-person-contact-layout"
    wait_until_condition(
        browser, lambda x: x.is_element_present_by_css(placeholder_selector))
    click_element(browser, placeholder_selector)

    with browser.get_iframe("xt-edit-sidebar-iframe") as iframe:
        # make sure all scripts are loaded
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        wait_until_condition(iframe,
                             lambda x: x.is_text_present("front_content"))
        wait_until_appeared(iframe, "button.layout-add-row-btn")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # click to add a new row
        click_element(iframe, "button.layout-add-row-btn")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # select the last row (the added one)
        click_element(iframe, "button.layout-add-row-btn")
        iframe.find_by_css("div.layout-cell").last.click()
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # select the TextPlugin
        wait_until_appeared(iframe, "select[name='general-plugin']")
        iframe.select("general-plugin", "text")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)
        wait_until_appeared(iframe, "ul.editor-tabs")

        filer_image = factories.get_random_filer_image()

        wait_until_appeared(
            browser,
            "#id_plugin-text_en-editor-wrap button[aria-label='Picture']")
        click_element(
            browser,
            "#id_plugin-text_en-editor-wrap button[aria-label='Picture']")
        wait_until_condition(browser,
                             lambda b: len(b.windows) == 2,
                             timeout=20)

        # change to the media browser window
        browser.windows.current = browser.windows[1]

        # click to select the picture
        wait_until_appeared(browser, "a.file-preview")
        browser.find_by_css("a.file-preview").first.click()

        # back to the main window
        wait_until_condition(browser, lambda b: len(b.windows) == 1)
        browser.windows.current = browser.windows[0]

        # make sure the image was added to the editor
        wait_until_appeared(
            browser,
            "#id_plugin-text_en-editor-wrap .note-editable img[src='%s']" %
            filer_image.url,
            timeout=20)
Пример #31
0
def test_product_media_api(admin_user):
    shop = get_default_shop()
    client = _get_client(admin_user)
    product = create_product("product", shop=shop)

    # create 2 images for product, 1 with contents, other with external url
    image = get_random_filer_image()
    media = ProductMedia.objects.create(product=product,
                                        kind=ProductMediaKind.IMAGE, file=image, enabled=True, public=True)
    media_external = ProductMedia.objects.create(product=product,
                                                 kind=ProductMediaKind.IMAGE,
                                                 external_url="http://www.myimage.com/img.gif",
                                                 enabled=True, public=True)
    product.primary_image = media
    product.save()

    # get product media
    response = client.get("/api/shuup/product_media/%d/" % media.pk)
    media_data = json.loads(response.content.decode("utf-8"))
    assert media_data["kind"] == media.kind.value
    assert media_data["product"] == product.pk
    assert media_data["public"] == media.public
    assert media_data["id"] == media.pk

    # get external media
    response = client.get("/api/shuup/product_media/%d/" % media_external.pk)
    media_data = json.loads(response.content.decode("utf-8"))
    assert media_data["kind"] == media_external.kind.value
    assert media_data["product"] == product.pk
    assert media_data["public"] == media_external.public
    assert media_data["id"] == media_external.pk
    assert media_data["external_url"] == media_external.external_url

    # update product media
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)

    media_data = {
        "translations": {
            "en": {"title": "title 2", "description": "desc2"}
        },
        "shops": [shop.pk],
        "kind": ProductMediaKind.IMAGE.value,
        "file": uri,
        "path": "/what/the/zzzz"
    }
    response = client.put("/api/shuup/product_media/%d/" % media.pk,
                          content_type="application/json",
                          data=json.dumps(media_data))
    assert response.status_code == status.HTTP_200_OK
    media.refresh_from_db()
    assert media.title == media_data["translations"]["en"]["title"]
    assert media.description == media_data["translations"]["en"]["description"]
    assert media.shops.count() == len(media_data["shops"])
    assert set(media.shops.all().values_list("pk", flat=True)) >= set(media_data["shops"])
    assert media.kind.value == media_data["kind"]
    assert media.file.folder.pretty_logical_path == media_data["path"]
    with open(media.file.path, 'rb') as f:
        assert img_base64 == base64.b64encode(f.read()).decode()

    media_count = product.media.count()
    # deletes an image
    response = client.delete("/api/shuup/product_media/%d/" % media.pk)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert media_count-1 == product.media.count()
Пример #32
0
def test_xtheme_editor_form_picture(admin_user, browser, live_server, settings):
    """
    Test that is is possible to add image fron media browser
    """
    browser = initialize_admin_browser_test(browser, live_server, settings)
    browser.visit(live_server + "/")

    wait_until_condition(browser, lambda x: page_has_loaded(x), timeout=20)
    wait_until_appeared(browser, ".xt-edit-toggle button[type='submit']")
    click_element(browser, ".xt-edit-toggle button[type='submit']")

    placeholder_selector = "#xt-ph-front_content-xtheme-person-contact-layout"
    wait_until_condition(browser, lambda x: x.is_element_present_by_css(placeholder_selector))
    click_element(browser, placeholder_selector)

    with browser.get_iframe("xt-edit-sidebar-iframe") as iframe:
        # make sure all scripts are loaded
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        wait_until_condition(iframe, lambda x: x.is_text_present("front_content"))
        wait_until_appeared(iframe, "button.layout-add-row-btn")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # click to add a new row
        click_element(iframe, "button.layout-add-row-btn")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # select the last row (the added one)
        click_element(iframe, "button.layout-add-row-btn")
        iframe.find_by_css("div.layout-cell").last.click()
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)

        # select the TextPlugin
        wait_until_appeared(iframe, "select[name='general-plugin']")
        iframe.select("general-plugin", "text")
        time.sleep(1)
        wait_until_condition(iframe, lambda x: page_has_loaded(x), timeout=20)
        wait_until_appeared(iframe, "ul.editor-tabs")

        filer_image = factories.get_random_filer_image()

        wait_until_appeared(browser, "#id_plugin-text_en-editor-wrap button[aria-label='Picture']")
        click_element(browser, "#id_plugin-text_en-editor-wrap button[aria-label='Picture']")
        wait_until_condition(browser, lambda b: len(b.windows) == 2, timeout=20)

        # change to the media browser window
        browser.windows.current = browser.windows[1]

        # click to select the picture
        wait_until_appeared(browser, "a.file-preview")
        browser.find_by_css("a.file-preview").first.click()

        # back to the main window
        wait_until_condition(browser, lambda b: len(b.windows) == 1)
        browser.windows.current = browser.windows[0]

        # make sure the image was added to the editor
        wait_until_appeared(browser, "#id_plugin-text_en-editor-wrap .note-editable img[src='%s']" % filer_image.url, timeout=20)
Пример #33
0
def test_category_api(admin_user):
    activate("en")
    shop = get_default_shop()
    client = APIClient()
    client.force_authenticate(user=admin_user)
    image = get_random_filer_image()
    with open(image.path, 'rb') as f:
        img_base64 = base64.b64encode(os.urandom(50)).decode()
        uri = "data:application/octet-stream;base64,{}".format(img_base64)
    category_data = {
        "shops": [shop.pk],
        "status": CategoryStatus.VISIBLE.value,
        "ordering": 1,
        "visibility": CategoryVisibility.VISIBLE_TO_ALL.value,
        "visible_in_menu": True,
        "translations": {
            "en": {
                "name": "Category 1"
            }
        },
        "image_path": "/didnt/choose/path",
        "image": uri
    }
    response = client.post("/api/shuup/category/",
                           content_type="application/json",
                           data=json.dumps(category_data))
    assert response.status_code == status.HTTP_201_CREATED
    category = Category.objects.first()
    assert category.name == category_data["translations"]["en"]["name"]
    assert category.status.value == category_data["status"]
    assert category.ordering == category_data["ordering"]
    assert category.visibility.value == category_data["visibility"]
    assert category.visible_in_menu == category_data["visible_in_menu"]
    assert category.shops.first().pk == shop.pk
    assert category.image.folder.pretty_logical_path == category_data[
        "image_path"]

    with open(category.image.path, 'rb') as f:
        assert img_base64 == base64.b64encode(f.read()).decode()

    category_data.pop("image_path")  # Test error when not sending a path
    response = client.post("/api/shuup/category/",
                           content_type="application/json",
                           data=json.dumps(category_data))
    assert response.status_code == status.HTTP_400_BAD_REQUEST
    data = json.loads(response.content.decode("utf-8"))
    assert data["non_field_errors"][
        0] == "Path is required when sending a Category image."

    category_data["image_path"] = "/path/chose/me"
    category_data["translations"]["en"]["name"] = "name 2"
    category_data["ordering"] = 3

    response = client.put("/api/shuup/category/%d/" % category.id,
                          content_type="application/json",
                          data=json.dumps(category_data))
    assert response.status_code == status.HTTP_200_OK
    category = Category.objects.first()
    assert category.name == category_data["translations"]["en"]["name"]
    assert category.ordering == category_data["ordering"]

    response = client.get("/api/shuup/category/%d/" % category.id)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert category.name == data["translations"]["en"]["name"]
    assert category.status.value == data["status"]
    assert category.ordering == data["ordering"]
    assert category.visibility.value == data["visibility"]
    assert category.visible_in_menu == data["visible_in_menu"]

    response = client.get("/api/shuup/category/")
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert category.name == data[0]["translations"]["en"]["name"]
    assert category.ordering == data[0]["ordering"]

    response = client.get("/api/shuup/category/?status=%s" %
                          CategoryStatus.VISIBLE.value)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert len(data) == 1

    response = client.get("/api/shuup/category/?status=%s" %
                          CategoryStatus.INVISIBLE.value)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert len(data) == 0

    response = client.get("/api/shuup/category/?status=%s" %
                          CategoryStatus.DELETED.value)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert len(data) == 0

    # soft delete
    response = client.delete("/api/shuup/category/%d/" % category.id)
    assert response.status_code == status.HTTP_204_NO_CONTENT
    assert Category.objects.first().status == CategoryStatus.DELETED

    response = client.get("/api/shuup/category/?status=%s" %
                          CategoryStatus.DELETED.value)
    assert response.status_code == status.HTTP_200_OK
    data = json.loads(response.content.decode("utf-8"))
    assert len(data) == 1
Пример #34
0
def test_carousel_multi_slide(browser, admin_user, live_server, settings):
    shop = factories.get_default_shop()
    filer_image = factories.get_random_filer_image()

    initialize_admin_browser_test(browser, live_server, settings, shop=shop)
    wait_until_condition(browser, lambda x: x.is_text_present("Welcome!"))

    assert not Carousel.objects.exists()

    browser.visit(live_server + "/sa/carousels/new")
    wait_until_condition(browser, lambda x: x.is_text_present("New Carousel"))
    browser.fill("base-name", "Carrot")
    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")

    assert Carousel.objects.count() == 1
    carousel = Carousel.objects.first()

    browser.visit(live_server + "/sa/carousels/%d/" % carousel.pk)
    wait_until_condition(browser, lambda x: x.is_text_present(carousel.name))
    click_element(browser, "a[href='#slides-section']")
    wait_until_appeared(browser, ".slide-add-new-panel")

    # add 4 slides
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")
    click_element(browser, ".slide-add-new-panel")

    wait_until_condition(browser, lambda x: x.is_text_present("Slide 3"))

    # delete slide3
    wait_until_appeared(browser, "a[href='#collapse3']")
    click_element(browser, "a[href='#collapse3']")
    wait_until_appeared(browser, "#collapse3 .btn-remove-slide")
    click_element(browser, "#collapse3 .btn-remove-slide")

    wait_until_condition(browser, lambda x: not x.is_text_present("Slide 3"))
    click_element(browser, "button[form='carousel_form']")

    wait_until_appeared(browser, "a[href='#slides-section'].errors")
    click_element(browser, "a[href='#slides-section']")

    for slide_id in [0, 1, 2]:
        wait_until_appeared(browser, "a[href='#collapse%d']" % (slide_id + 1))
        click_element(browser, "a[href='#collapse%d']" % (slide_id + 1))

        browser.find_by_css("[name='slides-%d-caption__en']" %
                            slide_id).fill("Slide")
        click_element(browser,
                      "[name='slides-%d-category_link'] + .select2" % slide_id)
        wait_until_appeared(
            browser,
            ".select2-container #select2-id_slides-%d-category_link-results li"
            % slide_id)
        click_element(
            browser,
            ".select2-container #select2-id_slides-%d-category_link-results li:last-child"
            % slide_id)

        browser.find_by_css("#id_slides-%d-image__en-dropzone" %
                            slide_id).click()
        wait_until_condition(browser, lambda b: len(b.windows) == 2)
        # change to the media browser window
        browser.windows.current = browser.windows[1]
        # click to select the picture
        wait_until_appeared(browser, "a.file-preview")
        click_element(browser, "a.file-preview")
        # back to the main window
        wait_until_condition(browser, lambda b: len(b.windows) == 1)
        browser.windows.current = browser.windows[0]
        wait_until_appeared(browser,
                            ".dz-image img[alt='%s']" % filer_image.name)

    click_element(browser, "button[form='carousel_form']")
    wait_until_appeared(browser, "div[class='message success']")