/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/extensions/default/CSSCodeHints/unittests.js
867 строк
44 KB
Swagatam Mitra
Handle multiline attribute value and add UNIT test for element styles
12 апр 2017, 09:59
12 апр 2017, 09:59
375b730
Код
Авторство
О чём код?
/* * Copyright (c) 2013 - 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"), testContentCSS = require("text!unittest-files/regions.css"), testContentHTML = require("text!unittest-files/region-template.html"), CSSCodeHints = require("main"); describe("CSS Code Hinting", function () { var defaultContent = "@media screen { \n" + " body { \n" + " }\n" + "} \n" + ".selector { \n" + " \n" + " b\n" + " bord\n" + " border-\n" + " border-colo\n" + " border-color: red;\n" + // line: 10 " d\n" + " disp\n" + " display: \n" + " display: in\n" + " bordborder: \n" + " color\n" + "} \n"; var defaultHTMLContent = "<html> \n" + "<head> \n" + "</head> \n" + "<body> \n" + "<div style=' \n" + // line 4 " \n" + " b\n" + " bord\n" + " border-\n" + " border-colo\n" + " border-color: red;'>\n" + // line 10 "</div> \n" + "</body> \n" + "</html> \n"; 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; } function extractHintList(hints) { return $.map(hints, function ($node) { return $node.text(); }); } // 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 : extractHintList(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); } function verifyAttrHints(hintList, expectedFirstHint) { expect(hintList.indexOf("div")).toBe(-1); expect(hintList[0]).toBe(expectedFirstHint); } // 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)); } // 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()); } describe("CSS properties in general (selection of correct property based on input)", 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 list all prop-name hints right after curly bracket", function () { testEditor.setCursorPos({ line: 4, ch: 11 }); // after { var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should list all prop-name hints in new line", function () { testEditor.setCursorPos({ line: 5, ch: 1 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should list all prop-name hints starting with 'b' in new line", function () { testEditor.setCursorPos({ line: 6, ch: 2 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "backface-visibility"); // filtered on "b" }); it("should list all prop-name hints starting with 'bord' ", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 6, ch: 2 }); testEditor.setCursorPos({ line: 7, ch: 5 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border"); // filtered on "bord" }); it("should list all prop-name hints starting with 'border-' ", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 7, ch: 5 }); testEditor.setCursorPos({ line: 8, ch: 8 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border-bottom"); // filtered on "border-" }); it("should list only prop-name hint border-color", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 8, ch: 8 }); testEditor.setCursorPos({ line: 9, ch: 12 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border-color"); // filtered on "border-color" verifyListsAreIdentical(hintList, ["border-color", "border-left-color", "border-top-color", "border-bottom-color", "border-right-color"]); }); it("should list prop-name hints at end of property-value finished by ;", function () { testEditor.setCursorPos({ line: 10, ch: 19 }); // after ; var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should NOT list prop-name hints right before curly bracket", function () { testEditor.setCursorPos({ line: 4, ch: 10 }); // inside .selector, before { expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list prop-name hints after declaration of mediatype", function () { testEditor.setCursorPos({ line: 0, ch: 15 }); // after { expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list prop-name hints if previous property is not closed properly", function () { testEditor.setCursorPos({ line: 16, ch: 6 }); // cursor directly after color expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list prop-name hints in media type declaration", function () { testEditor.setCursorPos({ line: 0, ch: 1 }); expect(CSSCodeHints.cssPropHintProvider.hasHints(testEditor, 'm')).toBe(false); }); }); describe("CSS property 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 colon prop-name selected", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 6, ch: 2 }); testEditor.setCursorPos({ line: 7, ch: 5 }); // cursor after 'bord' selectHint(CSSCodeHints.cssPropHintProvider, "border"); expect(testDocument.getLine(7)).toBe(" border: "); expectCursorAt({ line: 7, ch: 9 }); }); it("should not insert semicolon after prop-value selected", function () { testDocument.replaceRange(";", { line: 12, ch: 5 }); testEditor.setCursorPos({ line: 13, ch: 10 }); // cursor after 'display: ' selectHint(CSSCodeHints.cssPropHintProvider, "block"); expect(testDocument.getLine(13)).toBe(" display: block"); }); it("should insert prop-name directly after semicolon", function () { testEditor.setCursorPos({ line: 10, ch: 19 }); // cursor after red; selectHint(CSSCodeHints.cssPropHintProvider, "align-content"); expect(testDocument.getLine(10)).toBe(" border-color: red;align-content: "); }); it("should insert nothing but the closure(semicolon) if prop-value is fully written", function () { testDocument.replaceRange(";", { line: 15, ch: 13 }); // insert text ; testEditor.setCursorPos({ line: 16, ch: 6 }); // cursor directly after color selectHint(CSSCodeHints.cssPropHintProvider, "color"); expect(testDocument.getLine(16)).toBe(" color: "); expectCursorAt({ line: 16, ch: 8 }); }); it("should insert prop-name before an existing one", function () { testEditor.setCursorPos({ line: 10, ch: 1 }); // cursor before border-color: selectHint(CSSCodeHints.cssPropHintProvider, "float"); expect(testDocument.getLine(10)).toBe(" float: border-color: red;"); expectCursorAt({ line: 10, ch: 8 }); }); it("should insert prop-name before an existing one when invoked with an implicit character", function () { testDocument.replaceRange("f", { line: 10, ch: 1 }); // insert "f" before border-color: testEditor.setCursorPos({ line: 10, ch: 2 }); // set cursor before border-color: selectHint(CSSCodeHints.cssPropHintProvider, "float", "f"); expect(testDocument.getLine(10)).toBe(" float: border-color: red;"); expectCursorAt({ line: 10, ch: 8 }); }); it("should replace the existing prop-value with the new selection", function () { testDocument.replaceRange(";", { line: 12, ch: 5 }); testDocument.replaceRange("block", { line: 13, ch: 10 }); testEditor.setCursorPos({ line: 13, ch: 10 }); // cursor before block selectHint(CSSCodeHints.cssPropHintProvider, "none"); expect(testDocument.getLine(13)).toBe(" display: none"); expectCursorAt({ line: 13, ch: 14 }); }); xit("should start new hinting whenever there is a whitespace last stringliteral", function () { // topic: multi-value properties // this needs to be discussed, whether or not this behaviour is aimed for // if so, changes to CSSUtils.getInfoAt need to be done imho to classify this testDocument.replaceRange(" ", { line: 16, ch: 6 }); // insert whitespace after color testEditor.setCursorPos({ line: 16, ch: 7 }); // cursor one whitespace after color selectHint(CSSCodeHints.cssPropHintProvider, "color"); expect(testDocument.getLine(16)).toBe(" color color:"); expectCursorAt({ line: 16, ch: 13 }); }); }); describe("CSS prop-value hints", 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 list all prop-values for 'display' after colon", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 12, ch: 5 }); testEditor.setCursorPos({ line: 13, ch: 9 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "block"); // filtered after "display:" }); it("should list all prop-values for 'display' after colon and whitespace", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 12, ch: 5 }); testEditor.setCursorPos({ line: 13, ch: 10 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "block"); // filtered after "display: " }); it("should list all prop-values starting with 'in' for 'display' after colon and whitespace", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 13, ch: 10 }); testEditor.setCursorPos({ line: 14, ch: 12 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "inherit"); // filtered after "display: in" }); it("should NOT list prop-value hints for unknown prop-name", function () { testEditor.setCursorPos({ line: 15, ch: 12 }); // at bordborder: expectNoHints(CSSCodeHints.cssPropHintProvider); }); }); describe("CSS hint provider inside mixed htmlfiles", function () { var defaultContent = "<html> \n" + "<head><style>.selector{display: none;}</style></head> \n" + "<body> <style> \n" + " body { \n" + " background-color: red; \n" + " \n" + "} \n" + "</style>\n" + "<div class='selector'></div>\n" + "<style> .foobar { \n" + " colo </style>\n" + "</body></html>"; beforeEach(function () { // create dummy Document for the Editor var mock = SpecRunnerUtils.createMockEditor(defaultContent, "html"); testEditor = mock.editor; testDocument = mock.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(testDocument); testEditor = null; testDocument = null; }); it("should list prop-name hints right after curly bracket", function () { testEditor.setCursorPos({ line: 3, ch: 7 }); // inside body-selector, after { expectHints(CSSCodeHints.cssPropHintProvider); }); it("should list prop-name hints inside single-line styletags at start", function () { testEditor.setCursorPos({ line: 1, ch: 23 }); // inside style, after { expectHints(CSSCodeHints.cssPropHintProvider); }); it("should list prop-name hints inside single-line styletags after semicolon", function () { testEditor.setCursorPos({ line: 1, ch: 37 }); // inside style, after ; expectHints(CSSCodeHints.cssPropHintProvider); }); it("should list prop-name hints inside multi-line styletags with cursor in first line", function () { testEditor.setCursorPos({ line: 9, ch: 18 }); // inside style, after { expectHints(CSSCodeHints.cssPropHintProvider); }); it("should list prop-name hints inside multi-line styletags with cursor in last line", function () { testEditor.setCursorPos({ line: 10, ch: 5 }); // inside style, after colo var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyListsAreIdentical(hintList, ["color", "border-color", "background-color", "border-left-color", "border-top-color", "outline-color", "border-bottom-color", "border-right-color", "text-decoration-color", "text-emphasis-color", "column-count", "column-rule-color", "background-blend-mode"]); }); it("should NOT list prop-name hints between closed styletag and new opening styletag", function () { testEditor.setCursorPos({ line: 8, ch: 0 }); // right before <div expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list hints right before curly bracket", function () { testEditor.setCursorPos({ line: 3, ch: 6 }); // inside body-selector, before { expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list hints inside head-tag", function () { testEditor.setCursorPos({ line: 1, ch: 6 }); // between <head> and </head> { expectNoHints(CSSCodeHints.cssPropHintProvider); }); }); describe("CSS Hint provider in style attribute value context for html mode", function () { beforeEach(function () { // create Editor instance (containing a CodeMirror instance) var mock = SpecRunnerUtils.createMockEditor(defaultHTMLContent, "html"); testEditor = mock.editor; testDocument = mock.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(testDocument); testEditor = null; testDocument = null; }); it("should list all prop-name hints right after the open quote for style value context", function () { testEditor.setCursorPos({ line: 4, ch: 12 }); // after "='" var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should list all prop-name hints in new line for style value context", function () { testEditor.setCursorPos({ line: 5, ch: 0 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should list all prop-name hints starting with 'b' in new line for style value context", function () { testEditor.setCursorPos({ line: 6, ch: 2 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "backface-visibility"); // filtered on "b" }); it("should list all prop-name hints starting with 'bord' for style value context", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 6, ch: 2 }); testEditor.setCursorPos({ line: 7, ch: 5 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border"); // filtered on "bord" }); it("should list all prop-name hints starting with 'border-' for style value context", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 7, ch: 5 }); testEditor.setCursorPos({ line: 8, ch: 8 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border-bottom"); // filtered on "border-" }); it("should list only prop-name hint border-color for style value context", function () { // insert semicolon after previous rule to avoid incorrect tokenizing testDocument.replaceRange(";", { line: 8, ch: 8 }); testEditor.setCursorPos({ line: 9, ch: 12 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border-color"); // filtered on "border-color" verifyListsAreIdentical(hintList, ["border-color", "border-left-color", "border-top-color", "border-bottom-color", "border-right-color"]); }); it("should list prop-name hints at end of property-value finished by ; for style value context", function () { testEditor.setCursorPos({ line: 10, ch: 19 }); // after ; var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "align-content"); // filtered on "empty string" }); it("should NOT list prop-name hints right before style value context", function () { testEditor.setCursorPos({ line: 4, ch: 11 }); // after = expectNoHints(CSSCodeHints.cssPropHintProvider); }); it("should NOT list prop-name hints after style value context", function () { testEditor.setCursorPos({ line: 10, ch: 20 }); // after "'" expectNoHints(CSSCodeHints.cssPropHintProvider); }); }); describe("CSS hint provider in other filecontext (e.g. javascript)", function () { var defaultContent = "function foobar (args) { \n " + " /* do sth */ \n" + " return 1; \n" + "} \n"; beforeEach(function () { // create dummy Document for the Editor var mock = SpecRunnerUtils.createMockEditor(defaultContent, "javascript"); testEditor = mock.editor; testDocument = mock.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(testDocument); testEditor = null; testDocument = null; }); it("should NOT list hints after function declaration", function () { testEditor.setCursorPos({ line: 0, ch: 24 }); // after { after function declaration expectNoHints(CSSCodeHints.cssPropHintProvider); }); }); describe("CSS hint provider cursor placement inside value functions", function () { var defaultContent = ".selector { \n" + // line 0 "shape-inside:\n" + // line 1 "}\n"; // line 2 beforeEach(function () { // create dummy Document for the Editor var mock = SpecRunnerUtils.createMockEditor(defaultContent, "css"); testEditor = mock.editor; testDocument = mock.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(testDocument); testEditor = null; testDocument = null; }); it("should should place the cursor between the parens of the value function", function () { var expectedString = "shape-inside:polygon()"; testEditor.setCursorPos({ line: 1, ch: 15 }); // after shape-inside expectHints(CSSCodeHints.cssPropHintProvider); selectHint(CSSCodeHints.cssPropHintProvider, "polygon()"); expect(testDocument.getLine(1).length).toBe(expectedString.length); expect(testDocument.getLine(1)).toBe(expectedString); expectCursorAt({ line: 1, ch: expectedString.length - 1 }); }); }); describe("CSS hint provider for regions and exclusions", function () { var defaultContent = ".selector { \n" + // line 0 " shape-inside: \n;" + // line 1 " shape-outside: \n;" + // line 2 " region-fragment: \n;" + // line 3 " region-break-after: \n;" + // line 4 " region-break-inside: \n;" + // line 5 " region-break-before: \n;" + // line 6 " -ms-region\n;" + // line 7 " -webkit-region\n;" + // line 8 " flow-from: \n;" + // line 9 " flow-into: \n;" + // line 10 "}\n"; // line 11 beforeEach(function () { // create dummy Document for the Editor var mock = SpecRunnerUtils.createMockEditor(defaultContent, "css"); testEditor = mock.editor; testDocument = mock.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(testDocument); testEditor = null; testDocument = null; }); it("should list 7 value-name hints for shape-inside", function () { testEditor.setCursorPos({ line: 1, ch: 15 }); // after shape-inside var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "auto"); // first hint should be auto verifyAllValues(hintList, ["auto", "circle()", "ellipse()", "inherit", "outside-shape", "polygon()", "rectangle()"]); }); it("should list 16 value-name hints for shape-outside", function () { testEditor.setCursorPos({ line: 2, ch: 16 }); // after shape-outside var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "border-box"); // first hint should be border-box verifyAllValues(hintList, ["none", "inherit", "circle()", "ellipse()", "polygon()", "inset()", "margin-box", "border-box", "padding-box", "content-box", "url()", "image()", "linear-gradient()", "radial-gradient()", "repeating-linear-gradient()", "repeating-radial-gradient()"]); }); it("should list 2 value-name hints for region-fragment", function () { testEditor.setCursorPos({ line: 3, ch: 18 }); // after region-fragment var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "auto"); // first hint should be auto verifyAllValues(hintList, ["auto", "break"]); }); it("should list 11 value-name hints for region-break-after", function () { testEditor.setCursorPos({ line: 4, ch: 21 }); // after region-break-after var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "always"); // first hint should be always verifyAllValues(hintList, ["always", "auto", "avoid", "avoid-column", "avoid-page", "avoid-region", "column", "left", "page", "region", "right"]); }); it("should list 5 value-name hints for region-break-inside", function () { testEditor.setCursorPos({ line: 5, ch: 22 }); // after region-break-inside var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "auto"); // first hint should be auto verifyAllValues(hintList, ["auto", "avoid", "avoid-column", "avoid-page", "avoid-region"]); }); it("should list 11 value-name hints for region-break-before", function () { testEditor.setCursorPos({ line: 6, ch: 23 }); // after region-break-before var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "always"); // first hint should be always verifyAllValues(hintList, ["always", "auto", "avoid", "avoid-column", "avoid-page", "avoid-region", "column", "left", "page", "region", "right"]); }); // TODO: Need to add vendor prefixed properties for CSS code hint provider. xit("should list 4 value-name hints for vendor prefixed region-* properties", function () { testEditor.setCursorPos({ line: 7, ch: 16 }); // after -ms-region var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "region-break-after"); // first hint should be region-break-after verifyAllValues(hintList, ["region-break-after", "region-break-before", "region-break-inside", "region-fragment"]); testEditor.setCursorPos({ line: 8, ch: 20 }); // after -webkit-region hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "region-break-after"); // first hint should be region-break-after verifyAllValues(hintList, ["region-break-after", "region-break-before", "region-break-inside", "region-fragment"]); }); it("should list 2 value-name hints for flow-from", function () { testEditor.setCursorPos({ line: 9, ch: 12 }); // after flow-from var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "inherit"); // first hint should be inherit verifyAllValues(hintList, ["inherit", "none"]); }); it("should list 1 value-name hint for flow-into", function () { testEditor.setCursorPos({ line: 10, ch: 12 }); // after flow-into var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "none"); // first hint should be none verifyAllValues(hintList, ["none"]); }); }); describe("Named flow hints for flow-into and flow-from properties in a CSS file", function () { beforeEach(function () { setupTest(testContentCSS, "css"); }); afterEach(function () { tearDownTest(); }); it("should list more than 2 value hints for flow-from", function () { testEditor.setCursorPos({ line: 66, ch: 15 }); // after flow-from var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "edge-code_now_shipping"); // first hint should be edge-code_now_shipping verifyAllValues(hintList, ["edge-code_now_shipping", "inherit", "jeff", "lim", "main", "none", "randy"]); }); it("should list more than 1 value hint for flow-into", function () { testEditor.setCursorPos({ line: 77, ch: 4 }); selectHint(CSSCodeHints.cssPropHintProvider, "flow-into"); expect(testDocument.getLine(77)).toBe(" flow-into: "); expectCursorAt({ line: 77, ch: 15 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "edge-code_now_shipping"); // first hint should be edge-code_now_shipping verifyAllValues(hintList, ["edge-code_now_shipping", "jeff", "lim", "main", "none", "randy"]); }); it("should NOT include partially entered named flow value in hint list", function () { // Insert a letter for a new named flow after flow-from: on line 66 testDocument.replaceRange("m", { line: 66, ch: 15 }); testEditor.setCursorPos({ line: 66, ch: 16 }); // after flow-from: m var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyListsAreIdentical(hintList, ["main", "lim"]); }); }); describe("Named flow hints inside a style block of an HTML", function () { beforeEach(function () { setupTest(testContentHTML, "html"); }); afterEach(function () { tearDownTest(); }); it("should include only 2 named flows available in the style block for flow-from", function () { testEditor.setCursorPos({ line: 28, ch: 21 }); // after flow-from var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "article"); // first hint should be article verifyAllValues(hintList, ["article", "inherit", "none", "regionC"]); }); it("should include only 2 named flows available in the style block for flow-into", function () { testEditor.setCursorPos({ line: 34, ch: 21 }); var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "article"); // first hint should be article verifyAllValues(hintList, ["article", "none", "regionC"]); }); it("should NOT include partially entered named flow value in hint list", function () { // Insert a letter for a new named flow after flow-from: on line 28 testDocument.replaceRange("m", { line: 28, ch: 21 }); testEditor.setCursorPos({ line: 28, ch: 22 }); // after flow-from: m var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAllValues(hintList, []); }); it("should NOT show named flow available inisde HTML text", function () { // Insert a letter for a new named flow after flow-from: on line 28 testDocument.replaceRange("some", { line: 28, ch: 21 }); testEditor.setCursorPos({ line: 28, ch: 25 }); // after flow-from: some var hintList = expectHints(CSSCodeHints.cssPropHintProvider); // some-named-flow should not be in the hint list since it is inside HTML text verifyAllValues(hintList, []); }); }); describe("Color names and swatches in a CSS file", function () { beforeEach(function () { setupTest(testContentCSS, "css"); }); afterEach(function () { tearDownTest(); }); it("should list color names for color", function () { testEditor.setCursorPos({ line: 98, ch: 11 }); // after color var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "aliceblue"); // first hint should be aliceblue }); it("should show color swatches for background-color", function () { testEditor.setCursorPos({ line: 99, ch: 22 }); // after background-color var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints; expect(hints[0].text()).toBe("aliceblue"); // first hint should be aliceblue expect(hints[0].find(".color-swatch").length).toBe(1); // CEF 2623 will output "aliceblue" whereas earlier versions give "rgb(240, 248, 255)", // so we need this ugly hack to make sure this test passes on both expect(hints[0].find(".color-swatch").css("backgroundColor")).toMatch(/^rgb\(240, 248, 255\)$|aliceblue/); }); it("should filter out color names appropriately", function () { testEditor.setCursorPos({ line: 100, ch: 27 }); // after border-left-color var hintList = expectHints(CSSCodeHints.cssPropHintProvider); verifyAttrHints(hintList, "deeppink"); // first hint should be deeppink verifyAllValues(hintList, ["deeppink", "deepskyblue"]); }); it("should always include transparent and currentColor and they should not have a swatch, but class no-swatch-margin", function () { testEditor.setCursorPos({ line: 101, ch: 22 }); // after border-color var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints, hintList = extractHintList(hints); verifyAttrHints(hintList, "currentColor"); // first hint should be currentColor verifyAllValues(hintList, ["currentColor", "darkmagenta", "transparent"]); expect(hints[0].find(".color-swatch").length).toBe(0); // no swatch for currentColor expect(hints[2].find(".color-swatch").length).toBe(0); // no swatch for transparent expect(hints[0].hasClass("no-swatch-margin")).toBeTruthy(); // no-swatch-margin applied to currentColor expect(hints[2].hasClass("no-swatch-margin")).toBeTruthy(); // no-swatch-margin applied to transparent }); it("should remove class no-swatch-margin from transparent if it's the only one in the list", function () { testEditor.setCursorPos({ line: 103, ch: 22 }); // after color var hints = expectHints(CSSCodeHints.cssPropHintProvider, undefined, true).hints, hintList = extractHintList(hints); verifyAllValues(hintList, ["transparent"]); expect(hints[0].find(".color-swatch").length).toBe(0); // no swatch for transparent expect(hints[0].hasClass("no-swatch-margin")).toBeFalsy(); // no-swatch-margin not applied to transparent }); it("should insert color names correctly", function () { var expectedString = " border-left-color: deeppink;", line = 100; testEditor.setCursorPos({ line: line, ch: 27 }); // after border-left-color expectHints(CSSCodeHints.cssPropHintProvider); selectHint(CSSCodeHints.cssPropHintProvider, "deeppink"); expect(testDocument.getLine(line).length).toBe(expectedString.length); expect(testDocument.getLine(line)).toBe(expectedString); expectCursorAt({ line: line, ch: expectedString.length - 1 }); }); it("should not display color names for unrelated properties", function () { testEditor.setCursorPos({ line: 102, ch: 12 }); // after height var hintList = expectHints(CSSCodeHints.cssPropHintProvider); expect(hintList.indexOf("aliceblue")).toBe(-1); }); }); describe("Should not invoke CSS hints on space key", function () { beforeEach(function () { setupTest(testContentHTML, "html"); }); afterEach(function () { tearDownTest(); }); it("should not trigger CSS property name hints with space key", function () { testEditor.setCursorPos({ line: 25, ch: 11 }); // after { expectNoHints(CSSCodeHints.cssPropHintProvider, " "); }); it("should not trigger CSS property value hints with space key", function () { testEditor.setCursorPos({ line: 28, ch: 21 }); // after flow-from expectNoHints(CSSCodeHints.cssPropHintProvider, " "); }); }); }); });