def test_page_url_conflict(): page_one = Page('one', core.Container()) page_two = Page('two', core.Container(), url='/one') app = Dazzler(__name__) with pytest.raises(PageConflictError) as context: app.add_page(page_one, page_two) assert context.value.args[0] == 'Duplicate page url: two@/one'
async def test_page_meta_attributes(start_page, browser): meta = [ { 'name': 'description', 'content': 'test dazzler' }, { 'name': 'custom', 'content': 'customized' }, ] await start_page( Page(name='meta', layout=core.Container('Hello', identity='layout'), meta_tags=meta)) await asyncio.sleep(0.001) meta_tags = await browser.wait_for_elements_by_css_selector('meta') # Meta charset + http-equiv always present (+2) assert len(meta_tags) == 4 for i in range(2, len(meta_tags)): meta_dict = meta[i - 2] meta_tag = meta_tags[i] for k, v in meta_dict.items(): assert meta_tag.get_attribute(k) == v
async def test_package_route(start_page, browser): async def package_route(_): return web.Response(body='<html><head></head><body>' '<div id="content">Package route</div>' '</body></html>', content_type='text/html') await start_page( Page('package', core.Container(), routes=[Route('/package-route', package_route)])) await browser.get('http://localhost:8150/package-route') await browser.wait_for_text_to_equal('#content', 'Package route')
async def test_html_single(start_page, browser, tag_name, attributes): # Test attributes are set and render. page = Page(__name__, core.Html(tag_name, attributes=attributes, identity='html')) await start_page(page) component = await browser.wait_for_element_by_id('html') for k, v in attributes.items(): if k == 'children': await browser.wait_for_text_to_equal('#html', v) else: attr = component.get_attribute(k) assert attr == str(v)
async def test_page_routes(start_page, browser): page = Page('page-routes', core.Container()) # pylint: disable=unused-variable @page.route('/page-route') async def page_route(_): return web.Response(body='<html><head></head><body>' '<div id="content">Page route</div>' '</body></html>', content_type='text/html') await start_page(page) await browser.get('http://localhost:8150/page-routes/page-route') await browser.wait_for_text_to_equal('#content', 'Page route')
async def test_page_requirements_package_override(start_page, browser): # Overriding the package is an optimization if some pages uses big bundles # and others pages are more lightweight, down the line maybe add # on-demand loading of requirements, it's already set up for it. # noinspection PyUnresolvedReferences from tests.components import spec_components as spec # noqa: F401 page = Page(__name__, core.Container('Rendered'), packages=['dazzler_core']) await start_page(page) await browser.wait_for_element_by_css_selector('.dazzler-rendered') scripts = await browser.wait_for_elements_by_css_selector('script') for script in scripts: src = script.get_attribute('src') assert 'dazzler_test' not in src
async def test_middleware(start_visit, browser): page = Page(__name__, layout=layout, url='/') @page.bind(Trigger('cookie-setter', 'clicks')) async def on_cookie(ctx: BindingContext): cookie = ctx.request.cookies.get('dummy') await ctx.set_aspect('cookie-output', children=cookie) app = Dazzler(__name__) app.middlewares.append(DummyMiddleware()) app.add_page(page) await start_visit(app) await browser.wait_for_text_to_equal('#request-output', 'dummy') await browser.click('#cookie-setter') await browser.wait_for_text_to_equal('#cookie-output', 'dummy-cookie')
def session_app(): app = Dazzler(__name__) app.config.session.duration = 3 app.config.secret_key = uuid.uuid4().hex page = Page(__name__, core.Container( [core.Container(identity='session-output', clicks=1)]), url='/') @page.bind(Trigger('session-output', 'clicks')) async def on_session(ctx: BindingContext): await ctx.set_aspect('session-output', children=ctx.session.session_id) app.add_page(page) return app
async def test_auth_from_configs(start_visit, browser): app = Dazzler(__name__) app.config.authentication.enable = True app.config.session.backend = 'Redis' app.config.authentication.authenticator = \ 'tests.test_dazzler_auth:DummyAuthenticator' page = Page(__name__, core.Container('my-page', identity='content'), require_login=True, url='/') app.add_page(page) await start_visit(app) await browser.get('http://localhost:8150/') await proceed_login(browser, 'AgentSmith', 'SuperSecret1') await browser.wait_for_text_to_equal('#content', 'my-page')
async def test_session(start_visit, browser, backend): app = Dazzler(__name__) app.config.session.enable = False app.config.session.duration = 3 app.middlewares.append(SessionMiddleware(app, backend=backend(app))) page = Page(__name__, url='/', layout=core.Container([ core.Button('Click', identity='session-click'), core.Container(identity='session-output'), core.Button('Remove session', identity='remove-session'), ])) @page.bind(Trigger('session-click', 'clicks')) async def on_session(ctx: BindingContext): session = ctx.request['session'] clicks = await session.get('clicks') or 0 clicks += 1 await session.set('clicks', clicks) await ctx.set_aspect('session-output', children=f'Clicked {clicks}') @page.bind(Trigger('remove-session', 'clicks')) async def on_remove(ctx: BindingContext): session = ctx.request['session'] await session.delete('clicks') app.add_page(page) await start_visit(app) for i in range(1, 4): await browser.get('http://localhost:8150/') await browser.click('#session-click') await browser.wait_for_text_to_equal('#session-output', f'Clicked {i}') # Delete session item await browser.click('#remove-session') await browser.click('#session-click') await browser.wait_for_text_to_equal('#session-output', 'Clicked 1')
def auth_app(): app = Dazzler(__name__) page = Page('test-auth', core.Container([ core.Html('h2', 'logged-in', identity='header'), core.Container(identity='username-output'), _auth.Logout('/auth/logout', identity='logout') ]), url='/', require_login=True) @page.bind(Trigger('header', 'children')) async def on_username(ctx): user = ctx.request['user'] await ctx.set_aspect('username-output', children=user.username) app.add_page(page) app.config.session.backend = 'Redis' DazzlerAuth(app, DummyAuthenticator()) return app
""" Page same_identity of dazzler Created 2019-06-17 """ from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext, State page = Page( __name__, core.Container([ core.Container( core.Input(value=0, type='number', identity='same'), identity='container' ), core.Button('click', identity='click') ]) ) @page.bind(Trigger('click', 'clicks'), State('container', 'children')) async def on_click(ctx: BindingContext): component = ctx.states['container']['children'] component.value = ctx.trigger.value await ctx.set_aspect( 'container', children=component )
from dazzler.components import core, extra from dazzler.system import Page, BindingContext page = Page( __name__, core.Container([ extra.TreeView([ 'item12', { 'identifier': 'nest', 'label': 'nest', 'items': [ 'nested1', 'nested2', { 'label': 'subnest', 'identifier': 'subnest', 'items': ['sub1', 'sub2'] } ], } ], identity='treeview'), core.Container(identity='output') ])) @page.bind('selected@treeview') async def on_selected(ctx: BindingContext): await ctx.set_aspect('output', children=ctx.trigger.value)
[1, 2, 3, 4], [1, 'foo', 'bar', 4], [{'arr': [1, 2, 3], 'foo': 'bar'}], [[1, 2, 4], ['foo', 'bar']] ] ) ] for i in range(0, 4)), 2))) page = Page( __name__, core.Container([ core.Store(identity='empty-store'), core.Store(data={'foo': 'bar'}, identity='initial-store'), core.Button('click', identity='click'), core.Container(identity='click-output'), core.Container(identity='initial-output'), core.Button('type-click', identity='type-click'), core.Store(identity='type-store'), core.Container(identity='type-output'), core.Button('get-aspect', identity='get-aspect-click'), core.Container(identity='get-aspect-output') ]) ) @page.bind(Trigger('initial-store', 'data')) async def initial(ctx: BindingContext): await ctx.set_aspect( 'initial-output', children=json.dumps(ctx.trigger.value) )
from dazzler import Dazzler from dazzler.system import Page from dazzler.components import core app = Dazzler(__name__) app.config.requirements.prefer_external = True app.add_page(Page('index', core.Container('foo'), url='/'))
import asyncio import json from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext, State page = Page( 'binding-tree', core.Container([ core.Button('trigger', identity='trigger'), core.Container([ core.Container([ core.Input(identity=f'output-{i}', type='number') for i in range(1, 3) ]), core.Container([ core.Input(identity=f'value-{i}', type='number') for i in range(1, 11) ]), core.Container('[]', identity='output'), core.Container(identity='done') ]) ])) @page.bind(Trigger('trigger', 'clicks')) async def trigger_click(context: BindingContext): await context.set_aspect('output-1', value=1) # Got to alternate the inputs for the first set to complete and let # frontend to register the state and all, # so as long as this start after and the other delay # is a little higher it should be ok.
""" Page get_aspect_error of dazzler Created 2019-06-15 """ from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext from dazzler.errors import GetAspectError page = Page( __name__, core.Container([ core.Button('click error', identity='click-error'), core.Container(identity='error-output') ])) @page.bind(Trigger('click-error', 'clicks')) async def trigger_error(ctx: BindingContext): try: await ctx.get_aspect('invalid', 'error') except GetAspectError as err: await ctx.set_aspect('error-output', children=err.args[0])
from dazzler import Dazzler from dazzler.components import core from dazzler.system import Page app = Dazzler(__name__) async def layout(_): return core.Container('Layout as function', identity='layout') page = Page( __name__, url='/', layout=layout, ) app.add_page(page) if __name__ == '__main__': app.start('-v --debug=1 --port=5420'.split())
""" Page icons of dazzler Created 2021-06-13 """ from dazzler.components import core, icons from dazzler.system import Page page = Page( __name__, core.Container([ icons.IconLoader([]), icons.LinearIconPack(), icons.FoundIconPack(), icons.OpenIconicPack(), icons.TypiconsPack(), core.Container(icons.Icon('lnr-home'), ), core.Container(icons.Icon('fi-home')), core.Container(icons.Icon('oi-bug')), core.Container(icons.Icon('typcn-globe')), ]))
from dazzler import Dazzler from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext page = Page(name='page', url='/', layout=core.Container([ core.Button('click', identity='clicker'), core.Container('output', identity='output') ])) app = Dazzler(__name__) app.add_page(page) @page.bind(Trigger('clicker', 'clicks')) async def on_click(context: BindingContext): await context.set_aspect('output', children=core.Container('from binding', id='from-binding')) if __name__ == '__main__': app.start('-v --debug=1 --port=8151'.split())
from dazzler import Dazzler from dazzler.components import core from dazzler.system import Page app = Dazzler(__name__) for num in ('one', 'two', 'three', 'four'): page = Page( name=num, layout=core.Container(f'Page {num}', identity='content'), title=f'Page {num}', ) app.add_page(page) if __name__ == '__main__': app.start('-v --debug 1'.split())
""" Page pager of dazzler Created 2019-09-03 """ from dazzler.components import core, extra from dazzler.system import Page, Trigger, BindingContext items = list(range(1, 200)) page = Page( __name__, core.Container([ core.Grid([], columns=2, identity='output'), extra.Pager(total_items=len(items), items_per_page=10, identity='pager'), core.Container(identity='num_pages'), ])) @page.bind(Trigger('pager', 'current_page')) async def on_page(ctx: BindingContext): start = await ctx.get_aspect('pager', 'start_offset') stop = await ctx.get_aspect('pager', 'end_offset') await ctx.set_aspect('output', children=items[start:stop]) @page.bind(Trigger('pager', 'total_pages')) async def on_total(ctx: BindingContext): await ctx.set_aspect('num_pages', children=ctx.trigger.value)
""" Page initial_trigger of dazzler Created 2019-06-15 """ from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext, State page = Page( 'initial-trigger', core.Container([ core.Input(value=10, identity='input'), core.Container(identity='output'), core.Input(value=88, identity='state'), core.Container(identity='state-output') ])) @page.bind(Trigger('input', 'value'), State('state', 'value')) async def on_value(context: BindingContext): await context.set_aspect('output', children=f'Input {context.trigger.value}') await context.set_aspect( 'state-output', children=F'State {context.states["state"]["value"]}')
Created 2019-08-24 """ import datetime import pytz from dazzler.components import core, calendar from dazzler.system import Page past = datetime.datetime(day=22, month=11, year=1986, tzinfo=pytz.utc) future = datetime.datetime(day=11, month=9, year=2031, tzinfo=pytz.utc) page = Page( __name__, core.Container([ calendar.Calendar(identity='initial-calendar'), # FIXME * 1000 JavaScript are in ms where Python ts in seconds. calendar.Calendar( datetime.datetime.timestamp(past) * 1000, identity='past-calendar' ), calendar.Calendar( datetime.datetime.timestamp(future) * 1000, identity='future-calendar' ), calendar.Calendar(use_selected=False), calendar.DatePicker(identity='single-picker'), calendar.TimePicker(fallback_mode=True, identity='time-picker'), calendar.Timestamp(past.timestamp() * 1000, format='DD MM YYYY'), ]) )
""" Page progress of dazzler Created 2019-06-26 """ from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext, State page = Page( __name__, core.Container([ core.ProgressBar(identity='progress', minimum=0, high=80, low=20, maximum=100, rounded=True, optimum=21, striped=True, progress_text='percent'), core.Button('add progress', identity='progress-btn'), core.Container(identity='counter') ])) @page.bind(Trigger('progress-btn', 'clicks'), State('progress', 'value')) async def on_meter(ctx: BindingContext): new_value = (ctx.states['progress']['value'] or 0) + 1 await ctx.set_aspect('progress', value=new_value) await ctx.set_aspect('counter', children=new_value)
page = Page( __name__, core.Container([ spec.ComponentAsAspect( identity='component', single=core.Button('single', identity='single'), array=[ core.Input(value=x, identity=f'array-{x}', type='number') for x in arr ], shape={'shaped': core.Button('shaped', identity='shaped')}, list_of_dict=[ { 'label': core.Container( f'label{x}', identity=f'label-{x}' ), 'value': f'label-{x}' } for x in arr ] ), core.Container(identity='single-output'), core.Container([ core.Container(identity=f'output-array-{x}') for x in arr ]), core.Button('click sum', identity='click-sum'), core.Container(identity='sum-output'), core.Container(identity='shaped-output'), ]) )
""" Page markdown of dazzler Created 2019-08-19 """ from dazzler.components import core, markdown as md from dazzler.system import Page text = ''' # Foo ## Bar [google](http://google.com) ```jsx const Foo = props => <div>{props.text}</div>; ``` ''' page = Page( __name__, core.Container([ md.Markdown(text, identity='markdown'), md.CodeBlock(value=text, language='md') ]))
""" Page grid of dazzler Created 2019-07-08 """ from dazzler.components import core from dazzler.system import Page page = Page( __name__, core.Container( [core.Grid([x for x in range(1, 101)], 10, identity='grid')]))
import functools from dazzler.components import core from dazzler.system import Page, Trigger, BindingContext page = Page( 'binding-chain', core.Container([ core.Button(x, identity=f'trigger-{x}') for x in range(1, 21) ] + [core.Container(identity='output')]) ) async def update_next(context: BindingContext, num: int = 0): await context.set_aspect( f'trigger-{num+1}', clicks=1, ) @page.bind(Trigger('trigger-20', 'clicks')) async def last_trigger(context: BindingContext): await context.set_aspect('output', children='output generated') for i in range(1, 20): page.bind(Trigger(f'trigger-{i}', 'clicks'))( functools.partial(update_next, num=i) )
""" Page form of dazzler Created 2019-07-14 """ from aiohttp import web from dazzler.components import core from dazzler.system import Page, RouteMethod page = Page( __name__, core.Container([ core.Form(fields=[ { 'label': 'Field 1', 'name': 'field1', 'type': 'text' }, ], action='/submit-form', method='post', identity='form') ])) @page.route('/submit-form', method=RouteMethod.POST, prefix=False) async def submit(request: web.Request): data = await request.post() return web.Response(body=f'<div id="output">{data.get("field1")}</div>', content_type='text/html')