src/extensions/default/CSSAtRuleCodeHints/unittests.js
/*
* Copyright (c) 2017 - present Adobe Systems Incorporated. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
/*global describe, it, xit, expect, beforeEach, afterEach */
define(function (require, exports, module) {
"use strict";
var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"),
CSSAtRuleCodeHints = require("main");
describe("CSS '@' rules Code Hinting", function () {
var defaultContent = "@ { \n" +
"} \n" +
" \n" +
"@m ";
var testDocument, testEditor;
/*
* Create a mockup editor with the given content and language id.
*
* @param {string} content - content for test window
* @param {string} languageId
*/
function setupTest(content, languageId) {
var mock = SpecRunnerUtils.createMockEditor(content, languageId);
testDocument = mock.doc;
testEditor = mock.editor;
}
function tearDownTest() {
SpecRunnerUtils.destroyMockEditor(testDocument);
testEditor = null;
testDocument = null;
}
// Ask provider for hints at current cursor position; expect it to return some
function expectHints(provider, implicitChar, returnWholeObj) {
expect(provider.hasHints(testEditor, implicitChar)).toBe(true);
var hintsObj = provider.getHints();
expect(hintsObj).toBeTruthy();
// return just the array of hints if returnWholeObj is falsy
return returnWholeObj ? hintsObj : hintsObj.hints;
}
// Ask provider for hints at current cursor position; expect it NOT to return any
function expectNoHints(provider, implicitChar) {
expect(provider.hasHints(testEditor, implicitChar)).toBe(false);
}
// compares lists to ensure they are the same
function verifyListsAreIdentical(hintList, values) {
var i;
expect(hintList.length).toBe(values.length);
for (i = 0; i < values.length; i++) {
expect(hintList[i]).toBe(values[i]);
}
}
function selectHint(provider, expectedHint, implicitChar) {
var hintList = expectHints(provider, implicitChar);
expect(hintList.indexOf(expectedHint)).not.toBe(-1);
return provider.insertHint(expectedHint);
}
// Helper function for testing cursor position
function fixPos(pos) {
if (!("sticky" in pos)) {
pos.sticky = null;
}
return pos;
}
function expectCursorAt(pos) {
var selection = testEditor.getSelection();
expect(fixPos(selection.start)).toEqual(fixPos(selection.end));
expect(fixPos(selection.start)).toEqual(fixPos(pos));
}
function verifyFirstEntry(hintList, expectedFirstHint) {
expect(hintList[0]).toBe(expectedFirstHint);
}
// Helper function to
// a) ensure the hintList and the list with the available values have the same size
// b) ensure that all possible values are mentioned in the hintList
function verifyAllValues(hintList, values) {
expect(hintList.length).toBe(values.length);
expect(hintList.sort().toString()).toBe(values.sort().toString());
}
var modesToTest = ['css', 'scss', 'less'],
modeCounter;
var selectMode = function () {
return modesToTest[modeCounter];
};
describe("'@' rules in styles mode (selection of correct restricted block based on input)", function () {
beforeEach(function () {
// create Editor instance (containing a CodeMirror instance)
var mock = SpecRunnerUtils.createMockEditor(defaultContent, selectMode());
testEditor = mock.editor;
testDocument = mock.doc;
});
afterEach(function () {
SpecRunnerUtils.destroyMockEditor(testDocument);
testEditor = null;
testDocument = null;
});
var testAllHints = function () {
testEditor.setCursorPos({ line: 0, ch: 1 }); // after @
var hintList = expectHints(CSSAtRuleCodeHints.restrictedBlockHints);
verifyFirstEntry(hintList, "@charset"); // filtered on "empty string"
verifyListsAreIdentical(hintList, ["@charset",
"@counter-style",
"@font-face",
"@font-feature-values",
"@import",
"@keyframes",
"@media",
"@namespace",
"@page",
"@supports"]);
},
testFilteredHints = function () {
testEditor.setCursorPos({ line: 3, ch: 2 }); // after @m
var hintList = expectHints(CSSAtRuleCodeHints.restrictedBlockHints);
verifyFirstEntry(hintList, "@media"); // filtered on "@m"
verifyListsAreIdentical(hintList, ["@media"]);
},
testNoHintsOnSpace = function () {
testEditor.setCursorPos({ line: 3, ch: 3 }); // after {
expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, '')).toBe(false);
},
testNoHints = function () {
testEditor.setCursorPos({ line: 0, ch: 0 }); // after {
expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, 'c')).toBe(false);
};
for (modeCounter in modesToTest) {
it("should list all rule hints right after @", testAllHints);
it("should list filtered rule hints right after @m", testFilteredHints);
it("should not list rule hints on space", testNoHintsOnSpace);
it("should not list rule hints if the cursor is before @", testNoHints);
}
});
describe("'@' rules in LESS mode (selection of correct restricted block based on input)", function () {
defaultContent = "@ { \n" +
"} \n" +
" \n" +
"@m \n" +
"@green: green;\n" +
".div { \n" +
"color: @" +
"} \n";
beforeEach(function () {
// create Editor instance (containing a CodeMirror instance)
var mock = SpecRunnerUtils.createMockEditor(defaultContent, "less");
testEditor = mock.editor;
testDocument = mock.doc;
});
afterEach(function () {
SpecRunnerUtils.destroyMockEditor(testDocument);
testEditor = null;
testDocument = null;
});
it("should not list rule hints in less variable evaluation scope", function () {
testEditor.setCursorPos({ line: 3, ch: 3 }); // after {
expect(CSSAtRuleCodeHints.restrictedBlockHints.hasHints(testEditor, '')).toBe(false);
});
});
describe("'@' rule hint insertion", function () {
beforeEach(function () {
// create Editor instance (containing a CodeMirror instance)
var mock = SpecRunnerUtils.createMockEditor(defaultContent, "css");
testEditor = mock.editor;
testDocument = mock.doc;
});
afterEach(function () {
SpecRunnerUtils.destroyMockEditor(testDocument);
testEditor = null;
testDocument = null;
});
it("should insert @rule selected", function () {
testEditor.setCursorPos({ line: 0, ch: 1 }); // cursor after '@'
selectHint(CSSAtRuleCodeHints.restrictedBlockHints, "@charset");
expect(testDocument.getLine(0)).toBe("@charset { ");
expectCursorAt({ line: 0, ch: 8 });
});
it("should insert filtered selection by replacing the existing rule", function () {
testEditor.setCursorPos({ line: 3, ch: 2 }); // cursor after '@m'
selectHint(CSSAtRuleCodeHints.restrictedBlockHints, "@media");
expect(testDocument.getLine(3)).toBe("@media ");
expectCursorAt({ line: 3, ch: 6 });
});
});
});
});