Add First Test

This commit is contained in:
Josh Johnson 2018-01-30 16:45:10 -05:00
parent e1d41f6025
commit b9b6aec528
6 changed files with 88 additions and 29 deletions

View File

@ -25,7 +25,7 @@ export class V2XmlFormatter implements XmlFormatter {
output += `${this._getIndent(options, indentLevel)}<`; output += `${this._getIndent(options, indentLevel)}<`;
location = Location.CData; location = Location.CData;
} }
// exiting CData // exiting CData
else if (location === Location.CData && cc === "]" && nc === "]" && nnc === ">") { else if (location === Location.CData && cc === "]" && nc === "]" && nnc === ">") {
output += "]]>"; output += "]]>";
@ -34,13 +34,13 @@ export class V2XmlFormatter implements XmlFormatter {
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Text; location = Location.Text;
} }
// entering Comment // entering Comment
else if (location === Location.Text && cc === "<" && nc === "!" && nnc === "-") { else if (location === Location.Text && cc === "<" && nc === "!" && nnc === "-") {
output += `${this._getIndent(options, indentLevel)}<`; output += `${this._getIndent(options, indentLevel)}<`;
location = Location.Comment; location = Location.Comment;
} }
// exiting Comment // exiting Comment
else if (location === Location.Comment && cc === "-" && nc === "-" && nnc === ">") { else if (location === Location.Comment && cc === "-" && nc === "-" && nnc === ">") {
output += "-->"; output += "-->";
@ -49,20 +49,20 @@ export class V2XmlFormatter implements XmlFormatter {
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Text; location = Location.Text;
} }
// entering SpecialTag // entering SpecialTag
else if (location === Location.Text && cc === "<" && (nc === "!" || nc === "?")) { else if (location === Location.Text && cc === "<" && (nc === "!" || nc === "?")) {
output += `${this._getIndent(options, indentLevel)}<`; output += `${this._getIndent(options, indentLevel)}<`;
location = Location.SpecialTag; location = Location.SpecialTag;
} }
// exiting SpecialTag // exiting SpecialTag
else if (location === Location.SpecialTag && cc === ">") { else if (location === Location.SpecialTag && cc === ">") {
output += `>`; output += `>`;
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Text; location = Location.Text;
} }
// entering StartTag.StartTagName // entering StartTag.StartTagName
else if (location === Location.Text && cc === "<" && ["/", "!"].indexOf(nc) === -1) { else if (location === Location.Text && cc === "<" && ["/", "!"].indexOf(nc) === -1) {
// if this occurs after another tag, prepend a line break // if this occurs after another tag, prepend a line break
@ -77,17 +77,20 @@ export class V2XmlFormatter implements XmlFormatter {
indentLevel++; indentLevel++;
location = Location.StartTagName; location = Location.StartTagName;
} }
// exiting StartTag.StartTagName, enter StartTag // exiting StartTag.StartTagName, enter StartTag
else if (location === Location.StartTagName && cc === " ") { else if (location === Location.StartTagName && cc === " ") {
output += " "; output += " ";
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.StartTag; location = Location.StartTag;
} }
// entering StartTag.Attribute // entering StartTag.Attribute
else if (location === Location.StartTag && [" ", "/", ">"].indexOf(cc) === -1) { else if (location === Location.StartTag && [" ", "/", ">"].indexOf(cc) === -1) {
if (lastNonTextLocation === Location.AttributeValue && ((options.splitXmlnsOnFormat && xml.substr(i, 5).toLowerCase() === "xmlns") || options.splitAttributesOnFormat)) { if (lastNonTextLocation === Location.AttributeValue
&& ((options.splitXmlnsOnFormat
&& xml.substr(i, 5).toLowerCase() === "xmlns")
|| options.splitAttributesOnFormat)) {
output += `${options.newLine}${this._getIndent(options, indentLevel)}`; output += `${options.newLine}${this._getIndent(options, indentLevel)}`;
} }
@ -95,14 +98,14 @@ export class V2XmlFormatter implements XmlFormatter {
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Attribute; location = Location.Attribute;
} }
// entering StartTag.Attribute.AttributeValue // entering StartTag.Attribute.AttributeValue
else if (location === Location.Attribute && cc === "\"") { else if (location === Location.Attribute && cc === "\"") {
output += "\""; output += "\"";
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.AttributeValue; location = Location.AttributeValue;
} }
// exiting StartTag.Attribute.AttributeValue, entering StartTag // exiting StartTag.Attribute.AttributeValue, entering StartTag
else if (location === Location.AttributeValue && cc === "\"") { else if (location === Location.AttributeValue && cc === "\"") {
output += "\""; output += "\"";
@ -118,6 +121,21 @@ export class V2XmlFormatter implements XmlFormatter {
output += `>${options.newLine}`; output += `>${options.newLine}`;
} }
// if this is an open tag followed by a line break, add an indent before the text (after the line break)
// TODO: there could be multiple lines of text here, so we'll need a less naive implementation at some point
else if (nc === "\r" || nc === "\n") {
output += `>${options.newLine}${this._getIndent(options, indentLevel)}`;
// fast-forward based on what type of line break was used
if (nc === "\r") {
i += 2;
}
else {
i++;
}
}
else { else {
output += ">"; output += ">";
} }
@ -125,31 +143,36 @@ export class V2XmlFormatter implements XmlFormatter {
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Text; location = Location.Text;
} }
// entering EndTag // entering EndTag
else if (location === Location.Text && cc === "<" && nc === "/") { else if (location === Location.Text && cc === "<" && nc === "/") {
indentLevel--; indentLevel--;
// if the end tag immediately follows another end tag, add a line break and indent // if the end tag immediately follows another end tag, add a line break and indent
// if the end tag immediately follows a line break, just add an indentation
// otherwise, this should be treated as a same-line end tag(ex. <element>text</element>) // otherwise, this should be treated as a same-line end tag(ex. <element>text</element>)
if (lastNonTextLocation === Location.EndTag) { if (lastNonTextLocation === Location.EndTag) {
output += `${options.newLine}${this._getIndent(options, indentLevel)}<`; output += `${options.newLine}${this._getIndent(options, indentLevel)}<`;
} }
else if (pc === "\n") {
output += `${this._getIndent(options, indentLevel)}<`;
}
else { else {
output += "<"; output += "<";
} }
location = Location.EndTag; location = Location.EndTag;
} }
// exiting EndTag, entering Text // exiting EndTag, entering Text
else if (location === Location.EndTag && cc === ">") { else if (location === Location.EndTag && cc === ">") {
output += ">"; output += ">";
lastNonTextLocation = location; lastNonTextLocation = location;
location = Location.Text; location = Location.Text;
} }
// Text // Text
else { else {
output += cc; output += cc;

View File

@ -1,17 +1,42 @@
//
// Note: This example test is leveraging the Mocha test framework.
// Please refer to their documentation on https://mochajs.org/ for help.
//
// The module 'assert' provides assertion methods from node
import * as assert from "assert"; import * as assert from "assert";
import { FormattingOptions } from "vscode";
// You can import and use all API from the 'vscode' module import { TestDataLoader } from "./test-utils/test-data-loader";
// as well as import your extension to test it
import * as vscode from "vscode"; import { XmlFormatter } from "../formatting/xml-formatter";
import * as myExtension from "../extension"; import { XmlFormattingOptions } from "../formatting/xml-formatting-options";
import { V2XmlFormatter } from "../formatting/formatters/v2-xml-formatter";
describe("V2XmlFormatter", () => {
const xmlFormatter = new V2XmlFormatter();
describe("#formatXml(xml, options)", () => {
const options = {
editorOptions: {
insertSpaces: true,
tabSize: 4
},
newLine: "\r\n",
removeCommentsOnMinify: false,
splitAttributesOnFormat: false,
splitXmlnsOnFormat: true
};
it("should handle basic XML", () => {
testFormatter(xmlFormatter, options, "basic");
});
});
// Defines a Mocha test suite to group tests of similar kind together
suite("Extension Tests", () => {
// TODO: implement tests
}); });
function testFormatter(xmlFormatter: XmlFormatter, options: XmlFormattingOptions, fileLabel: string): void {
const expectedFormattedXml = TestDataLoader.load(`${fileLabel}.formatted.xml`);
const unformattedXml = TestDataLoader.load(`${fileLabel}.unformatted.xml`);
const actualFormattedXml = xmlFormatter.formatXml(unformattedXml, options);
assert.equal(actualFormattedXml, expectedFormattedXml, "Actual formatted XML does not match expected formatted XML.");
}

View File

@ -15,7 +15,7 @@ import * as testRunner from "vscode/lib/testrunner";
// You can directly control Mocha options by uncommenting the following lines // You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({ testRunner.configure({
ui: "tdd", // the TDD UI is being used in extension.test.ts (suite, test, etc.) ui: "bdd",
useColors: true // colored output from test results useColors: true // colored output from test results
}); });

View File

@ -0,0 +1,3 @@
<root>
<element>text</element>
</root>

View File

@ -0,0 +1 @@
<root><element>text</element></root>

View File

@ -0,0 +1,7 @@
import * as fs from "fs";
export class TestDataLoader {
static load(fileName: string): string {
return fs.readFileSync(`${__dirname}/../../../src/test/test-data/${fileName}`, "UTF-8");
}
}