var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
define(["require", "exports", "jquery", "wed/convert", "wed/dloc", "wed/domutil", "wed/guiroot", "../util", "../wed-test-util"], function (require, exports, jquery_1, convert, dloc_1, domutil_1, guiroot, util_1, wed_test_util_1) {
    /**
     * @author Louis-Dominique Dubeau
     * @license MPL 2.0
     * @copyright Mangalam Research Center for Buddhist Languages
     */
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    jquery_1 = __importDefault(jquery_1);
    convert = __importStar(convert);
    guiroot = __importStar(guiroot);
    const assert = chai.assert;
    // tslint:disable:no-any
    function defined(x) {
        assert.isDefined(x);
        // The assertion above already excludes null and undefined, but TypeScript
        // does not know this.
        return x;
    }
    describe("guiroot", () => {
        let $root;
        let root;
        let rootObj;
        let htmlTree;
        let xmlDoc;
        before(() => new util_1.DataProvider(`${wed_test_util_1.dataPath}/guiroot_test_data/`)
            .getText("source_converted.xml")
            .then((sourceXML) => {
            root = document.createElement("div");
            document.body.appendChild(root);
            $root = jquery_1.default(root);
            const parser = new window.DOMParser();
            xmlDoc = parser.parseFromString(sourceXML, "text/xml");
            htmlTree = convert.toHTMLTree(window.document, xmlDoc.firstElementChild);
            root.appendChild(htmlTree.cloneNode(true));
            rootObj = new guiroot.GUIRoot(root);
        }));
        after(() => {
            document.body.removeChild(root);
        });
        describe("GUIRoot", () => {
            it("marks the root", () => {
                assert.equal(dloc_1.findRoot(root), rootObj);
            });
            it("fails if the node is already marked", () => {
                assert.throws(() => {
                    new guiroot.GUIRoot(root);
                }, Error, "node already marked as root");
            });
            describe("nodeToPath", () => {
                afterEach(() => {
                    // Reset the tree.
                    $root.empty();
                    root.appendChild(htmlTree.cloneNode(true));
                });
                it("returns an empty string on root", () => {
                    assert.equal(rootObj.nodeToPath(root), "");
                });
                it("returns a correct path on text node", () => {
                    const node = defined($root.find(".title")[0].childNodes[0]);
                    assert.equal(rootObj.nodeToPath(node), "0/0/0/0/0/0");
                });
                it("returns a correct path on phantom_wrap nodes", () => {
                    $root.find(".p").wrap("<div class='_phantom_wrap'>");
                    const node = defined($root.find(".p").get(-1));
                    assert.equal(rootObj.nodeToPath(node), "0/1/0/1");
                });
                it("returns a correct path on later text node", () => {
                    const node = defined($root.find(".body>.p").get(-1).childNodes[2]);
                    assert.equal(rootObj.nodeToPath(node), "0/1/0/1/2");
                });
                it("returns a correct path on attribute", () => {
                    let node = defined($root.find(".body>.p:last-of-type>.quote")[0]);
                    // Decorate it.
                    jquery_1.default(node).prepend("<span class=\"_gui _phantom __start_label _quote_label" +
                        " _label_level_1 _label\"><span class=\"_phantom\">" +
                        "&nbsp; quote <span class=\"_phantom _attribute\">" +
                        "<span class=\"_phantom _attribute_name\">type</span>" +
                        "=<span class=\"_phantom _attribute_value\">q</span>" +
                        "</span> >&nbsp;</span></span>");
                    node = defined(jquery_1.default(node).find("._attribute_value")[0]);
                    assert.equal(rootObj.nodeToPath(node), "0/1/0/1/1/@type");
                });
                it("returns a correct path on text node in attribute", () => {
                    let node = defined($root.find(".body>.p:last-of-type>.quote")[0]);
                    // Decorate it.
                    jquery_1.default(node).prepend("<span class=\"_gui _phantom __start_label _quote_label" +
                        " _label_level_1 _label\"><span class=\"_phantom\">" +
                        "&nbsp; quote <span class=\"_phantom _attribute\">" +
                        "<span class=\"_phantom _attribute_name\">type</span>" +
                        "=<span class=\"_phantom _attribute_value\">q</span>" +
                        "</span> >&nbsp;</span></span>");
                    node = defined(jquery_1.default(node).find("._attribute_value")[0].childNodes[0]);
                    assert.equal(rootObj.nodeToPath(node), "0/1/0/1/1/@type");
                });
                it("fails on a node which is not a descendant of its root", () => {
                    const node = defined(jquery_1.default("body")[0]);
                    assert.throws(rootObj.nodeToPath.bind(rootObj, node), Error, "node is not a descendant of root");
                });
                it("fails on invalid node", () => {
                    assert.throws(rootObj.nodeToPath.bind(rootObj, null), Error, "node is not a descendant of root");
                    assert.throws(rootObj.nodeToPath.bind(rootObj, undefined), Error, "node is not a descendant of root");
                });
                it("is equivalent to nodeToPath on a data tree", () => {
                    const dataRootObj = new dloc_1.DLocRoot(xmlDoc);
                    domutil_1.linkTrees(xmlDoc.firstElementChild, root.firstElementChild);
                    let targetDataNode = xmlDoc.getElementsByTagName("quote")[0];
                    const phantomWrapTemplate = "<span class='_phantom_wrap'></span>";
                    jquery_1.default(jquery_1.default.data(targetDataNode, "wed_mirror_node"))
                        .wrap(phantomWrapTemplate)
                        .after("<span class='_phantom'>Boo</span>Blip")
                        .wrap(phantomWrapTemplate);
                    const dataNode = targetDataNode.parentNode;
                    // Wrap twice for good measure.
                    jquery_1.default(jquery_1.default.data(dataNode, "wed_mirror_node"))
                        .wrap(phantomWrapTemplate)
                        .wrap(phantomWrapTemplate);
                    targetDataNode = xmlDoc.getElementsByTagName("quote")[1];
                    const targetGuiNode = jquery_1.default.data(targetDataNode, "wed_mirror_node");
                    const guiPath = rootObj.nodeToPath(targetGuiNode);
                    // tslint:disable-next-line:no-shadowed-variable
                    const dataPath = dataRootObj.nodeToPath(targetDataNode);
                    // Both paths should be equal.
                    assert.equal(guiPath, dataPath);
                    // It should also be reversible.
                    assert.equal(rootObj.pathToNode(guiPath), targetGuiNode);
                });
            });
            describe("pathToNode", () => {
                it("returns root when passed an empty string", () => {
                    assert.equal(rootObj.pathToNode(""), root);
                });
                it("returns a correct node on a text path", () => {
                    const node = defined($root.find(".title")[0].childNodes[0]);
                    assert.equal(rootObj.pathToNode("0/0/0/0/0/0"), node);
                });
                it("returns a correct node on a later text path", () => {
                    const node = defined($root.find(".body>.p").get(-1).childNodes[2]);
                    assert.equal(rootObj.pathToNode("0/1/0/1/2"), node);
                });
                it("returns a correct node on attribute path", () => {
                    let node = defined($root.find(".body>.p:last-of-type>.quote")[0]);
                    // Decorate it.
                    jquery_1.default(node).prepend("<span class=\"_gui _phantom __start_label _quote_label" +
                        " _label_level_1 _label\"><span class=\"_phantom\">" +
                        "&nbsp; quote <span class=\"_phantom _attribute\">" +
                        "<span class=\"_phantom _attribute_name\">type</span>" +
                        "=<span class=\"_phantom _attribute_value\">q</span>" +
                        "</span> >&nbsp;</span></span>");
                    node = defined(jquery_1.default(node).find("._attribute_value")[0]);
                    assert.equal(rootObj.pathToNode("0/1/0/1/1/@type"), node);
                });
                it("returns a correct node when path contains _phantom_wrap", () => {
                    $root.find(".p").wrap("<div class='_phantom_wrap'>");
                    const node = defined($root.find(".p").get(-1));
                    assert.equal(rootObj.pathToNode("0/1/0/1"), node);
                });
                it("accepts more than one digit per path step", () => {
                    // There was a stupid bug in an earlier version which would make this
                    // fail with an exception complaining that the path was malformed due to
                    // the presence of "10". The null return value is fine since there is no
                    // such element, but at least it should not generate an exception.
                    assert.equal(rootObj.pathToNode("0/10"), null);
                });
                it("fails on malformed path", () => {
                    assert.throws(rootObj.pathToNode.bind(rootObj, "+"), Error, "malformed path expression");
                });
            });
        });
    });
});
//# sourceMappingURL=guiroot-test.js.map