import enaml
import pytest
from utils import compile_source
from textwrap import dedent
from web.core.app import WebApplication

@pytest.fixture
def app():
    app = WebApplication.instance() or WebApplication()
    yield app


def test_block(app):
    # Test that a block's content is replaced
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                pass

    enamldef Page(Template):
        Block:
            block = parent.content
            H2:
                text = "It worked!"

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h2')) == 1


def test_block_unused(app):
    # Test that an unused block retains it's default content
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        pass

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 1


def test_block_replace(app):
    # Test that a used a block's content is replaced in 'replace' mode
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"
                P:
                    text = "Foo"

    enamldef Page(Template):
        Block:
            block = parent.content
            H2:
                text = "It worked!"

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/p')) == 0
    assert len(view.xpath('/html/body/h2')) == 1


def test_block_append(app):
    # Test that a block's content is retained and new content is appended in
    # append mode
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        Block:
            block = parent.content
            mode = 'append'
            H1:
                text = "Appended"

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == "Default"
    assert nodes[1].text == "Appended"


def test_block_prepend(app):
    # Test that a block's content is retained and new content is inserted
    # before the default content in prepend mode.
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        Block:
            block = parent.content
            mode = 'prepend'
            H1:
                text = "Prepended"

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == "Prepended"
    assert nodes[1].text == "Default"


def test_block_replace_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            Looper:
                iterable << names
                H2:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/h2')) == 1

    # Update
    print(view.render(names=['alice', 'bob']))
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/h2')) == 2

    print(view.render(names=['tom']))
    assert len(view.xpath('/html/body/h1')) == 0
    nodes = view.xpath('/html/body/h2')
    assert len(nodes) == 1
    assert nodes[0].text == 'tom'


def test_block_append_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            mode = 'append'
            Looper:
                iterable << names
                H1:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'alice'

    # Update
    print(view.render(names=['alice', 'bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'alice'
    assert nodes[2].text == 'bob'

    # Update
    print(view.render(names=['bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'bob'


def test_block_prepend_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            mode = 'prepend'
            Looper:
                iterable << names
                H1:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'alice'
    assert nodes[1].text == 'Default'

    # Update
    print(view.render(names=['alice', 'bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'alice'
    assert nodes[1].text == 'bob'
    assert nodes[2].text == 'Default'

    # Update
    print(view.render(names=['bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'bob'
    assert nodes[1].text == 'Default'


def test_block_mode_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template): view:
        attr mode = 'append'
        Block:
            block = parent.content
            mode << view.mode
            H1:
                text = 'Mode'

    """), 'Page')
    view = Page()

    for mode in ('append', 'prepend', 'append', 'prepend'):
        print(view.render(mode=mode))
        nodes = view.xpath('/html/body/h1')
        assert len(nodes) == 2
        i, j = (0, 1) if mode == 'append' else (1, 0)
        assert nodes[i].text == 'Default'
        assert nodes[j].text == 'Mode'


def test_block_ref_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias header
        alias footer
        Head:
            Title:
                text = "Test"
        Body:
            Block: header:
                H1:
                    text = "Header"
            Block: footer:
                H1:
                    text = "Footer"


    enamldef Page(Template): view:
        attr block = 'header'
        Block:
            block << parent.header if view.block == 'header' else parent.footer
            mode = 'append'
            H1:
                text = 'Added'

    """), 'Page')
    view = Page()
    print(view.render(block='header'))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Header'
    assert nodes[1].text == 'Added'
    assert nodes[2].text == 'Footer'

    print(view.render(block='footer'))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Header'
    assert nodes[1].text == 'Footer'
    assert nodes[2].text == 'Added'

import enaml
import pytest
from utils import compile_source
from textwrap import dedent
from web.core.app import WebApplication

@pytest.fixture
def app():
    app = WebApplication.instance() or WebApplication()
    yield app


def test_block(app):
    # Test that a block's content is replaced
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                pass

    enamldef Page(Template):
        Block:
            block = parent.content
            H2:
                text = "It worked!"

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h2')) == 1


def test_block_unused(app):
    # Test that an unused block retains it's default content
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        pass

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 1


def test_block_replace(app):
    # Test that a used a block's content is replaced in 'replace' mode
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"
                P:
                    text = "Foo"

    enamldef Page(Template):
        Block:
            block = parent.content
            H2:
                text = "It worked!"

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/p')) == 0
    assert len(view.xpath('/html/body/h2')) == 1


def test_block_append(app):
    # Test that a block's content is retained and new content is appended in
    # append mode
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        Block:
            block = parent.content
            mode = 'append'
            H1:
                text = "Appended"

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == "Default"
    assert nodes[1].text == "Appended"


def test_block_prepend(app):
    # Test that a block's content is retained and new content is inserted
    # before the default content in prepend mode.
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        Block:
            block = parent.content
            mode = 'prepend'
            H1:
                text = "Prepended"

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == "Prepended"
    assert nodes[1].text == "Default"


def test_block_replace_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            Looper:
                iterable << names
                H2:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/h2')) == 1

    # Update
    print(view.render(names=['alice', 'bob']))
    assert len(view.xpath('/html/body/h1')) == 0
    assert len(view.xpath('/html/body/h2')) == 2

    print(view.render(names=['tom']))
    assert len(view.xpath('/html/body/h1')) == 0
    nodes = view.xpath('/html/body/h2')
    assert len(nodes) == 1
    assert nodes[0].text == 'tom'


def test_block_append_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            mode = 'append'
            Looper:
                iterable << names
                H1:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'alice'

    # Update
    print(view.render(names=['alice', 'bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'alice'
    assert nodes[2].text == 'bob'

    # Update
    print(view.render(names=['bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'Default'
    assert nodes[1].text == 'bob'


def test_block_prepend_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template):
        attr names = ['alice']
        Block:
            block = parent.content
            mode = 'prepend'
            Looper:
                iterable << names
                H1:
                    text = loop_item

    """), 'Page')
    view = Page()
    print(view.render())
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'alice'
    assert nodes[1].text == 'Default'

    # Update
    print(view.render(names=['alice', 'bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'alice'
    assert nodes[1].text == 'bob'
    assert nodes[2].text == 'Default'

    # Update
    print(view.render(names=['bob']))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 2
    assert nodes[0].text == 'bob'
    assert nodes[1].text == 'Default'


def test_block_mode_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias content
        Head:
            Title:
                text = "Test"
        Body:
            Block: content:
                H1:
                    text = "Default"

    enamldef Page(Template): view:
        attr mode = 'append'
        Block:
            block = parent.content
            mode << view.mode
            H1:
                text = 'Mode'

    """), 'Page')
    view = Page()

    for mode in ('append', 'prepend', 'append', 'prepend'):
        print(view.render(mode=mode))
        nodes = view.xpath('/html/body/h1')
        assert len(nodes) == 2
        i, j = (0, 1) if mode == 'append' else (1, 0)
        assert nodes[i].text == 'Default'
        assert nodes[j].text == 'Mode'


def test_block_ref_changed(app):
    # Test that a block's content is updated when the blocks content is updated
    Page = compile_source(dedent("""
    from web.components.api import *
    from web.core.api import *

    enamldef Template(Html):
        alias header
        alias footer
        Head:
            Title:
                text = "Test"
        Body:
            Block: header:
                H1:
                    text = "Header"
            Block: footer:
                H1:
                    text = "Footer"


    enamldef Page(Template): view:
        attr block = 'header'
        Block:
            block << parent.header if view.block == 'header' else parent.footer
            mode = 'append'
            H1:
                text = 'Added'

    """), 'Page')
    view = Page()
    print(view.render(block='header'))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Header'
    assert nodes[1].text == 'Added'
    assert nodes[2].text == 'Footer'

    print(view.render(block='footer'))
    nodes = view.xpath('/html/body/h1')
    assert len(nodes) == 3
    assert nodes[0].text == 'Header'
    assert nodes[1].text == 'Footer'
    assert nodes[2].text == 'Added'

# Test that a block's content is replaced from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 pass      enamldef Page(Template):         Block:             block = parent.content             H2:                 text = "It worked!" # Test that an unused block retains it's default content from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         pass # Test that a used a block's content is replaced in 'replace' mode from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"                 P:                     text = "Foo"      enamldef Page(Template):         Block:             block = parent.content             H2:                 text = "It worked!" # Test that a block's content is retained and new content is appended in # append mode from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         Block:             block = parent.content             mode = 'append'             H1:                 text = "Appended" # Test that a block's content is retained and new content is inserted # before the default content in prepend mode. from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         Block:             block = parent.content             mode = 'prepend'             H1:                 text = "Prepended" # Test that a block's content is updated when the blocks content is updated from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         attr names = ['alice']         Block:             block = parent.content             Looper:                 iterable << names                 H2:                     text = loop_item # Update # Test that a block's content is updated when the blocks content is updated from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         attr names = ['alice']         Block:             block = parent.content             mode = 'append'             Looper:                 iterable << names                 H1:                     text = loop_item # Update # Update # Test that a block's content is updated when the blocks content is updated from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template):         attr names = ['alice']         Block:             block = parent.content             mode = 'prepend'             Looper:                 iterable << names                 H1:                     text = loop_item # Update # Update # Test that a block's content is updated when the blocks content is updated from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias content         Head:             Title:                 text = "Test"         Body:             Block: content:                 H1:                     text = "Default"      enamldef Page(Template): view:         attr mode = 'append'         Block:             block = parent.content             mode << view.mode             H1:                 text = 'Mode' # Test that a block's content is updated when the blocks content is updated from web.components.api import *     from web.core.api import *      enamldef Template(Html):         alias header         alias footer         Head:             Title:                 text = "Test"         Body:             Block: header:                 H1:                     text = "Header"             Block: footer:                 H1:                     text = "Footer"       enamldef Page(Template): view:         attr block = 'header'         Block:             block << parent.header if view.block == 'header' else parent.footer             mode = 'append'             H1:                 text = 'Added'