Beispiel #1
0
def test_draft_reversion():
    view_name = printable_gibberish()
    shop = get_default_shop()
    theme = ATestTheme(shop=shop)
    placeholder_name = "test_ph"
    vc = ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
    def get_layout_data(draft):
        # shorthand -- we're going to be doing this a lot in this test case
        return ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=draft).saved_view_config.get_layout_data(placeholder_name)
    data1 = {printable_gibberish(): True}
    data2 = {printable_gibberish(): True}
    vc.save_placeholder_layout(placeholder_name, data1)
    vc.publish()

    assert get_layout_data(draft=False) == data1
    assert get_layout_data(draft=True) == data1
    vc = ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
    svc = vc.saved_view_config
    assert svc.draft
    assert svc.get_layout_data(placeholder_name) == data1
    # Make changes over the last published version
    svc.set_layout_data(placeholder_name, data2)
    svc.save()
    # Still all good in public?
    assert get_layout_data(draft=False) == data1
    # Still got it in draft?
    assert get_layout_data(draft=True) == data2
    # Actually revert those draft changes now!
    vc.revert()
    # So in draft we're back to the published version, right?
    assert get_layout_data(draft=True) == data1
Beispiel #2
0
def get_view_config(context, global_type=False):
    """
    Get a view configuration object for a Jinja2 rendering context.

    :param context: Rendering context
    :type context: jinja2.runtime.Context
    :param global_type: Boolean indicating whether this is a global type
    :type global_type: bool|False
    :return: View config
    :rtype: shuup.xtheme.view_config.ViewConfig
    """
    # This uses the Jinja context's technically-immutable vars dict
    # to cache the view configuration. This is fine in our case, I'd say.
    request = context.get("request")
    config_key = "_xtheme_global_view_config" if global_type else "_xtheme_view_config"
    config = context.vars.get(config_key)
    if (config is None):
        view_object = context.get("view")
        if view_object:
            view_class = view_object.__class__
            view_name = view_class.__name__
        else:
            view_name = "UnknownView"
        config = ViewConfig(
            theme=get_current_theme(request.shop),
            shop=request.shop,
            view_name=view_name,
            draft=is_edit_mode(request),
            global_type=global_type,
        )
        context.vars[config_key] = config
    return config
Beispiel #3
0
    def _populate_vars(self):
        theme = get_theme_by_identifier(self.request.GET["theme"],
                                        self.request.shop)
        if not theme:
            raise Problem(_("Unable to determine current theme."))
        view_name = self.request.GET["view"]
        global_type = self.request.GET.get("global_type", None)
        self.view_config = ViewConfig(
            theme=theme,
            shop=self.request.shop,
            view_name=view_name,
            draft=True,
            global_type=global_type,
        )

        self.placeholder_name = self.request.GET["ph"]
        self.default_layout = self._get_default_layout()
        self.layout = self.view_config.get_placeholder_layout(
            placeholder_name=self.placeholder_name,
            default_layout=self.default_layout)
        (x, y) = self.current_cell_coords = (
            int(self.request.GET.get("x", -1)),
            int(self.request.GET.get("y", -1)),
        )
        self.current_cell = self.layout.get_cell(x=x, y=y)
        self.build_form()
Beispiel #4
0
def test_load_save_default():
    view_name = printable_gibberish()
    shop = get_default_shop()
    theme = ATestTheme(shop=shop)
    vc = ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
    placeholder_name = "test_ph"
    data = {"dummy": True}
    assert not vc.saved_view_config.get_layout_data(placeholder_name)
    assert vc.save_default_placeholder_layout(placeholder_name, data)
    assert not vc.save_default_placeholder_layout(placeholder_name, data)

    # Not in public mode yet, right?
    assert not ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=False).saved_view_config.get_layout_data(placeholder_name)

    # But it is in drafts, even if we reload it?
    vc = ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
    assert vc.saved_view_config.get_layout_data(placeholder_name) == data
Beispiel #5
0
def test_load_save_publish():
    view_name = printable_gibberish()
    shop = get_default_shop()
    theme = ATestTheme(shop=shop)
    vc = ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
    placeholder_name = "test_ph"
    data = {"dummy": True}
    vc.save_placeholder_layout(placeholder_name, data)
    assert not ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=False).saved_view_config.get_layout_data(placeholder_name)
    vc.publish()
    with pytest.raises(ValueError):  # Republishment is bad
        vc.publish()
    with pytest.raises(ValueError):  # Editing directly in public is bad
        vc.save_placeholder_layout(placeholder_name, "break all the things")
    with pytest.raises(ValueError):  # Can't quite revert public changes either
        vc.revert()
    assert ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=False).saved_view_config.get_layout_data(placeholder_name)
Beispiel #6
0
def test_unsaved_vc_reversion():
    shop = get_default_shop()
    vc = ViewConfig(theme=ATestTheme(shop=shop),
                    shop=shop,
                    view_name=printable_gibberish(),
                    draft=True)
    vc.revert(
    )  # No-op, since this has never been saved (but shouldn't crash either)
Beispiel #7
0
def test_unthemebound_view_config_cant_do_much():
    vc = ViewConfig(theme=None, shop=get_default_shop(), view_name="durr", draft=True)
    with pytest.raises(ValueError):
        vc.publish()
    with pytest.raises(ValueError):
        vc.revert()
    with pytest.raises(ValueError):
        vc.save_placeholder_layout("hurr", {"foo": True})
    l = vc.get_placeholder_layout(Layout, "hurr")  # loading should work, but . . .
    assert not len(l.rows)  # . . . there shouldn't be much in there
def test_page_layout():
    if "shuup.xtheme" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.xtheme in INSTALLED_APPS")

    shop = factories.get_default_shop()
    theme = get_current_theme(shop)
    view_config = ViewConfig(theme=theme,
                             shop=shop,
                             view_name="PageView",
                             draft=True)
    page1_content = printable_gibberish()
    page1 = create_page(available_from=datetime.date(1917, 12, 6),
                        content=page1_content,
                        shop=shop,
                        url="test1")
    page2_content = printable_gibberish()
    page2 = create_page(available_from=datetime.date(1917, 12, 6),
                        content=page2_content,
                        shop=shop,
                        url="test2")

    placeholder_name = "cms_page"
    context = {"page": page1}
    layout = view_config.get_placeholder_layout(PageLayout,
                                                placeholder_name,
                                                context=context)
    assert isinstance(layout, PageLayout)
    assert layout.get_help_text({}) == ""  # Invalid context for help text
    assert page1.title in layout.get_help_text(context)

    # Make sure layout is empty
    serialized = layout.serialize()
    assert len(serialized["rows"]) == 0
    assert serialized["name"] == placeholder_name

    # Add custom plugin to page
    layout.begin_column({"md": 8})
    plugin_text = printable_gibberish()
    layout.add_plugin("text", {"text": plugin_text})
    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout, context), layout)
    view_config.publish()

    c = SmartClient()
    soup = c.soup(reverse("shuup:cms_page", kwargs={"url": page1.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page1_content in page_content.text
    assert plugin_text in page_content.text

    c = SmartClient()
    soup = c.soup(reverse("shuup:cms_page", kwargs={"url": page2.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page2_content in page_content.text
    assert plugin_text not in page_content.text
Beispiel #9
0
    def _populate_vars(self):
        theme = get_theme_by_identifier(self.request.GET["theme"],
                                        self.request.shop)
        if not theme:
            raise Problem(_("Unable to determine the current theme."))
        view_name = self.request.GET["view"]
        global_type = self.request.GET.get("global_type", None)
        self.view_config = ViewConfig(
            theme=theme,
            shop=self.request.shop,
            view_name=view_name,
            draft=True,
            global_type=global_type,
        )

        # Let's store the layout data key for save here
        self.layout_data_key = self.request.GET.get("layout_data_key", None)

        # Let's use the layout identifier passed by the view to
        # fetch correct layout
        layout_identifier = self.request.GET.get("layout_identifier", None)
        layout_cls = Layout
        for provided_layout in get_provided_layouts():
            if provided_layout.identifier == layout_identifier:
                layout_cls = provided_layout

        self.placeholder_name = self.request.GET["ph"]
        self.default_layout = self._get_default_layout()
        self.layout = self.view_config.get_placeholder_layout(
            layout_cls=layout_cls,
            placeholder_name=self.placeholder_name,
            default_layout=self.default_layout,
            layout_data_key=self.layout_data_key,
        )
        (x, y) = self.current_cell_coords = (
            int(self.request.GET.get("x", -1)),
            int(self.request.GET.get("y", -1)),
        )
        self.current_cell = self.layout.get_cell(x=x, y=y)
        self.build_form()
Beispiel #10
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
def test_page_anonymous_layout():
    if "shuup.simple_cms" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.simple_cms in INSTALLED_APPS")

    if "shuup.xtheme" not in settings.INSTALLED_APPS:
        pytest.skip("Need shuup.xtheme in INSTALLED_APPS")

    shop = factories.get_default_shop()
    theme = set_current_theme("shuup.themes.classic_gray", shop)
    view_config = ViewConfig(theme=theme,
                             shop=shop,
                             view_name="PageView",
                             draft=True)
    page1_content = printable_gibberish()
    page1 = create_page(available_from=datetime.date(1917, 12, 6),
                        content=page1_content,
                        shop=shop,
                        url="test1")
    page2_content = printable_gibberish()
    page2 = create_page(available_from=datetime.date(1917, 12, 6),
                        content=page2_content,
                        shop=shop,
                        url="test2")

    person = factories.create_random_person(shop=shop)
    person.user = factories.create_random_user()
    password = "******"
    person.user.set_password(password)
    person.user.save()
    person.save()

    placeholder_name = "cms_page"
    request = get_request()
    context = {"page": page1, "request": request}
    layout = view_config.get_placeholder_layout(PageAnonymousLayout,
                                                placeholder_name,
                                                context=context)
    assert isinstance(layout, PageAnonymousLayout)
    assert layout.get_help_text({}) == ""  # Invalid context for help text
    assert page1.title in layout.get_help_text(context)

    # Make sure layout is empty
    serialized = layout.serialize()
    assert len(serialized["rows"]) == 0
    assert serialized["name"] == placeholder_name

    # Add custom plugin to page
    layout.begin_column({"md": 8})
    plugin_text = printable_gibberish()
    layout.add_plugin("text", {"text": plugin_text})
    view_config.save_placeholder_layout(
        get_layout_data_key(placeholder_name, layout, context), layout)
    view_config.publish()

    c = SmartClient()
    soup = c.soup(reverse("shuup:cms_page", kwargs={"url": page1.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page1_content in page_content.text
    assert plugin_text in page_content.text

    # Make sure content not available for page2
    c = SmartClient()
    soup = c.soup(reverse("shuup:cms_page", kwargs={"url": page2.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page2_content in page_content.text
    assert plugin_text not in page_content.text

    # Make sure content not available for logged in users
    c = SmartClient()
    c.login(username=person.user.username, password=password)
    soup = c.soup(reverse("shuup:cms_page", kwargs={"url": page1.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page1_content in page_content.text
    assert plugin_text not in page_content.text
Beispiel #12
0
 def get_layout_data(draft):
     # shorthand -- we're going to be doing this a lot in this test case
     return ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=draft).saved_view_config.get_layout_data(placeholder_name)
Beispiel #13
0
def _get_basic_view_config(view_name="pow"):
    shop = factories.get_default_shop()
    theme = get_current_theme(shop)
    return ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)
Beispiel #14
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