Skip to content
Browse files

Added small test suite using Jasmine.

  • Loading branch information...
1 parent e9a0eba commit 35b0c60e1efd6ea4cd36a6b9220ecc5193199d2c @polarblau committed
View
1 .gitignore
@@ -0,0 +1 @@
+.DS_Store
View
20 lib/jasmine-1.1.0/MIT.LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2008-2011 Pivotal Labs
+
+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.
View
190 lib/jasmine-1.1.0/jasmine-html.js
@@ -0,0 +1,190 @@
+jasmine.TrivialReporter = function(doc) {
+ this.document = doc || document;
+ this.suiteDivs = {};
+ this.logRunningSpecs = false;
+};
+
+jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
+ var el = document.createElement(type);
+
+ for (var i = 2; i < arguments.length; i++) {
+ var child = arguments[i];
+
+ if (typeof child === 'string') {
+ el.appendChild(document.createTextNode(child));
+ } else {
+ if (child) { el.appendChild(child); }
+ }
+ }
+
+ for (var attr in attrs) {
+ if (attr == "className") {
+ el[attr] = attrs[attr];
+ } else {
+ el.setAttribute(attr, attrs[attr]);
+ }
+ }
+
+ return el;
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
+ var showPassed, showSkipped;
+
+ this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
+ this.createDom('div', { className: 'banner' },
+ this.createDom('div', { className: 'logo' },
+ this.createDom('span', { className: 'title' }, "Jasmine"),
+ this.createDom('span', { className: 'version' }, runner.env.versionString())),
+ this.createDom('div', { className: 'options' },
+ "Show ",
+ showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
+ showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
+ )
+ ),
+
+ this.runnerDiv = this.createDom('div', { className: 'runner running' },
+ this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
+ this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
+ this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
+ );
+
+ this.document.body.appendChild(this.outerDiv);
+
+ var suites = runner.suites();
+ for (var i = 0; i < suites.length; i++) {
+ var suite = suites[i];
+ var suiteDiv = this.createDom('div', { className: 'suite' },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
+ this.suiteDivs[suite.id] = suiteDiv;
+ var parentDiv = this.outerDiv;
+ if (suite.parentSuite) {
+ parentDiv = this.suiteDivs[suite.parentSuite.id];
+ }
+ parentDiv.appendChild(suiteDiv);
+ }
+
+ this.startedAt = new Date();
+
+ var self = this;
+ showPassed.onclick = function(evt) {
+ if (showPassed.checked) {
+ self.outerDiv.className += ' show-passed';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
+ }
+ };
+
+ showSkipped.onclick = function(evt) {
+ if (showSkipped.checked) {
+ self.outerDiv.className += ' show-skipped';
+ } else {
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
+ }
+ };
+};
+
+jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
+ var results = runner.results();
+ var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
+ this.runnerDiv.setAttribute("class", className);
+ //do it twice for IE
+ this.runnerDiv.setAttribute("className", className);
+ var specs = runner.specs();
+ var specCount = 0;
+ for (var i = 0; i < specs.length; i++) {
+ if (this.specFilter(specs[i])) {
+ specCount++;
+ }
+ }
+ var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
+ message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
+ this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
+
+ this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
+};
+
+jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
+ var results = suite.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.totalCount === 0) { // todo: change this to check results.skipped
+ status = 'skipped';
+ }
+ this.suiteDivs[suite.id].className += " " + status;
+};
+
+jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
+ if (this.logRunningSpecs) {
+ this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
+ }
+};
+
+jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
+ var results = spec.results();
+ var status = results.passed() ? 'passed' : 'failed';
+ if (results.skipped) {
+ status = 'skipped';
+ }
+ var specDiv = this.createDom('div', { className: 'spec ' + status },
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
+ this.createDom('a', {
+ className: 'description',
+ href: '?spec=' + encodeURIComponent(spec.getFullName()),
+ title: spec.getFullName()
+ }, spec.description));
+
+
+ var resultItems = results.getItems();
+ var messagesDiv = this.createDom('div', { className: 'messages' });
+ for (var i = 0; i < resultItems.length; i++) {
+ var result = resultItems[i];
+
+ if (result.type == 'log') {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
+
+ if (result.trace.stack) {
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
+ }
+ }
+ }
+
+ if (messagesDiv.childNodes.length > 0) {
+ specDiv.appendChild(messagesDiv);
+ }
+
+ this.suiteDivs[spec.suite.id].appendChild(specDiv);
+};
+
+jasmine.TrivialReporter.prototype.log = function() {
+ var console = jasmine.getGlobal().console;
+ if (console && console.log) {
+ if (console.log.apply) {
+ console.log.apply(console, arguments);
+ } else {
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
+ }
+ }
+};
+
+jasmine.TrivialReporter.prototype.getLocation = function() {
+ return this.document.location;
+};
+
+jasmine.TrivialReporter.prototype.specFilter = function(spec) {
+ var paramMap = {};
+ var params = this.getLocation().search.substring(1).split('&');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i].split('=');
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
+ }
+
+ if (!paramMap.spec) {
+ return true;
+ }
+ return spec.getFullName().indexOf(paramMap.spec) === 0;
+};
View
166 lib/jasmine-1.1.0/jasmine.css
@@ -0,0 +1,166 @@
+body {
+ font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
+}
+
+
+.jasmine_reporter a:visited, .jasmine_reporter a {
+ color: #303;
+}
+
+.jasmine_reporter a:hover, .jasmine_reporter a:active {
+ color: blue;
+}
+
+.run_spec {
+ float:right;
+ padding-right: 5px;
+ font-size: .8em;
+ text-decoration: none;
+}
+
+.jasmine_reporter {
+ margin: 0 5px;
+}
+
+.banner {
+ color: #303;
+ background-color: #fef;
+ padding: 5px;
+}
+
+.logo {
+ float: left;
+ font-size: 1.1em;
+ padding-left: 5px;
+}
+
+.logo .version {
+ font-size: .6em;
+ padding-left: 1em;
+}
+
+.runner.running {
+ background-color: yellow;
+}
+
+
+.options {
+ text-align: right;
+ font-size: .8em;
+}
+
+
+
+
+.suite {
+ border: 1px outset gray;
+ margin: 5px 0;
+ padding-left: 1em;
+}
+
+.suite .suite {
+ margin: 5px;
+}
+
+.suite.passed {
+ background-color: #dfd;
+}
+
+.suite.failed {
+ background-color: #fdd;
+}
+
+.spec {
+ margin: 5px;
+ padding-left: 1em;
+ clear: both;
+}
+
+.spec.failed, .spec.passed, .spec.skipped {
+ padding-bottom: 5px;
+ border: 1px solid gray;
+}
+
+.spec.failed {
+ background-color: #fbb;
+ border-color: red;
+}
+
+.spec.passed {
+ background-color: #bfb;
+ border-color: green;
+}
+
+.spec.skipped {
+ background-color: #bbb;
+}
+
+.messages {
+ border-left: 1px dashed gray;
+ padding-left: 1em;
+ padding-right: 1em;
+}
+
+.passed {
+ background-color: #cfc;
+ display: none;
+}
+
+.failed {
+ background-color: #fbb;
+}
+
+.skipped {
+ color: #777;
+ background-color: #eee;
+ display: none;
+}
+
+
+/*.resultMessage {*/
+ /*white-space: pre;*/
+/*}*/
+
+.resultMessage span.result {
+ display: block;
+ line-height: 2em;
+ color: black;
+}
+
+.resultMessage .mismatch {
+ color: black;
+}
+
+.stackTrace {
+ white-space: pre;
+ font-size: .8em;
+ margin-left: 10px;
+ max-height: 5em;
+ overflow: auto;
+ border: 1px inset red;
+ padding: 1em;
+ background: #eef;
+}
+
+.finished-at {
+ padding-left: 1em;
+ font-size: .6em;
+}
+
+.show-passed .passed,
+.show-skipped .skipped {
+ display: block;
+}
+
+
+#jasmine_content {
+ position:fixed;
+ right: 100%;
+}
+
+.runner {
+ border: 1px solid gray;
+ display: block;
+ margin: 5px 0;
+ padding: 2px 0 2px 10px;
+}
View
2,476 lib/jasmine-1.1.0/jasmine.js
2,476 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
BIN lib/jasmine-1.1.0/jasmine_favicon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
53 spec/index.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Jasmine Test Runner</title>
+ <link rel="stylesheet" type="text/css" href="../lib/jasmine-1.1.0/jasmine.css">
+ <script type="text/javascript" src="../lib/jasmine-1.1.0/jasmine.js"></script>
+ <script type="text/javascript" src="../lib/jasmine-1.1.0/jasmine-html.js"></script>
+
+ <script src="http://code.jquery.com/jquery.min.js" type="text/javascript" charset="utf-8"></script>
+ <script src="stickysectionheaders_spec.js" type="text/javascript" charset="utf-8"></script>
+
+ <script src="../src/jquery.stickysectionheaders.js" type="text/javascript" charset="utf-8"></script>
+
+ <style>
+ ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ #sticky-list {
+ height: 100px;
+ overflow: hidden;
+ position: relative;
+ }
+
+ #sticky-list > ul {
+ height: 100%;
+ overflow: auto;
+ }
+
+ #sticky-list > ul > li strong {
+ display: block;
+ }
+
+ #sticky-list > ul > li.sticky strong {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ }
+ </style>
+
+ </head>
+ <body>
+
+ <script type="text/javascript">
+ jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
+ jasmine.getEnv().execute();
+ </script>
+
+ </body>
+</html>
View
136 spec/stickysectionheaders_spec.js
@@ -0,0 +1,136 @@
+describe('stickysectionheaders', function () {
+
+ // Helpers
+
+ function hasNamesSpacedEvent(el, event, namespace) {
+ var events = $(el).data("events");
+ return events[event] !== undefined && events[event][0].namespace === namespace;
+ };
+
+ function makeFixture() {
+ var fixture = [];
+ fixture.push('<div id="sticky-list" class="sticky-list">');
+ fixture.push('<ul class="sections">');
+ var sectionsCount = Math.ceil(Math.random() * 5) + 5;
+ for (var i = 0; i < sectionsCount; i++) {
+ fixture.push('<li><strong>Headline</strong><ul>');
+ var listItemsCount = Math.ceil(Math.random() * 5) + 5;
+ for (var j = 0; j < listItemsCount; j++) {
+ fixture.push('<li>Content line</li>');
+ }
+ fixture.push('</ul></li>');
+ }
+ fixture.push('</ul>');
+ fixture.push('</div>');
+ return $(fixture.join(''));
+ }
+
+ // Custom matchers
+
+ var isListStickified = function(input) {
+ var isStickified = hasNamesSpacedEvent($(input).find("> ul"), "scroll", "sticky");
+ return isStickified ? isStickified : null;
+ };
+
+ beforeEach(function () {
+ this.addMatchers({
+ toBeStickified: function() {
+ return isListStickified(this.actual);
+ },
+ toBeNotStickified: function() {
+ return !isListStickified(this.actual);
+ }
+ });
+ });
+
+ // Build and remove fixtures in setup and teardown
+
+ beforeEach(function () {
+ makeFixture().appendTo('body');
+ });
+
+ afterEach(function () {
+ $("#sticky-list").remove();
+ });
+
+ //
+
+ // TEST: Settings
+
+ it('should use the default "sticky" for stickyClass', function() {
+ var $list = $(".sticky-list").stickySectionHeaders();
+ $list.find("ul").scrollTop(10);
+ expect($list.find("> ul > li:first").hasClass("sticky")).toBeTruthy();
+ });
+
+ it('should allow setting the "stickyClass" property', function() {
+ var $list = $(".sticky-list").stickySectionHeaders({ 'stickyClass' : 'foo' });
+ $list.find("ul").scrollTop(10);
+ expect($list.find("> ul > li:first").hasClass("foo")).toBeTruthy();
+ });
+
+ // TEST: CSS & Attrbutes
+
+ it('should assign the "stickyClass" to the top most list element when scrolled', function() {
+ var $list = $(".sticky-list").stickySectionHeaders();
+ $list.find("ul").scrollTop(10);
+ expect($list.find("> ul > li:first").hasClass("sticky")).toBeTruthy();
+ });
+
+ it('should not assign the "stickyClass" to the top most list element when not scrolled', function() {
+ var $list = $(".sticky-list").stickySectionHeaders();
+ expect($list.find("> ul > li:first").hasClass("sticky")).toBeFalsy();
+ });
+
+ it('should "stick" the top most element to the top when scrolled', function() {
+ var $list = $(".sticky-list").stickySectionHeaders();
+ $list.find("ul").scrollTop(20);
+ expect($list.find("> ul > li:first strong").css("top")).toEqual("0px");
+ });
+
+
+ // TEST: General jQuery plugin functionality
+
+ it('should be applicable to multiple elements', function() {
+ var $list_1 = $("#sticky-list");
+ var $list_2 = makeFixture().appendTo('body');
+ $(".sticky-list").stickySectionHeaders();
+ expect($list_1).toBeStickified();
+ expect($list_2).toBeStickified();
+ $list_2.remove();
+ });
+
+ it('should be chainable', function() {
+ var $list = $("#sticky-list");
+ $list.stickySectionHeaders().addClass('foo');
+ expect($list.hasClass('foo')).toBeTruthy();
+ });
+
+
+ // TEST: Helper: cssShortForAllSides
+
+ describe('cssSum', function(){
+
+ var $div;
+
+ beforeEach(function(){
+ $div = $("<div/>");
+ });
+
+ afterEach(function(){
+ $div.remove();
+ });
+
+ it('should return the sum of all properties', function() {
+ $div.attr("style", "padding-left: 5px");
+ expect($div.cssSum('paddingLeft', 'paddingRight')).toEqual(5);
+ });
+
+ it('should return the sum of all properties', function() {
+ $div.attr("style", "padding-left: 5px; padding-right: 10px;");
+ expect($div.cssSum('paddingLeft', 'paddingRight')).toEqual(15);
+ });
+
+ });
+
+});

0 comments on commit 35b0c60

Please sign in to comment.
Something went wrong with that request. Please try again.