browser/devtools/sourceeditor/test/cm_doc_test.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/devtools/sourceeditor/test/cm_doc_test.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,348 @@
     1.4 +(function() {
     1.5 +  // A minilanguage for instantiating linked CodeMirror instances and Docs
     1.6 +  function instantiateSpec(spec, place, opts) {
     1.7 +    var names = {}, pos = 0, l = spec.length, editors = [];
     1.8 +    while (spec) {
     1.9 +      var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/);
    1.10 +      var name = m[1], isDoc = m[2], cur;
    1.11 +      if (m[3]) {
    1.12 +        cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]}));
    1.13 +      } else {
    1.14 +        var other = m[5];
    1.15 +        if (!names.hasOwnProperty(other)) {
    1.16 +          names[other] = editors.length;
    1.17 +          editors.push(CodeMirror(place, opts));
    1.18 +        }
    1.19 +        var doc = editors[names[other]].linkedDoc({
    1.20 +          sharedHist: !m[4],
    1.21 +          from: m[6] ? Number(m[6]) : null,
    1.22 +          to: m[7] ? Number(m[7]) : null
    1.23 +        });
    1.24 +        cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc}));
    1.25 +      }
    1.26 +      names[name] = editors.length;
    1.27 +      editors.push(cur);
    1.28 +      spec = spec.slice(m[0].length);
    1.29 +    }
    1.30 +    return editors;
    1.31 +  }
    1.32 +
    1.33 +  function clone(obj, props) {
    1.34 +    if (!obj) return;
    1.35 +    clone.prototype = obj;
    1.36 +    var inst = new clone();
    1.37 +    if (props) for (var n in props) if (props.hasOwnProperty(n))
    1.38 +      inst[n] = props[n];
    1.39 +    return inst;
    1.40 +  }
    1.41 +
    1.42 +  function eqAll(val) {
    1.43 +    var end = arguments.length, msg = null;
    1.44 +    if (typeof arguments[end-1] == "string")
    1.45 +      msg = arguments[--end];
    1.46 +    if (i == end) throw new Error("No editors provided to eqAll");
    1.47 +    for (var i = 1; i < end; ++i)
    1.48 +      eq(arguments[i].getValue(), val, msg)
    1.49 +  }
    1.50 +
    1.51 +  function testDoc(name, spec, run, opts, expectFail) {
    1.52 +    if (!opts) opts = {};
    1.53 +
    1.54 +    return test("doc_" + name, function() {
    1.55 +      var place = document.getElementById("testground");
    1.56 +      var editors = instantiateSpec(spec, place, opts);
    1.57 +      var successful = false;
    1.58 +
    1.59 +      try {
    1.60 +        run.apply(null, editors);
    1.61 +        successful = true;
    1.62 +      } finally {
    1.63 +        if (!successful || verbose) {
    1.64 +          place.style.visibility = "visible";
    1.65 +        } else {
    1.66 +          for (var i = 0; i < editors.length; ++i)
    1.67 +            if (editors[i] instanceof CodeMirror)
    1.68 +              place.removeChild(editors[i].getWrapperElement());
    1.69 +        }
    1.70 +      }
    1.71 +    }, expectFail);
    1.72 +  }
    1.73 +
    1.74 +  var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
    1.75 +
    1.76 +  function testBasic(a, b) {
    1.77 +    eqAll("x", a, b);
    1.78 +    a.setValue("hey");
    1.79 +    eqAll("hey", a, b);
    1.80 +    b.setValue("wow");
    1.81 +    eqAll("wow", a, b);
    1.82 +    a.replaceRange("u\nv\nw", Pos(0, 3));
    1.83 +    b.replaceRange("i", Pos(0, 4));
    1.84 +    b.replaceRange("j", Pos(2, 1));
    1.85 +    eqAll("wowui\nv\nwj", a, b);
    1.86 +  }
    1.87 +
    1.88 +  testDoc("basic", "A='x' B<A", testBasic);
    1.89 +  testDoc("basicSeparate", "A='x' B<~A", testBasic);
    1.90 +
    1.91 +  testDoc("sharedHist", "A='ab\ncd\nef' B<A", function(a, b) {
    1.92 +    a.replaceRange("x", Pos(0));
    1.93 +    b.replaceRange("y", Pos(1));
    1.94 +    a.replaceRange("z", Pos(2));
    1.95 +    eqAll("abx\ncdy\nefz", a, b);
    1.96 +    a.undo();
    1.97 +    a.undo();
    1.98 +    eqAll("abx\ncd\nef", a, b);
    1.99 +    a.redo();
   1.100 +    eqAll("abx\ncdy\nef", a, b);
   1.101 +    b.redo();
   1.102 +    eqAll("abx\ncdy\nefz", a, b);
   1.103 +    a.undo(); b.undo(); a.undo(); a.undo();
   1.104 +    eqAll("ab\ncd\nef", a, b);
   1.105 +  }, null, ie_lt8);
   1.106 +
   1.107 +  testDoc("undoIntact", "A='ab\ncd\nef' B<~A", function(a, b) {
   1.108 +    a.replaceRange("x", Pos(0));
   1.109 +    b.replaceRange("y", Pos(1));
   1.110 +    a.replaceRange("z", Pos(2));
   1.111 +    a.replaceRange("q", Pos(0));
   1.112 +    eqAll("abxq\ncdy\nefz", a, b);
   1.113 +    a.undo();
   1.114 +    a.undo();
   1.115 +    eqAll("abx\ncdy\nef", a, b);
   1.116 +    b.undo();
   1.117 +    eqAll("abx\ncd\nef", a, b);
   1.118 +    a.redo();
   1.119 +    eqAll("abx\ncd\nefz", a, b);
   1.120 +    a.redo();
   1.121 +    eqAll("abxq\ncd\nefz", a, b);
   1.122 +    a.undo(); a.undo(); a.undo(); a.undo();
   1.123 +    eqAll("ab\ncd\nef", a, b);
   1.124 +    b.redo();
   1.125 +    eqAll("ab\ncdy\nef", a, b);
   1.126 +  });
   1.127 +
   1.128 +  testDoc("undoConflict", "A='ab\ncd\nef' B<~A", function(a, b) {
   1.129 +    a.replaceRange("x", Pos(0));
   1.130 +    a.replaceRange("z", Pos(2));
   1.131 +    // This should clear the first undo event in a, but not the second
   1.132 +    b.replaceRange("y", Pos(0));
   1.133 +    a.undo(); a.undo();
   1.134 +    eqAll("abxy\ncd\nef", a, b);
   1.135 +    a.replaceRange("u", Pos(2));
   1.136 +    a.replaceRange("v", Pos(0));
   1.137 +    // This should clear both events in a
   1.138 +    b.replaceRange("w", Pos(0));
   1.139 +    a.undo(); a.undo();
   1.140 +    eqAll("abxyvw\ncd\nefu", a, b);
   1.141 +  });
   1.142 +
   1.143 +  testDoc("doubleRebase", "A='ab\ncd\nef\ng' B<~A C<B", function(a, b, c) {
   1.144 +    c.replaceRange("u", Pos(3));
   1.145 +    a.replaceRange("", Pos(0, 0), Pos(1, 0));
   1.146 +    c.undo();
   1.147 +    eqAll("cd\nef\ng", a, b, c);
   1.148 +  });
   1.149 +
   1.150 +  testDoc("undoUpdate", "A='ab\ncd\nef' B<~A", function(a, b) {
   1.151 +    a.replaceRange("x", Pos(2));
   1.152 +    b.replaceRange("u\nv\nw\n", Pos(0, 0));
   1.153 +    a.undo();
   1.154 +    eqAll("u\nv\nw\nab\ncd\nef", a, b);
   1.155 +    a.redo();
   1.156 +    eqAll("u\nv\nw\nab\ncd\nefx", a, b);
   1.157 +    a.undo();
   1.158 +    eqAll("u\nv\nw\nab\ncd\nef", a, b);
   1.159 +    b.undo();
   1.160 +    a.redo();
   1.161 +    eqAll("ab\ncd\nefx", a, b);
   1.162 +    a.undo();
   1.163 +    eqAll("ab\ncd\nef", a, b);
   1.164 +  });
   1.165 +
   1.166 +  testDoc("undoKeepRanges", "A='abcdefg' B<A", function(a, b) {
   1.167 +    var m = a.markText(Pos(0, 1), Pos(0, 3), {className: "foo"});
   1.168 +    b.replaceRange("x", Pos(0, 0));
   1.169 +    eqPos(m.find().from, Pos(0, 2));
   1.170 +    b.replaceRange("yzzy", Pos(0, 1), Pos(0));
   1.171 +    eq(m.find(), null);
   1.172 +    b.undo();
   1.173 +    eqPos(m.find().from, Pos(0, 2));
   1.174 +    b.undo();
   1.175 +    eqPos(m.find().from, Pos(0, 1));
   1.176 +  });
   1.177 +
   1.178 +  testDoc("longChain", "A='uv' B<A C<B D<C", function(a, b, c, d) {
   1.179 +    a.replaceSelection("X");
   1.180 +    eqAll("Xuv", a, b, c, d);
   1.181 +    d.replaceRange("Y", Pos(0));
   1.182 +    eqAll("XuvY", a, b, c, d);
   1.183 +  });
   1.184 +
   1.185 +  testDoc("broadCast", "B<A C<A D<A E<A", function(a, b, c, d, e) {
   1.186 +    b.setValue("uu");
   1.187 +    eqAll("uu", a, b, c, d, e);
   1.188 +    a.replaceRange("v", Pos(0, 1));
   1.189 +    eqAll("uvu", a, b, c, d, e);
   1.190 +  });
   1.191 +
   1.192 +  // A and B share a history, C and D share a separate one
   1.193 +  testDoc("islands", "A='x\ny\nz' B<A C<~A D<C", function(a, b, c, d) {
   1.194 +    a.replaceRange("u", Pos(0));
   1.195 +    d.replaceRange("v", Pos(2));
   1.196 +    b.undo();
   1.197 +    eqAll("x\ny\nzv", a, b, c, d);
   1.198 +    c.undo();
   1.199 +    eqAll("x\ny\nz", a, b, c, d);
   1.200 +    a.redo();
   1.201 +    eqAll("xu\ny\nz", a, b, c, d);
   1.202 +    d.redo();
   1.203 +    eqAll("xu\ny\nzv", a, b, c, d);
   1.204 +  });
   1.205 +
   1.206 +  testDoc("unlink", "B<A C<A D<B", function(a, b, c, d) {
   1.207 +    a.setValue("hi");
   1.208 +    b.unlinkDoc(a);
   1.209 +    d.setValue("aye");
   1.210 +    eqAll("hi", a, c);
   1.211 +    eqAll("aye", b, d);
   1.212 +    a.setValue("oo");
   1.213 +    eqAll("oo", a, c);
   1.214 +    eqAll("aye", b, d);
   1.215 +  });
   1.216 +
   1.217 +  testDoc("bareDoc", "A*='foo' B*<A C<B", function(a, b, c) {
   1.218 +    is(a instanceof CodeMirror.Doc);
   1.219 +    is(b instanceof CodeMirror.Doc);
   1.220 +    is(c instanceof CodeMirror);
   1.221 +    eqAll("foo", a, b, c);
   1.222 +    a.replaceRange("hey", Pos(0, 0), Pos(0));
   1.223 +    c.replaceRange("!", Pos(0));
   1.224 +    eqAll("hey!", a, b, c);
   1.225 +    b.unlinkDoc(a);
   1.226 +    b.setValue("x");
   1.227 +    eqAll("x", b, c);
   1.228 +    eqAll("hey!", a);
   1.229 +  });
   1.230 +
   1.231 +  testDoc("swapDoc", "A='a' B*='b' C<A", function(a, b, c) {
   1.232 +    var d = a.swapDoc(b);
   1.233 +    d.setValue("x");
   1.234 +    eqAll("x", c, d);
   1.235 +    eqAll("b", a, b);
   1.236 +  });
   1.237 +
   1.238 +  testDoc("docKeepsScroll", "A='x' B*='y'", function(a, b) {
   1.239 +    addDoc(a, 200, 200);
   1.240 +    a.scrollIntoView(Pos(199, 200));
   1.241 +    var c = a.swapDoc(b);
   1.242 +    a.swapDoc(c);
   1.243 +    var pos = a.getScrollInfo();
   1.244 +    is(pos.left > 0, "not at left");
   1.245 +    is(pos.top > 0, "not at top");
   1.246 +  });
   1.247 +
   1.248 +  testDoc("copyDoc", "A='u'", function(a) {
   1.249 +    var copy = a.getDoc().copy(true);
   1.250 +    a.setValue("foo");
   1.251 +    copy.setValue("bar");
   1.252 +    var old = a.swapDoc(copy);
   1.253 +    eq(a.getValue(), "bar");
   1.254 +    a.undo();
   1.255 +    eq(a.getValue(), "u");
   1.256 +    a.swapDoc(old);
   1.257 +    eq(a.getValue(), "foo");
   1.258 +    eq(old.historySize().undo, 1);
   1.259 +    eq(old.copy(false).historySize().undo, 0);
   1.260 +  });
   1.261 +
   1.262 +  testDoc("docKeepsMode", "A='1+1'", function(a) {
   1.263 +    var other = CodeMirror.Doc("hi", "text/x-markdown");
   1.264 +    a.setOption("mode", "text/javascript");
   1.265 +    var old = a.swapDoc(other);
   1.266 +    eq(a.getOption("mode"), "text/x-markdown");
   1.267 +    eq(a.getMode().name, "markdown");
   1.268 +    a.swapDoc(old);
   1.269 +    eq(a.getOption("mode"), "text/javascript");
   1.270 +    eq(a.getMode().name, "javascript");
   1.271 +  });
   1.272 +
   1.273 +  testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) {
   1.274 +    eq(b.getValue(), "2\n3");
   1.275 +    eq(b.firstLine(), 1);
   1.276 +    b.setCursor(Pos(4));
   1.277 +    eqPos(b.getCursor(), Pos(2, 1));
   1.278 +    a.replaceRange("-1\n0\n", Pos(0, 0));
   1.279 +    eq(b.firstLine(), 3);
   1.280 +    eqPos(b.getCursor(), Pos(4, 1));
   1.281 +    a.undo();
   1.282 +    eqPos(b.getCursor(), Pos(2, 1));
   1.283 +    b.replaceRange("oyoy\n", Pos(2, 0));
   1.284 +    eq(a.getValue(), "1\n2\noyoy\n3\n4\n5");
   1.285 +    b.undo();
   1.286 +    eq(a.getValue(), "1\n2\n3\n4\n5");
   1.287 +  });
   1.288 +
   1.289 +  testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) {
   1.290 +    a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1));
   1.291 +    eq(b.firstLine(), 2);
   1.292 +    eq(b.lineCount(), 2);
   1.293 +    eq(b.getValue(), "z3\n44");
   1.294 +    a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1));
   1.295 +    eq(b.firstLine(), 2);
   1.296 +    eq(b.getValue(), "z3\n4q");
   1.297 +    eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5");
   1.298 +    a.execCommand("selectAll");
   1.299 +    a.replaceSelection("!");
   1.300 +    eqAll("!", a, b);
   1.301 +  });
   1.302 +
   1.303 +
   1.304 +  testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
   1.305 +    var mark = b.markText(Pos(0, 1), Pos(3, 1),
   1.306 +                          {className: "cm-searching", shared: true});
   1.307 +    var found = a.findMarksAt(Pos(0, 2));
   1.308 +    eq(found.length, 1);
   1.309 +    eq(found[0], mark);
   1.310 +    eq(c.findMarksAt(Pos(1, 1)).length, 1);
   1.311 +    eqPos(mark.find().from, Pos(0, 1));
   1.312 +    eqPos(mark.find().to, Pos(3, 1));
   1.313 +    b.replaceRange("x\ny\n", Pos(0, 0));
   1.314 +    eqPos(mark.find().from, Pos(2, 1));
   1.315 +    eqPos(mark.find().to, Pos(5, 1));
   1.316 +    var cleared = 0;
   1.317 +    CodeMirror.on(mark, "clear", function() {++cleared;});
   1.318 +    b.operation(function(){mark.clear();});
   1.319 +    eq(a.findMarksAt(Pos(3, 1)).length, 0);
   1.320 +    eq(b.findMarksAt(Pos(3, 1)).length, 0);
   1.321 +    eq(c.findMarksAt(Pos(3, 1)).length, 0);
   1.322 +    eq(mark.find(), null);
   1.323 +    eq(cleared, 1);
   1.324 +  });
   1.325 +
   1.326 +  testDoc("sharedBookmark", "A='ab\ncd\nef\ngh' B<A C<~A/1-2", function(a, b, c) {
   1.327 +    var mark = b.setBookmark(Pos(1, 1), {shared: true});
   1.328 +    var found = a.findMarksAt(Pos(1, 1));
   1.329 +    eq(found.length, 1);
   1.330 +    eq(found[0], mark);
   1.331 +    eq(c.findMarksAt(Pos(1, 1)).length, 1);
   1.332 +    eqPos(mark.find(), Pos(1, 1));
   1.333 +    b.replaceRange("x\ny\n", Pos(0, 0));
   1.334 +    eqPos(mark.find(), Pos(3, 1));
   1.335 +    var cleared = 0;
   1.336 +    CodeMirror.on(mark, "clear", function() {++cleared;});
   1.337 +    b.operation(function() {mark.clear();});
   1.338 +    eq(a.findMarks(Pos(0, 0), Pos(5)).length, 0);
   1.339 +    eq(b.findMarks(Pos(0, 0), Pos(5)).length, 0);
   1.340 +    eq(c.findMarks(Pos(0, 0), Pos(5)).length, 0);
   1.341 +    eq(mark.find(), null);
   1.342 +    eq(cleared, 1);
   1.343 +  });
   1.344 +
   1.345 +  testDoc("undoInSubview", "A='line 0\nline 1\nline 2\nline 3\nline 4' B<A/1-4", function(a, b) {
   1.346 +    b.replaceRange("x", Pos(2, 0));
   1.347 +    a.undo();
   1.348 +    eq(a.getValue(), "line 0\nline 1\nline 2\nline 3\nline 4");
   1.349 +    eq(b.getValue(), "line 1\nline 2\nline 3");
   1.350 +  });
   1.351 +})();

mercurial