Permalink
Browse files

[test driver] Different approach to indentation tests

All tests now check whether indentation from mode corresponds
to the indentation in the test source. test.indentation is
gone.
  • Loading branch information...
1 parent f943b02 commit d09247c69a051868fd966b5b8b19e91bc998dc8c @marijnh marijnh committed Dec 12, 2013
Showing with 95 additions and 111 deletions.
  1. +1 −1 mode/css/less_test.js
  2. +23 −17 mode/css/scss_test.js
  3. +34 −21 mode/css/test.js
  4. +0 −4 mode/haml/haml.js
  5. +1 −1 mode/haml/test.js
  6. +36 −67 test/mode_test.js
@@ -1,7 +1,7 @@
(function() {
"use strict";
- var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-less");
+ var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
MT("variable",
View
@@ -1,7 +1,6 @@
(function() {
- var mode = CodeMirror.getMode({indentUnit: 1}, "text/x-scss");
+ var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
- function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
MT('url_with_quotation',
"[tag foo] { [property background]:[atom url]([string test.jpg]) }");
@@ -79,23 +78,30 @@
MT('nested_structure_with_id_selector',
"[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
- IT('mixin',
- "[1 @mixin container ($a: 10, $b: 10, $c: 10) {]}");
+ MT('indent_mixin',
+ "[def @mixin] [tag container] (",
+ " [variable-2 $a]: [number 10],",
+ " [variable-2 $b]: [number 10])",
+ "{}");
- IT('nested',
- "foo [1 { bar ][2 { ][1 } ]}");
-
- IT('comma',
- "foo [1 { font-family][2 : verdana, sans-serif][1 ; ]}");
+ MT('indent_nested',
+ "[tag foo] {",
+ " [tag bar] {",
+ " }",
+ "}");
- IT('parentheses',
- "foo [1 { color][2 : darken][3 ($blue, 9%][2 )][1 ; ]}");
+ MT('indent_parentheses',
+ "[tag foo] {",
+ " [property color]: [variable darken]([variable-2 $blue],",
+ " [number 9%]);",
+ "}");
- IT('vardef',
- "$name[1 : 'val'];",
- "tag [1 {]",
- "[1 inner ][2 {]",
- "[2 margin][3 : 3px][2 ;]",
- "[2 ][1 }]",
+ MT('indent_vardef',
+ "[variable-2 $name]:",
+ " [string 'val'];",
+ "[tag tag] {",
+ " [tag inner] {",
+ " [property margin]: [number 3px];",
+ " }",
"}");
})();
View
@@ -1,7 +1,6 @@
(function() {
- var mode = CodeMirror.getMode({indentUnit: 1}, "css");
+ var mode = CodeMirror.getMode({indentUnit: 2}, "css");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
- function IT(name) { test.indentation(name, mode, Array.prototype.slice.call(arguments, 1)); }
// Error, because "foobarhello" is neither a known type or property, but
// property was expected (after "and"), and it should be in parenthese.
@@ -38,11 +37,11 @@
"[tag foo] { [property font-family]: [string 'hello world']; }");
MT("tagColorKeyword",
- "[tag foo] {" +
- "[property color]: [keyword black];" +
- "[property color]: [keyword navy];" +
- "[property color]: [keyword yellow];" +
- "}");
+ "[tag foo] {",
+ " [property color]: [keyword black];",
+ " [property color]: [keyword navy];",
+ " [property color]: [keyword yellow];",
+ "}");
MT("tagColorHex3",
"[tag foo] { [property background]: [atom #fff]; }");
@@ -81,18 +80,32 @@
"[comment <!--comment]",
"[comment -->] [tag div] {}");
- IT("tagSelector",
- "strong, em [1 { background][2 : rgba][3 (255, 255, 0, .2][2 )][1 ;]}");
-
- IT("atMedia",
- "[1 @media { foo ][2 { ][1 } ]}");
-
- IT("comma",
- "foo [1 { font-family][2 : verdana, sans-serif][1 ; ]}");
-
- IT("parentheses",
- "foo [1 { background][2 : url][3 (\"bar\"][2 )][1 ; ]}");
-
- IT("pseudo",
- "foo:before [1 { ]}");
+ MT("indent_tagSelector",
+ "[tag strong], [tag em] {",
+ " [property background]: [atom rgba](",
+ " [number 255], [number 255], [number 0], [number .2]",
+ " );",
+ "}");
+
+ MT("indent_atMedia",
+ "[def @media] {",
+ " [tag foo] {",
+ " [property color]:",
+ " [keyword yellow];",
+ " }",
+ "}");
+
+ MT("indent_comma",
+ "[tag foo] {",
+ " [property font-family]: [variable verdana],",
+ " [atom sans-serif];",
+ "}");
+
+ MT("indent_parentheses",
+ "[tag foo]:[variable-3 before] {",
+ " [property background]: [atom url](",
+ "[string blahblah]",
+ "[string etc]",
+ "[string ]) [keyword !important];",
+ "}");
})();
View
@@ -141,10 +141,6 @@
style = null;
}
return style;
- },
-
- indent: function(state) {
- return state.indented;
}
};
}, "htmlmixed", "ruby");
View
@@ -1,5 +1,5 @@
(function() {
- var mode = CodeMirror.getMode({tabSize: 4}, "haml");
+ var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
// Requires at least one media query
View
@@ -59,21 +59,18 @@
return {tokens: tokens, plain: plain};
}
- test.indentation = function(name, mode, tokens, modeName) {
- var data = parseTokens(tokens);
- return test((modeName || mode.name) + "_indent_" + name, function() {
- return compare(data.plain, data.tokens, mode, true);
- });
- };
-
test.mode = function(name, mode, tokens, modeName) {
var data = parseTokens(tokens);
return test((modeName || mode.name) + "_" + name, function() {
return compare(data.plain, data.tokens, mode);
});
};
- function compare(text, expected, mode, compareIndentation) {
+ function esc(str) {
+ return str.replace('&', '&amp;').replace('<', '&lt;');
+ }
+
+ function compare(text, expected, mode) {
var expectedOutput = [];
for (var i = 0; i < expected.length; i += 2) {
@@ -82,59 +79,48 @@
expectedOutput.push(sty, expected[i + 1]);
}
- var observedOutput = highlight(text, mode, compareIndentation);
+ var observedOutput = highlight(text, mode);
- var pass, passStyle = "";
- pass = highlightOutputsEqual(expectedOutput, observedOutput);
- passStyle = pass ? 'mt-pass' : 'mt-fail';
-
- var s = '';
- if (pass) {
- s += '<div class="mt-test ' + passStyle + '">';
- s += '<pre>' + text.replace('&', '&amp;').replace('<', '&lt;') + '</pre>';
- s += '<div class="cm-s-default">';
- s += prettyPrintOutputTable(observedOutput);
- s += '</div>';
- s += '</div>';
- return s;
- } else {
- s += '<div class="mt-test ' + passStyle + '">';
- s += '<pre>' + text.replace('&', '&amp;').replace('<', '&lt;') + '</pre>';
+ var s = "";
+ var diff = highlightOutputsDifferent(expectedOutput, observedOutput);
+ if (diff != null) {
+ s += '<div class="mt-test mt-fail">';
+ s += '<pre>' + esc(text) + '</pre>';
s += '<div class="cm-s-default">';
s += 'expected:';
- s += prettyPrintOutputTable(expectedOutput);
+ s += prettyPrintOutputTable(expectedOutput, diff);
s += 'observed:';
- s += prettyPrintOutputTable(observedOutput);
+ s += prettyPrintOutputTable(observedOutput, diff);
s += '</div>';
s += '</div>';
- throw s;
}
+ if (observedOutput.indentFailures) {
+ for (var i = 0; i < observedOutput.indentFailures.length; i++)
+ s += "<div class='mt-test mt-fail'>" + esc(observedOutput.indentFailures[i]) + "</div>";
+ }
+ if (s) throw new Failure(s);
}
- /**
- * Emulation of CodeMirror's internal highlight routine for testing. Multi-line
- * input is supported.
- *
- * @param string to highlight
- *
- * @param mode the mode that will do the actual highlighting
- *
- * @return array of [style, token] pairs
- */
- function highlight(string, mode, compareIndentation) {
+ function highlight(string, mode) {
var state = mode.startState()
var lines = string.replace(/\r\n/g,'\n').split('\n');
var st = [], pos = 0;
for (var i = 0; i < lines.length; ++i) {
var line = lines[i], newLine = true;
+ if (mode.indent) {
+ var ws = line.match(/^\s*/)[0];
+ var indent = mode.indent(state, line.slice(ws.length));
+ if (indent != CodeMirror.Pass && indent != ws.length)
+ (st.indentFailures || (st.indentFailures = [])).push(
+ "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")");
+ }
var stream = new CodeMirror.StringStream(line);
if (line == "" && mode.blankLine) mode.blankLine(state);
/* Start copied code from CodeMirror.highlight */
while (!stream.eol()) {
var compare = mode.token(stream, state), substr = stream.current();
- if (compareIndentation) compare = mode.indent(state) || null;
- else if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
+ if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' ');
stream.start = stream.pos;
if (pos && st[pos-2] == compare && !newLine) {
st[pos-1] += substr;
@@ -153,39 +139,22 @@
return st;
}
- /**
- * Compare two arrays of output from highlight.
- *
- * @param o1 array of [style, token] pairs
- *
- * @param o2 array of [style, token] pairs
- *
- * @return boolean; true iff outputs equal
- */
- function highlightOutputsEqual(o1, o2) {
- if (o1.length != o2.length) return false;
- for (var i = 0; i < o1.length; ++i)
- if (o1[i] != o2[i]) return false;
- return true;
+ function highlightOutputsDifferent(o1, o2) {
+ var minLen = Math.min(o1.length, o2.length);
+ for (var i = 0; i < minLen; ++i)
+ if (o1[i] != o2[i]) return i >> 1;
+ if (o1.length > minLen || o2.length > minLen) return minLen;
}
- /**
- * Print tokens and corresponding styles in a table. Spaces in the token are
- * replaced with 'interpunct' dots (&middot;).
- *
- * @param output array of [style, token] pairs
- *
- * @return html string
- */
- function prettyPrintOutputTable(output) {
+ function prettyPrintOutputTable(output, diffAt) {
var s = '<table class="mt-output">';
s += '<tr>';
for (var i = 0; i < output.length; i += 2) {
var style = output[i], val = output[i+1];
s +=
- '<td class="mt-token">' +
- '<span class="cm-' + String(style).replace(/ +/g, " cm-") + '">' +
- val.replace(/ /g,'\xb7').replace('&', '&amp;').replace('<', '&lt;') +
+ '<td class="mt-token"' + (i == diffAt * 2 ? " style='background: pink'" : "") + '>' +
+ '<span class="cm-' + esc(String(style)) + '">' +
+ esc(val.replace(/ /g,'\xb7')) +
'</span>' +
'</td>';
}

0 comments on commit d09247c

Please sign in to comment.