aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Jones <bjones@galois.com>2013-07-16 14:44:19 -0700
committerGravatar Benjamin Jones <bjones@galois.com>2013-07-16 14:44:19 -0700
commite089832e50c87a79a9872009fd47231473d81b7a (patch)
tree21b6e323d99ea0b8a75696708d496360e9cea383
parent265f160e55d98b37aa8d8f9b16a1a5ccb32bdb0d (diff)
modified: src/js/fiveui/injected/jquery-plugins.js
added two new plugins -- noAttr and noSubElt fixed bug in notColorSet modified: src/js/fiveui/injected/prelude.js fixed bugs and added better error handling to the fiveui.color functions new file: src/js/tests/specs/jquery-plugins.js added unit tests for all the (non-debugging) jQuery plugins
-rw-r--r--src/js/fiveui/injected/jquery-plugins.js61
-rw-r--r--src/js/fiveui/injected/prelude.js35
-rw-r--r--src/js/tests/PhantomJSJasmineRunner.html3
-rw-r--r--src/js/tests/SpecRunner.html2
-rw-r--r--src/js/tests/specs/jquery-plugins.js135
5 files changed, 216 insertions, 20 deletions
diff --git a/src/js/fiveui/injected/jquery-plugins.js b/src/js/fiveui/injected/jquery-plugins.js
index 43cfbd6..5a32031 100644
--- a/src/js/fiveui/injected/jquery-plugins.js
+++ b/src/js/fiveui/injected/jquery-plugins.js
@@ -31,6 +31,10 @@ fiveui.jquery = fiveui.jquery || {};
/**
* Wrapper for the :contains('text') selector
*
+ * Example:
+ *
+ * $('div').hasText('to remove').remove();
+ *
* @param {!String} text Text to select for
* @returns {!Object} A modified jQuery object
*/
@@ -39,6 +43,42 @@ fiveui.jquery.hasText = function (text) {
};
/**
+ * Filter for elements which lack of the given attribute.
+ *
+ * Example:
+ *
+ * This object will be non-empty:
+ *
+ * $('<table></table>').noAttr('summary')
+ *
+ * @param {!String} attribute name
+ * @returns {!Object} a filtered jQuery object
+ */
+fiveui.jquery.noAttr = function (name) {
+ return this.filter(function () {
+ $attr = $.trim($(this).attr(name));
+ return $attr == undefined || $attr == '';
+ });
+};
+
+
+/**
+ * Filter for elements having no sub-elements matching the given selector.
+ *
+ * Example: the following should contain no elements
+ *
+ * $('<div><p>hello</p></div>').noSubElt('p')
+ *
+ * @param {!String} sel a jQuery selector
+ * @param {!Object} A filtered jQuery object
+ */
+fiveui.jquery.noSubElt = function (sel) {
+ return this.filter(function () {
+ return $(this).find(sel).length == 0;
+ });
+};
+
+/**
* Color checker plugin: filters for elements whose CSS color property is
* not in the given set.
*
@@ -46,17 +86,20 @@ fiveui.jquery.hasText = function (text) {
* $(..).notColorSet(set) == $(..).cssIsNot("color", set, fiveui.color.colorToHex)
* @see {fiveui.color.colorToHex}
*
- * @param {String[]} cset A set of allowable color strings
+ * @param {String[]} cset An array of allowable color strings
* @returns {!Object} A modified jQuery object
*/
fiveui.jquery.notColorSet = function (cset) {
var allowable = {};
- for (var i = 0; i < cset.length; i += 1) { allowable[cset[i]] = true; } // array -> object
+ // input array -> object
+ for (var i = 0; i < cset.length; i += 1) {
+ allowable[fiveui.color.colorToHex(cset[i])] = true;
+ }
return this.filter(function (index) {
- var color = fiveui.color.colorToHex($(this).css("color")); // .css("color") returns rgb(...)
+ var color = fiveui.color.colorToHexWithDefault($(this).css("color")); // .css("color") returns rgb(...)
return !(color in allowable);
});
-}
+};
/**
* General CSS propetry checker plugin
@@ -78,7 +121,10 @@ fiveui.jquery.cssIsNot = function (prop, set, fn) {
allowable[fn(set)] = true;
}
else { // assume `set` is an array of strings
- for (var i = 0; i < set.length; i += 1) { allowable[fn(set[i])] = true; } // array -> object
+ // array -> object
+ for (var i = 0; i < set.length; i += 1) {
+ allowable[fn(set[i])] = true;
+ }
}
return this.filter(function (index) {
var cssProp = fn($(this).css(prop));
@@ -94,10 +140,7 @@ fiveui.jquery.cssIsNot = function (prop, set, fn) {
* @returns {Object} jQuery object
*/
fiveui.jquery.linksTo = function (href) {
- return this.filter(function (index) {
- var addr = $(this).attr("href");
- return (addr == href);
- });
+ return this.filter('[href=' + href + ']');
}
/**
diff --git a/src/js/fiveui/injected/prelude.js b/src/js/fiveui/injected/prelude.js
index ce242f6..db32d7f 100644
--- a/src/js/fiveui/injected/prelude.js
+++ b/src/js/fiveui/injected/prelude.js
@@ -300,7 +300,7 @@ fiveui.color.hexToRGB = function (hex) {
/**
* Covert rgb colors to hex and abreviated hex colors to their full 3 byte
- * form.
+ * and uppercase normal form.
*
* In case there are parse errors during the conversion, i.e. color values
* that are not understood, the input is returned unchanged.
@@ -312,16 +312,29 @@ fiveui.color.hexToRGB = function (hex) {
fiveui.color.colorToHex = function(color) {
if (color.substr(0, 1) === '#') {
if (color.length === 7) {
- return color;
+ return color.toUpperCase();
}
else { // deal with #0 or #F7 cases
- return shortHexToHex(color);
+ return shortHexToHex(color).toUpperCase();
}
}
- else { // color == 'rgb...'
+ else if (color.substr(0,3) === 'rgb') {
var c = fiveui.color.colorToRGB(color)
return fiveui.color.rgbToHex(c.r, c.g, c.b);
}
+ else {
+ throw new Error('could not convert color string "' + color + '"');
+ }
+};
+
+fiveui.color.colorToHexWithDefault = function (color) {
+ try {
+ return fiveui.color.colorToHex(color);
+ }
+ catch (e) {
+ console.log(e);
+ return color;
+ }
};
/**
@@ -333,14 +346,14 @@ fiveui.color.colorToHex = function(color) {
*/
fiveui.color.colorToRGB = function(color) {
- if (color.substr(0, 1) === '#') {
- return fiveui.color.hexToRGB(fiveui.color.colorToHex(color));
- }
+ if (color.substr(0, 1) === '#') {
+ return fiveui.color.hexToRGB(fiveui.color.colorToHex(color));
+ }
- var digits = /rgba?\((\d+), (\d+), (\d+)(, ([-+]?[0-9]*\.?[0-9]+))?/.exec(color);
- if (!digits) {
- throw new ParseError('could not parse color string: ' + color);
- }
+ var digits = /rgba?\((\d+), (\d+), (\d+)(, ([-+]?[0-9]*\.?[0-9]+))?/.exec(color);
+ if (!digits) {
+ throw new Error('could not parse color string: "' + color + '"');
+ }
var alpha = 1;
if (digits[5] != undefined) {
diff --git a/src/js/tests/PhantomJSJasmineRunner.html b/src/js/tests/PhantomJSJasmineRunner.html
index 606a251..907e176 100644
--- a/src/js/tests/PhantomJSJasmineRunner.html
+++ b/src/js/tests/PhantomJSJasmineRunner.html
@@ -26,6 +26,7 @@
<script type="text/javascript" src="../fiveui/js/settings.js"></script>
<script type="text/javascript" src="../fiveui/js/state.js"></script>
<script type="text/javascript" src="../fiveui/injected/prelude.js"></script>
+ <script type="text/javascript" src="../fiveui/injected/jquery-plugins.js"></script>
<!-- spec files -->
<script type="text/javascript" src="specs/set.js"></script>
@@ -35,6 +36,8 @@
<script type="text/javascript" src="specs/settings.js"></script>
<script type="text/javascript" src="specs/state.js"></script>
<script type="text/javascript" src="specs/prelude.js"></script>
+ <script type="text/javascript" src="specs/jquery-plugins.js"></script>
+
</head>
<body>
diff --git a/src/js/tests/SpecRunner.html b/src/js/tests/SpecRunner.html
index 606967e..caf0248 100644
--- a/src/js/tests/SpecRunner.html
+++ b/src/js/tests/SpecRunner.html
@@ -24,6 +24,7 @@
<script type="text/javascript" src="../fiveui/js/settings.js"></script>
<script type="text/javascript" src="../fiveui/js/state.js"></script>
<script type="text/javascript" src="../fiveui/injected/prelude.js"></script>
+ <script type="text/javascript" src="../fiveui/injected/jquery-plugins.js"></script>
<script type="text/javascript" src="specs/set.js"></script>
<script type="text/javascript" src="specs/utils.js"></script>
@@ -32,6 +33,7 @@
<script type="text/javascript" src="specs/settings.js"></script>
<script type="text/javascript" src="specs/state.js"></script>
<script type="text/javascript" src="specs/prelude.js"></script>
+ <script type="text/javascript" src="specs/jquery-plugins.js"></script>
</head>
diff --git a/src/js/tests/specs/jquery-plugins.js b/src/js/tests/specs/jquery-plugins.js
new file mode 100644
index 0000000..7fc196b
--- /dev/null
+++ b/src/js/tests/specs/jquery-plugins.js
@@ -0,0 +1,135 @@
+describe('jQuery plugins', function () {
+
+ describe('fiveui.jquery.hasText', function () {
+ it('finds an element containing "text foo bar"', function () {
+ var $t = $('<div>text foo bar</div>');
+ expect($t.hasText('text foo bar').length).toEqual(1);
+ });
+
+ it('finds no element containing "quux"', function () {
+ var $t = $('<div>text foo bar</div>');
+ expect($t.hasText('quux').length).toEqual(0);
+ });
+
+ it('finds a nested element containing "hobbit"', function () {
+ $t = $('<div><h1>golum</h1><div>hobbit</div></div>');
+ expect($t.hasText('hobbit').length).toEqual(1);
+ });
+ });
+
+ describe('fiveui.jquery.noAttr', function () {
+ it('returns elements having no summary attribute', function () {
+ var $t = $('<table></table>').noAttr('summary');
+ expect($t.length).toEqual(1);
+ });
+
+ it('returns no elements on empty input', function () {
+ var $t = $('').noAttr('summary');
+ expect($t.length).toEqual(0);
+ });
+
+ it('doesn\'t return elements with attributes other than the given', function () {
+ var $t = $('<table foo="bar"></table>').noAttr('summary');
+ expect($t.length).toEqual(1);
+ });
+
+ it('returns multiple elements having no summary attribute', function () {
+ var htm = '<table></table>' +
+ '<table summary="empty"></table>' +
+ '<table></table>' +
+ '<table></table>' +
+ '<table summary="full"></table>';
+ var $t = $(htm).noAttr('summary');
+ expect($t.length).toEqual(3);
+ });
+
+ });
+
+ describe('fiveui.jquery.noSubElt', function () {
+ var $t = $('<div><p>red hering</p><h1>blue hering</h1></div>')
+
+ it('filters out elements with a sub-heading', function () {
+ expect($t.noSubElt('h1').length).toEqual(0);
+ expect($t.noSubElt(':header').length).toEqual(0);
+ });
+
+ it('filters out elements with a <p>', function () {
+ expect($t.noSubElt('p').length).toEqual(0);
+ });
+
+ it('retains elements without <li>', function () {
+ expect($t.noSubElt('li').length).toEqual(1);
+ });
+
+ it('accepts arbitrary jQuery seclectors', function () {
+ expect($t.noSubElt('p[name=bob]').length).toEqual(1);
+ });
+ });
+
+ describe('fiveui.jquery.notColorSet', function () {
+ var htm = '<p style="color: #000000">foo</p>' +
+ '<p style="color: #ffffff">foo</p>' +
+ '<p style="color: #e1e1e1">foo</p>' +
+ '<p style="color: #ffffff">foo</p>';
+ var $t = $(htm);
+
+ it('filters out black', function () {
+ expect($t.notColorSet(['#000000']).length).toEqual(3);
+ });
+
+ it('filters out white', function () {
+ expect($t.notColorSet(['#ffffff']).length).toEqual(2);
+ });
+
+ it('filters out black and white', function () {
+ expect($t.notColorSet(['#ffffff', '#000000']).length).toEqual(1);
+ });
+
+ it('filters out everything', function () {
+ expect($t.notColorSet(['#ffffff', '#000000', '#e1e1e1']).length).toEqual(0);
+ });
+ });
+
+ describe('fiveui.jquery.cssIsNot', function () {
+ var htm = '<p style="color: #000000; background-color: #232323">foo</p>' +
+ '<p style="color: #ffffff; font-size: 5em">foo</p>' +
+ '<p style="color: #e1e1e1; background-color: #141414">foo</p>' +
+ '<p style="color: #ffffff">foo</p>' +
+ '<h1 style="color: #ffffff; font-size: 5em">big</h1>';
+ var $t = $(htm);
+
+ it('filters out colors', function () {
+ expect($t.cssIsNot('color', ['#ffffff', '#000000'], fiveui.color.colorToHexWithDefault).length).toEqual(1);
+ });
+
+ it('filters out background-colors', function () {
+ expect($t.cssIsNot('background-color', ['#141414', '#232323'], fiveui.color.colorToHexWithDefault).length).toEqual(3);
+ });
+
+ it('filters out elements of different type', function () {
+ expect($t.cssIsNot('font-size', ['5em']).length).toEqual(3);
+ });
+ });
+
+ describe('fiveui.jquery.linksTo', function () {
+ it('filters out elements with no href', function () {
+ expect($('<p>foo</p>').linksTo('bar').length).toEqual(0);
+ });
+
+ it('filters out elements with wrong href', function () {
+ expect($('<a href="quux">foo</a>').linksTo('bar').length).toEqual(0);
+ });
+
+ var htm = '<a href="quux">foo</a> <a href="bar">foo2</a> <a href="quux">foo3</a>';
+ var $t = $(htm);
+
+ it('filters in among various hrefs', function () {
+ expect($t.linksTo('bar').length).toEqual(1);
+ });
+
+ it('filters out among various hrefs', function () {
+ expect($t.linksTo('quux').length).toEqual(2);
+ });
+ });
+
+});