@Test
public void testFromJson_nodeTypeFilters() throws Exception {

    final File targetFile = new File(testOutDir, "testFromJson_nodeTypeFilters.json");
    if (targetFile.exists()) {
        targetFile.delete();
    }
    final String fooMixin1 = "foo:mixin1";
    final String fooMixin2 = "foo:mixin2";
    final List<JcrNs> nsList = Collections.singletonList(JcrNs.create("foo", "http://foo.com"));
    OakMachine.Builder oak = TestUtil.fromPlan(obj()
            .key("jcrNamespaces", nsList)
            .key("jcrNodetypes", obj()
                    .key("foo:folder", key("extends", arr("nt:folder")))
                    .key(fooMixin1, key("@", arr("mixin")))
                    .key(fooMixin2, key("@", arr("mixin"))))
            .key("forcedRoots", arr()
                    .val(new ForcedRoot().withPath("/foo1").withPrimaryType("nt:folder").withMixinTypes("mix:title", fooMixin1))
                    .val(new ForcedRoot().withPath("/foo2").withPrimaryType("nt:unstructured").withMixinTypes(fooMixin1))
            )
            .get());
    WebsterChecklistTarget target = WebsterChecklistTarget.fromJson(targetFile, obj()
            .key("jcrNamespaces", nsList)
            .key("selectors", arr()
                    .val(key("type", "nodetype").key("args", arr("mix:title")))
                    .val(key("type", "query").key("args", arr("select * from [nt:unstructured] as nun where issamenode([nun], '/foo2')"))))
            .key("nodeTypeFilters", arr()
                    .val(new Rule(RuleType.INCLUDE, Pattern.compile("foo:mixin.*"))))
            .key("exportNodeTypes", arr(fooMixin2))
            .get());
    oak.build().adminInitAndInspect(target::perform);
    assertJsonFile(targetFile, json -> {
        final Checklist checklist = Checklist.fromJson("testFromJson", null, json);
        assertEquals("expect 2 roots", 2, checklist.getForcedRoots().size());
        assertEquals("expect root path", "/foo1", checklist.getForcedRoots().get(0).getPath());
        assertNull("expect no primary type", checklist.getForcedRoots().get(0).getPrimaryType());
        assertEquals("expect mixins", Collections.singletonList(fooMixin1),
                checklist.getForcedRoots().get(0).getMixinTypes());
        assertEquals("expect root path", "/foo2", checklist.getForcedRoots().get(1).getPath());
        assertNull("expect no primary type", checklist.getForcedRoots().get(1).getPrimaryType());
        assertEquals("expect mixins", Collections.singletonList(fooMixin1),
                checklist.getForcedRoots().get(1).getMixinTypes());
        assertEquals("two types were exported", 2, checklist.getJcrNodetypes().size());
        final NamePathResolver resolver = new DefaultNamePathResolver(JsonCnd.toNamespaceMapping(nsList));
        assertEquals("foo:mixin1 node type was exported", uncheck1(resolver::getQName).apply(fooMixin1),
                checklist.getJcrNodetypes().get(0).getName());
        assertEquals("foo:mixin2 node type was exported", uncheck1(resolver::getQName).apply(fooMixin2),
                checklist.getJcrNodetypes().get(1).getName());
    });
}