StateTree implements NodeOwner { public StateNode getRootNode() { return rootNode; } @SafeVarargs  StateTree(UIInternals uiInternals,
            Class<? extends NodeFeature>... features); StateNode getRootNode(); @Override int register(StateNode node); @Override void unregister(StateNode node); @Override boolean hasNode(StateNode node); StateNode getNodeById(int id); void collectChanges(Consumer<NodeChange> collector); @Override void markAsDirty(StateNode node); Set<StateNode> collectDirtyNodes(); boolean hasDirtyNodes(); UI getUI(); ExecutionRegistration beforeClientResponse(StateNode context,
            SerializableConsumer<ExecutionContext> execution); void runExecutionsBeforeClientResponse(); boolean isDirty(); void prepareForResync();  }
@Test public void rootNodeState() { StateNode rootNode = tree.getRootNode(); Assert.assertNull("Root node should have no parent", rootNode.getParent()); Assert.assertTrue("Root node should always be attached", rootNode.isAttached()); Assert.assertEquals("Root node should always have the same id", 1, rootNode.getId()); Assert.assertSame(tree, rootNode.getOwner()); }
@Test(expected = IllegalStateException.class) public void rootNode_setStateNodeAsParent_throws() { tree.getRootNode().setParent(new StateNode()); }
@Test public void attachedNodeIsAttached() { StateNode node = StateNodeTest.createEmptyNode(); Assert.assertFalse("New node should not be attached", node.isAttached()); StateNodeTest.setParent(node, tree.getRootNode()); Assert.assertTrue("Node with parent set should be attached", node.isAttached()); StateNodeTest.setParent(node, null); Assert.assertFalse("Node without parent should not be attached", node.isAttached()); }
@Test(expected = IllegalStateException.class) public void moveNodeToOtherRoot_throws() { StateNode node = StateNodeTest.createEmptyNode(); StateNodeTest.setParent(node, tree.getRootNode()); StateNodeTest.setParent(node, null); StateTree anotherTree = new StateTree(new UI().getInternals(), ElementChildrenList.class); StateNodeTest.setParent(node, anotherTree.getRootNode()); }
@Test public void testTreeChangeCollection() { StateNode node2 = StateNodeTest.createEmptyNode(); StateNodeTest.setParent(node2, tree.getRootNode()); List<NodeChange> changes = collectChangesExceptChildrenAddRemove(); Assert.assertEquals(1, changes.size()); NodeAttachChange nodeChange = (NodeAttachChange) changes.get(0); Assert.assertSame(node2, nodeChange.getNode()); }
@Test public void testDetachInChanges() { StateNode node1 = tree.getRootNode(); StateNode node2 = StateNodeTest.createEmptyNode(); StateNodeTest.setParent(node2, node1); collectChangesExceptChildrenAddRemove(); StateNodeTest.setParent(node2, null); List<NodeChange> changes = collectChangesExceptChildrenAddRemove(); Assert.assertEquals("Should be one change.", 1, changes.size()); Assert.assertTrue("Should have a detach change", changes.get(0) instanceof NodeDetachChange); }
@Test public void allValuesAfterReattach() { StateNode node1 = tree.getRootNode(); StateNode node2 = new StateNode(ElementData.class); StateNodeTest.setParent(node2, node1); node2.getFeature(ElementData.class).setTag("foo"); collectChangesExceptChildrenAddRemove(); StateNodeTest.setParent(node2, null); collectChangesExceptChildrenAddRemove(); StateNodeTest.setParent(node2, node1); List<NodeChange> changes = collectChangesExceptChildrenAddRemove(); Assert.assertEquals("Should be three changes.", 2, changes.size()); Assert.assertTrue("First change should re-attach the node.", changes.get(0) instanceof NodeAttachChange); Assert.assertTrue("Second change should put the tag or payload value.", changes.get(1) instanceof MapPutChange); Optional<MapPutChange> tagFound = changes.stream() .filter(MapPutChange.class::isInstance) .map(MapPutChange.class::cast) .filter(chang -> chang.getKey().equals("tag")).findFirst(); Assert.assertTrue("No tag change found", tagFound.isPresent()); MapPutChange nodeChange = tagFound.get(); Assert.assertEquals(ElementData.class, nodeChange.getFeature()); Assert.assertEquals("tag", nodeChange.getKey()); Assert.assertEquals("foo", nodeChange.getValue()); }
@Test public void testSerializable() { @SuppressWarnings("unchecked") Class<? extends NodeFeature>[] features = new Class[] { ElementChildrenList.class, ElementData.class, ElementAttributeMap.class, ElementPropertyMap.class }; StateTree tree = new StateTree(new UI().getInternals(), features); StateNode root = tree.getRootNode(); root.getFeature(ElementData.class).setTag("body"); StateNode child = new StateNode(features); root.getFeature(ElementChildrenList.class).add(0, child); child.getFeature(ElementData.class).setTag(Tag.DIV); byte[] serialized = SerializationUtils.serialize(tree); StateTree d1 = (StateTree) SerializationUtils.deserialize(serialized); Assert.assertNotNull(d1); }