324 lines
12 KiB
JavaScript
324 lines
12 KiB
JavaScript
// 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.cssomTest');
|
|
goog.setTestOnly('goog.cssomTest');
|
|
|
|
goog.require('goog.array');
|
|
goog.require('goog.cssom');
|
|
goog.require('goog.cssom.CssRuleType');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.userAgent');
|
|
|
|
// Since sheet cssom_test1.css's first line is to import
|
|
// cssom_test2.css, we should get 2 before one in the string.
|
|
var cssText = '.css-link-1 { display: block; } ' +
|
|
'.css-import-2 { display: block; } ' +
|
|
'.css-import-1 { display: block; } ' +
|
|
'.css-style-1 { display: block; } ' +
|
|
'.css-style-2 { display: block; } ' +
|
|
'.css-style-3 { display: block; }';
|
|
|
|
var replacementCssText = '.css-repl-1 { display: block; }';
|
|
|
|
var isIe7 = goog.userAgent.IE &&
|
|
(goog.userAgent.compare(goog.userAgent.VERSION, '7.0') == 0);
|
|
|
|
// We're going to toLowerCase cssText before testing, because IE returns
|
|
// CSS property names in UPPERCASE, and the function shouldn't
|
|
// "fix" the text as it would be expensive and rarely of use.
|
|
// Same goes for the trailing whitespace in IE.
|
|
// Same goes for fixing the optimized removal of trailing ; in rules.
|
|
// Also needed for Opera.
|
|
function fixCssTextForIe(cssText) {
|
|
cssText = cssText.toLowerCase().replace(/\s*$/, '');
|
|
if (cssText.match(/[^;] \}/)) {
|
|
cssText = cssText.replace(/([^;]) \}/g, '$1; }');
|
|
}
|
|
return cssText;
|
|
}
|
|
|
|
function testGetFileNameFromStyleSheet() {
|
|
var styleSheet = {'href': 'http://foo.com/something/filename.css'};
|
|
assertEquals('filename.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
|
|
|
styleSheet = {'href': 'https://foo.com:123/something/filename.css'};
|
|
assertEquals('filename.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
|
|
|
styleSheet = {'href': 'http://foo.com/something/filename.css?bar=bas'};
|
|
assertEquals('filename.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
|
|
|
styleSheet = {'href': 'filename.css?bar=bas'};
|
|
assertEquals('filename.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
|
|
|
styleSheet = {'href': 'filename.css'};
|
|
assertEquals('filename.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheet));
|
|
}
|
|
|
|
function testGetAllCssStyleSheets() {
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
assertEquals(4, styleSheets.length);
|
|
// Makes sure they're in the right cascade order.
|
|
assertEquals('cssom_test_link_1.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheets[0]));
|
|
assertEquals('cssom_test_import_2.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheets[1]));
|
|
assertEquals('cssom_test_import_1.css',
|
|
goog.cssom.getFileNameFromStyleSheet(styleSheets[2]));
|
|
// Not an external styleSheet
|
|
assertNull(goog.cssom.getFileNameFromStyleSheet(styleSheets[3]));
|
|
}
|
|
|
|
function testGetAllCssText() {
|
|
var allCssText = goog.cssom.getAllCssText();
|
|
// In IE7, a CSSRule object gets included twice and replaces another
|
|
// existing CSSRule object. We aren't using
|
|
// goog.testing.ExpectedFailures since it brings in additional CSS
|
|
// which breaks a lot of our expectations about the number of rules
|
|
// present in a style sheet.
|
|
if (!isIe7) {
|
|
assertEquals(cssText, fixCssTextForIe(allCssText));
|
|
}
|
|
}
|
|
|
|
function testGetAllCssStyleRules() {
|
|
var allCssRules = goog.cssom.getAllCssStyleRules();
|
|
assertEquals(6, allCssRules.length);
|
|
}
|
|
|
|
|
|
function testAddCssText() {
|
|
var newCssText = '.css-add-1 { display: block; }';
|
|
var newCssNode = goog.cssom.addCssText(newCssText);
|
|
|
|
assertEquals(document.styleSheets.length, 3);
|
|
|
|
var allCssText = goog.cssom.getAllCssText();
|
|
|
|
// In IE7, a CSSRule object gets included twice and replaces another
|
|
// existing CSSRule object. We aren't using
|
|
// goog.testing.ExpectedFailures since it brings in additional CSS
|
|
// which breaks a lot of our expectations about the number of rules
|
|
// present in a style sheet.
|
|
if (!isIe7) {
|
|
// Opera inserts the CSSRule to the first position. And fixCssText
|
|
// is also needed to clean up whitespace.
|
|
if (goog.userAgent.OPERA) {
|
|
assertEquals(newCssText + ' ' + cssText,
|
|
fixCssTextForIe(allCssText));
|
|
} else {
|
|
assertEquals(cssText + ' ' + newCssText,
|
|
fixCssTextForIe(allCssText));
|
|
}
|
|
}
|
|
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
assertEquals(7, cssRules.length);
|
|
|
|
// Remove the new stylesheet now so it doesn't interfere with other
|
|
// tests.
|
|
newCssNode.parentNode.removeChild(newCssNode);
|
|
// Sanity check.
|
|
cssRules = goog.cssom.getAllCssStyleRules();
|
|
assertEquals(6, cssRules.length);
|
|
}
|
|
|
|
function testAddCssRule() {
|
|
// test that addCssRule correctly adds the rule to the style
|
|
// sheet.
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var newCssRule = '.css-addCssRule { display: block; }';
|
|
var rules = styleSheet.rules || styleSheet.cssRules;
|
|
var origNumberOfRules = rules.length;
|
|
|
|
goog.cssom.addCssRule(styleSheet, newCssRule, 1);
|
|
|
|
rules = styleSheet.rules || styleSheet.cssRules;
|
|
var newNumberOfRules = rules.length;
|
|
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
|
|
|
// Remove the added rule so we don't mess up other tests.
|
|
goog.cssom.removeCssRule(styleSheet, 1);
|
|
}
|
|
|
|
function testAddCssRuleAtPos() {
|
|
// test that addCssRule correctly adds the rule to the style
|
|
// sheet at the specified position.
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var newCssRule = '.css-addCssRulePos { display: block; }';
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var origNumberOfRules = rules.length;
|
|
|
|
// Firefox croaks if we try to insert a CSSRule at an index that
|
|
// contains a CSSImport Rule. Since we deal only with CSSStyleRule
|
|
// objects, we find the first CSSStyleRule and return its index.
|
|
//
|
|
// NOTE(user): We could have unified the code block below for all
|
|
// browsers but IE6 horribly mangled up the stylesheet by creating
|
|
// duplicate instances of a rule when removeCssRule was invoked
|
|
// just after addCssRule with the looping construct in. This is
|
|
// perfectly fine since IE's styleSheet.rules does not contain
|
|
// references to anything but CSSStyleRules.
|
|
var pos = 0;
|
|
if (styleSheet.cssRules) {
|
|
pos = goog.array.findIndex(rules, function(rule) {
|
|
return rule.type == goog.cssom.CssRuleType.STYLE;
|
|
});
|
|
}
|
|
goog.cssom.addCssRule(styleSheet, newCssRule, pos);
|
|
|
|
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var newNumberOfRules = rules.length;
|
|
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
|
|
|
// Remove the added rule so we don't mess up other tests.
|
|
goog.cssom.removeCssRule(styleSheet, pos);
|
|
|
|
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
assertEquals(origNumberOfRules, rules.length);
|
|
}
|
|
|
|
function testAddCssRuleNoIndex() {
|
|
// How well do we handle cases where the optional index is
|
|
// not passed in?
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var origNumberOfRules = rules.length;
|
|
var newCssRule = '.css-addCssRuleNoIndex { display: block; }';
|
|
|
|
// Try inserting the rule without specifying an index.
|
|
// Make sure we don't throw an exception, and that we added
|
|
// the entry.
|
|
goog.cssom.addCssRule(styleSheet, newCssRule);
|
|
|
|
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var newNumberOfRules = rules.length;
|
|
assertEquals(newNumberOfRules, origNumberOfRules + 1);
|
|
|
|
// Remove the added rule so we don't mess up the other tests.
|
|
goog.cssom.removeCssRule(styleSheet, newNumberOfRules - 1);
|
|
|
|
rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
assertEquals(origNumberOfRules, rules.length);
|
|
}
|
|
|
|
|
|
function testGetParentStyleSheetAfterGetAllCssStyleRules() {
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
var cssRule = cssRules[4];
|
|
var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule);
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
assertEquals(styleSheet, parentStyleSheet);
|
|
}
|
|
|
|
function testGetCssRuleIndexInParentStyleSheetAfterGetAllCssStyleRules() {
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
var cssRule = cssRules[4];
|
|
// Note here that this is correct - IE's styleSheet.rules does not
|
|
// contain references to anything but CSSStyleRules while FF and others
|
|
// include anything that inherits from the CSSRule interface.
|
|
// See http://dev.w3.org/csswg/cssom/#cssrule.
|
|
var parentStyleSheet = goog.cssom.getParentStyleSheet(cssRule);
|
|
var ruleIndex = goog.isDefAndNotNull(parentStyleSheet.cssRules) ? 2 : 1;
|
|
assertEquals(ruleIndex,
|
|
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule));
|
|
}
|
|
|
|
function testGetCssRuleIndexInParentStyleSheetNonStyleRule() {
|
|
// IE's styleSheet.rules only contain CSSStyleRules.
|
|
if (!goog.userAgent.IE) {
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var newCssRule = '@media print { .css-nonStyle { display: block; } }';
|
|
goog.cssom.addCssRule(styleSheet, newCssRule);
|
|
var rules = styleSheet.rules || styleSheet.cssRules;
|
|
var cssRule = rules[rules.length - 1];
|
|
assertEquals(goog.cssom.CssRuleType.MEDIA, cssRule.type);
|
|
// Make sure we don't throw an exception.
|
|
goog.cssom.getCssRuleIndexInParentStyleSheet(cssRule, styleSheet);
|
|
// Remove the added rule.
|
|
goog.cssom.removeCssRule(styleSheet, rules.length - 1);
|
|
}
|
|
}
|
|
|
|
// Tests the scenario where we have a known stylesheet and index.
|
|
function testReplaceCssRuleWithStyleSheetAndIndex() {
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var index = 2;
|
|
var origCssRule = rules[index];
|
|
var origCssText =
|
|
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule));
|
|
|
|
goog.cssom.replaceCssRule(origCssRule, replacementCssText, styleSheet,
|
|
index);
|
|
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var newCssRule = rules[index];
|
|
var newCssText = goog.cssom.getCssTextFromCssRule(newCssRule);
|
|
assertEquals(replacementCssText, fixCssTextForIe(newCssText));
|
|
|
|
// Now we need to re-replace our rule, to preserve parity for the other
|
|
// tests.
|
|
goog.cssom.replaceCssRule(newCssRule, origCssText, styleSheet, index);
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var nowCssRule = rules[index];
|
|
var nowCssText = goog.cssom.getCssTextFromCssRule(nowCssRule);
|
|
assertEquals(origCssText, fixCssTextForIe(nowCssText));
|
|
}
|
|
|
|
function testReplaceCssRuleUsingGetAllCssStyleRules() {
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
var origCssRule = cssRules[4];
|
|
var origCssText =
|
|
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(origCssRule));
|
|
// notice we don't pass in the stylesheet or index.
|
|
goog.cssom.replaceCssRule(origCssRule, replacementCssText);
|
|
|
|
var styleSheets = goog.cssom.getAllCssStyleSheets();
|
|
var styleSheet = styleSheets[3];
|
|
var rules = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
|
|
var index = goog.isDefAndNotNull(styleSheet.cssRules) ? 2 : 1;
|
|
var newCssRule = rules[index];
|
|
var newCssText =
|
|
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule));
|
|
assertEquals(replacementCssText, newCssText);
|
|
|
|
// try getting it the other way around too.
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
var newCssRule = cssRules[4];
|
|
var newCssText =
|
|
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(newCssRule));
|
|
assertEquals(replacementCssText, newCssText);
|
|
|
|
// Now we need to re-replace our rule, to preserve parity for the other
|
|
// tests.
|
|
goog.cssom.replaceCssRule(newCssRule, origCssText);
|
|
var cssRules = goog.cssom.getAllCssStyleRules();
|
|
var nowCssRule = cssRules[4];
|
|
var nowCssText =
|
|
fixCssTextForIe(goog.cssom.getCssTextFromCssRule(nowCssRule));
|
|
assertEquals(origCssText, nowCssText);
|
|
}
|