// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
goog.provide('goog.format.HtmlPrettyPrinterTest');
goog.setTestOnly('goog.format.HtmlPrettyPrinterTest');
goog.require('goog.format.HtmlPrettyPrinter');
goog.require('goog.testing.MockClock');
goog.require('goog.testing.jsunit');
var COMPLEX_HTML = ']>' +
'
My HTML' +
'' +
'My Header
My text.
My bold text.
' +
'My\npreformatted
HTML.
5 < 10' +
'';
var mockClock;
var mockClockTicks;
function setUp() {
mockClockTicks = 0;
mockClock = new goog.testing.MockClock();
mockClock.getCurrentTime = function() { return mockClockTicks++; };
mockClock.install();
}
function tearDown() {
if (mockClock) {
mockClock.uninstall();
}
}
function testSimpleHtml() {
var actual = goog.format.HtmlPrettyPrinter.format('
bold');
assertEquals('
\nbold\n', actual);
assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
}
function testSimpleHtmlMixedCase() {
var actual = goog.format.HtmlPrettyPrinter.format('
bold');
assertEquals('
\nbold\n', actual);
assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
}
function testComplexHtml() {
var actual = goog.format.HtmlPrettyPrinter.format(COMPLEX_HTML);
var expected = ']>\n' +
'\n' +
'\n' +
'My HTML\n' +
'' +
'\n' +
'\n' +
'\n' +
'My Header
\n' +
'My text.
\n' +
'My bold text.\n' +
'
\n' +
'My\npreformatted
HTML.
\n' +
'5 < 10' +
'\n' +
'\n';
assertEquals(expected, actual);
assertEquals(actual, goog.format.HtmlPrettyPrinter.format(actual));
}
function testTimeout() {
var pp = new goog.format.HtmlPrettyPrinter(3);
var actual = pp.format(COMPLEX_HTML);
var expected = ']>\n' +
'\n' +
'My HTML' +
'' +
'My Header
My text.
My bold text.
' +
'My\npreformatted
HTML.
5 < 10' +
'\n';
assertEquals(expected, actual);
}
function testKeepLeadingIndent() {
var original = ' Bold Ital ';
var expected = ' Bold Ital\n';
assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
}
function testTrimLeadingLineBreaks() {
var original = '\n \t\r\n \n Bold Ital ';
var expected = ' Bold Ital\n';
assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
}
function testExtraLines() {
var original = '
\ntombrat';
assertEquals(original + '\n', goog.format.HtmlPrettyPrinter.format(original));
}
function testCrlf() {
var original = '
\r\none\r\ntwo
';
assertEquals(original + '\n', goog.format.HtmlPrettyPrinter.format(original));
}
function testEndInLineBreak() {
assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo'));
assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo\n'));
assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo\n\n'));
assertEquals('foo
\n', goog.format.HtmlPrettyPrinter.format('foo
'));
assertEquals('foo
\n', goog.format.HtmlPrettyPrinter.format('foo
\n'));
}
function testTable() {
var original = '' +
'one.one | one.two |
' +
'two.one | two.two |
' +
'
';
var expected = '\n' +
'\none.one | \none.two | \n
\n' +
'\ntwo.one | \ntwo.two | \n
\n' +
'
\n';
assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
}
/**
* We have a sanity check in HtmlPrettyPrinter to make sure the regex index
* advances after every match. We should never hit this, but we include it on
* the chance there is some corner case where the pattern would match but not
* process a new token. It's not generally a good idea to break the
* implementation to test behavior, but this is the easiest way to mimic a
* bad internal state.
*/
function testRegexMakesProgress() {
var original = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
try {
// This regex matches \B, an index between 2 word characters, so the regex
// index does not advance when matching this.
goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
/(?:\B|||<(\/?)(\w+)[^>]*>|[^<]+|<)/g;
// It would work on this string.
assertEquals('f o o\n', goog.format.HtmlPrettyPrinter.format('f o o'));
// But not this one.
var ex = assertThrows(
'should have failed for invalid regex - endless loop',
goog.partial(goog.format.HtmlPrettyPrinter.format, COMPLEX_HTML));
assertEquals(
'Regex failed to make progress through source html.', ex.message);
} finally {
goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ = original;
}
}
/**
* FF3.0 doesn't like \n between
and
.
* See b/1520665.
*/
function testLists() {
var original = '';
var expected =
'\n';
assertEquals(expected, goog.format.HtmlPrettyPrinter.format(original));
}
/**
* We have a sanity check in HtmlPrettyPrinter to make sure the regex fully
* tokenizes the string. We should never hit this, but we include it on the
* chance there is some corner case where the pattern would miss a section of
* original string. It's not generally a good idea to break the
* implementation to test behavior, but this is the easiest way to mimic a
* bad internal state.
*/
function testAvoidDataLoss() {
var original = goog.format.HtmlPrettyPrinter.TOKEN_REGEX_;
try {
// This regex does not match stranded '<' characters, so does not fully
// tokenize the string.
goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ =
/(?:||<(\/?)(\w+)[^>]*>|[^<]+)/g;
// It would work on this string.
assertEquals('foo\n', goog.format.HtmlPrettyPrinter.format('foo'));
// But not this one.
var ex = assertThrows(
'should have failed for invalid regex - data loss',
goog.partial(goog.format.HtmlPrettyPrinter.format, COMPLEX_HTML));
assertEquals('Lost data pretty printing html.', ex.message);
} finally {
goog.format.HtmlPrettyPrinter.TOKEN_REGEX_ = original;
}
}