async def test_render_raw_vdom_dict_with_single_component_object_as_children(): @idom.component def Main(): return {"tagName": "div", "children": Child()} @idom.component def Child(): return {"tagName": "div", "children": {"tagName": "h1"}} async with idom.Layout(Main()) as layout: patch = await layout.render() assert_same_items( patch.changes, [ { "op": "add", "path": "/children", "value": [{ "tagName": "div", "children": [{ "tagName": "h1" }] }], }, { "op": "add", "path": "/tagName", "value": "div" }, ], )
async def test_nested_component_layout(): parent_set_state = idom.Ref(None) child_set_state = idom.Ref(None) @idom.component def Parent(): state, parent_set_state.current = idom.hooks.use_state(0) return idom.html.div(state, Child()) @idom.component def Child(): state, child_set_state.current = idom.hooks.use_state(0) return idom.html.div(state) async with idom.Layout(Parent()) as layout: path, changes = await layout.render() assert path == "" assert_same_items( changes, [ { "op": "add", "path": "/children", "value": ["0", { "tagName": "div", "children": ["0"] }], }, { "op": "add", "path": "/tagName", "value": "div" }, ], ) parent_set_state.current(1) path, changes = await layout.render() assert path == "" assert changes == [{ "op": "replace", "path": "/children/0", "value": "1" }] child_set_state.current(1) path, changes = await layout.render() assert path == "/children/1" assert changes == [{ "op": "replace", "path": "/children/0", "value": "1" }]
async def test_layout_render_error_has_partial_update(): @idom.component def Main(): return idom.html.div([OkChild(), BadChild(), OkChild()]) @idom.component def OkChild(): return idom.html.div(["hello"]) @idom.component def BadChild(): raise ValueError("Something went wrong :(") async with idom.Layout(Main()) as layout: patch = await layout.render() assert_same_items( patch.changes, [ { "op": "add", "path": "/children", "value": [ { "tagName": "div", "children": ["hello"] }, { "tagName": "div", "__error__": "Something went wrong :(" }, { "tagName": "div", "children": ["hello"] }, ], }, { "op": "add", "path": "/tagName", "value": "div" }, ], )
async def test_simple_stateful_component(): @idom.component def SimpleStatefulComponent(): index, set_index = idom.hooks.use_state(0) set_index(index + 1) return idom.html.div(index) sse = SimpleStatefulComponent() async with idom.Layout(sse) as layout: patch_1 = await layout.render() assert patch_1.path == "" assert_same_items( patch_1.changes, [ { "op": "add", "path": "/children", "value": ["0"] }, { "op": "add", "path": "/tagName", "value": "div" }, ], ) patch_2 = await layout.render() assert patch_2.path == "" assert patch_2.changes == [{ "op": "replace", "path": "/children/0", "value": "1" }] patch_3 = await layout.render() assert patch_3.path == "" assert patch_3.changes == [{ "op": "replace", "path": "/children/0", "value": "2" }]
def test_find_js_module_exports_in_source(module_source, expected_names): assert_same_items(find_js_module_exports_in_source(module_source), expected_names)
def test_web_module_exports(victory): assert_same_items( web_module_exports("victory"), [ "Area", "Axis", "Background", "Bar", "Border", "Box", "BrushHelpers", "Candle", "Circle", "ClipPath", "Collection", "CursorHelpers", "Curve", "Data", "DefaultTransitions", "Domain", "ErrorBar", "Events", "Flyout", "Helpers", "LabelHelpers", "Line", "LineSegment", "Log", "Path", "Point", "Portal", "PropTypes", "RawZoomHelpers", "Rect", "Scale", "Selection", "SelectionHelpers", "Slice", "Style", "TSpan", "Text", "TextSize", "Transitions", "VictoryAnimation", "VictoryArea", "VictoryAxis", "VictoryBar", "VictoryBoxPlot", "VictoryBrushContainer", "VictoryBrushLine", "VictoryCandlestick", "VictoryChart", "VictoryClipContainer", "VictoryContainer", "VictoryCursorContainer", "VictoryErrorBar", "VictoryGroup", "VictoryHistogram", "VictoryLabel", "VictoryLegend", "VictoryLine", "VictoryPie", "VictoryPolarAxis", "VictoryPortal", "VictoryScatter", "VictorySelectionContainer", "VictorySharedEvents", "VictoryStack", "VictoryTheme", "VictoryTooltip", "VictoryTransition", "VictoryVoronoi", "VictoryVoronoiContainer", "VictoryZoomContainer", "Voronoi", "VoronoiHelpers", "Whisker", "Wrapper", "ZoomHelpers", "addEvents", "brushContainerMixin", "combineContainerMixins", "createContainer", "cursorContainerMixin", "makeCreateContainerFunction", "selectionContainerMixin", "voronoiContainerMixin", "zoomContainerMixin", ], )
async def test_shared_state_dispatcher(): done = asyncio.Event() changes_1 = [] changes_2 = [] target_id = "an-event" events_to_inject = [LayoutEvent(target=target_id, data=[])] * 4 async def send_1(patch): changes_1.append(patch.changes) async def recv_1(): await asyncio.sleep(0) try: return events_to_inject.pop(0) except IndexError: done.set() raise asyncio.CancelledError() async def send_2(patch): changes_2.append(patch.changes) async def recv_2(): await done.wait() raise asyncio.CancelledError() @idom.component def Clickable(): count, set_count = idom.hooks.use_state(0) @idom.event(target_id=target_id) async def an_event(): set_count(count + 1) return idom.html.div({"anEvent": an_event, "count": count}) async with SharedViewDispatcher(Layout(Clickable())) as dispatcher: await dispatcher.run(send_1, recv_1, "1") await dispatcher.run(send_2, recv_2, "2") expected_changes = [ [ { "op": "add", "path": "/eventHandlers", "value": { "anEvent": { "target": "an-event", "preventDefault": False, "stopPropagation": False, } }, }, { "op": "add", "path": "/attributes", "value": { "count": 0 } }, { "op": "add", "path": "/tagName", "value": "div" }, ], [{ "op": "replace", "path": "/attributes/count", "value": 1 }], [{ "op": "replace", "path": "/attributes/count", "value": 2 }], [{ "op": "replace", "path": "/attributes/count", "value": 3 }], ] for c_2, expected_c in zip(changes_2, expected_changes): assert_same_items(c_2, expected_c) assert changes_1 == changes_2