diff --git a/.gitignore b/.gitignore
index 15812b0..4f7cdfc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
node_modules
build
+.grunt
.sizecache.json
*.log*
+_SpecRunner.html
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7ad0146..fff320b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,7 +39,7 @@ You should see a green message in the console:
You can also run the tests in the browser.
Start a test server from the project root:
- $ grunt connect:tests
+ $ grunt specs
This will automatically open the tests at http://127.0.0.1:9998/test/index.html in the default browser, with livereload enabled.
diff --git a/Gruntfile.js b/Gruntfile.js
index 3bc12c6..16b1fda 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -9,10 +9,23 @@ module.exports = function (grunt) {
qunit: {
all: ['test/index.html']
},
+ jasmine: {
+ src: 'src/**/*.js',
+ options: {
+ vendor: [
+ 'http://code.jquery.com/jquery-1.11.1.min.js',
+ 'vendor/jasmine-reporter.js'
+ ],
+ specs: 'spec/**/*.js',
+ // So we can view specs in a browser as well...
+ keepRunner: true
+ }
+ },
jshint: {
files: [
'Gruntfile.js',
- 'jquery.cookie.js'
+ 'src/**/*.js'
+ // TODO 'spec/**/*.js'
],
options: {
jshintrc: true
@@ -24,7 +37,7 @@ module.exports = function (grunt) {
},
build: {
files: {
- 'build/jquery.cookie-<%= pkg.version %>.min.js': 'jquery.cookie.js'
+ 'build/jquery.cookie-<%= pkg.version %>.min.js': 'src/jquery.cookie.js'
}
}
},
@@ -33,15 +46,15 @@ module.exports = function (grunt) {
livereload: true
},
files: [
- 'jquery.cookie.js',
- 'test/tests.js'
+ 'src/**/*.js',
+ 'spec/**/*.js'
],
- tasks: 'default'
+ tasks: ['default']
},
compare_size: {
files: [
'build/jquery.cookie-<%= pkg.version %>.min.js',
- 'jquery.cookie.js'
+ 'src/jquery.cookie.js'
],
options: {
compress: {
@@ -64,6 +77,14 @@ module.exports = function (grunt) {
keepalive: true,
livereload: true
}
+ },
+ specs: {
+ options: {
+ port: 3000,
+ open: 'http://127.0.0.1:3000/_SpecRunner.html',
+ keepalive: true,
+ livereload: true
+ }
}
},
'saucelabs-qunit': {
@@ -155,7 +176,99 @@ module.exports = function (grunt) {
]
}
}
- }
+ },
+ 'saucelabs-jasmine': {
+ all: {
+ options: {
+ urls: ['http://127.0.0.1:9999/_SpecRunner.html'],
+ tunnelTimeout: 5,
+ build: process.env.TRAVIS_JOB_ID,
+ concurrency: 3,
+ browsers: [
+ // iOS
+ {
+ browserName: 'iphone',
+ platform: 'OS X 10.9',
+ version: '7.1'
+ },
+ {
+ browserName: 'ipad',
+ platform: 'OS X 10.9',
+ version: '7.1'
+ },
+ // Android
+ {
+ browserName: 'android',
+ platform: 'Linux',
+ version: '4.3'
+ },
+ // OS X
+ {
+ browserName: 'safari',
+ platform: 'OS X 10.9',
+ version: '7'
+ },
+ {
+ browserName: 'safari',
+ platform: 'OS X 10.8',
+ version: '6'
+ },
+ {
+ browserName: 'firefox',
+ platform: 'OS X 10.9',
+ version: '28'
+ },
+ // Windows
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 8.1',
+ version: '11'
+ },
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 8',
+ version: '10'
+ },
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 7',
+ version: '11'
+ },
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 7',
+ version: '10'
+ },
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 7',
+ version: '9'
+ },
+ {
+ browserName: 'internet explorer',
+ platform: 'Windows 7',
+ version: '8'
+ },
+ {
+ browserName: 'firefox',
+ platform: 'Windows 7',
+ version: '29'
+ },
+ {
+ browserName: 'chrome',
+ platform: 'Windows 7',
+ version: '34'
+ },
+ // Linux
+ {
+ browserName: 'firefox',
+ platform: 'Linux',
+ version: '29'
+ }
+ ]
+ }
+ }
+ },
});
// Loading dependencies
@@ -165,7 +278,8 @@ module.exports = function (grunt) {
}
}
- grunt.registerTask('default', ['jshint', 'qunit', 'uglify', 'compare_size']);
- grunt.registerTask('saucelabs', ['connect:saucelabs', 'saucelabs-qunit']);
- grunt.registerTask('ci', ['jshint', 'qunit', 'saucelabs']);
+ grunt.registerTask('default', ['jshint', 'qunit', 'jasmine', 'uglify', 'compare_size']);
+ grunt.registerTask('saucelabs', ['connect:saucelabs', 'saucelabs-qunit', 'saucelabs-jasmine']);
+ grunt.registerTask('ci', ['jshint', 'qunit', 'jasmine', 'saucelabs']);
+ grunt.registerTask('specs', ['jasmine', 'connect:specs']);
};
diff --git a/bower.json b/bower.json
index 2d8c25b..1b38e4d 100644
--- a/bower.json
+++ b/bower.json
@@ -2,7 +2,7 @@
"name": "jquery.cookie",
"version": "1.4.1",
"main": [
- "./jquery.cookie.js"
+ "./src/jquery.cookie.js"
],
"dependencies": {
"jquery": ">=1.2"
diff --git a/component.json b/component.json
index 58f79d6..0fad480 100644
--- a/component.json
+++ b/component.json
@@ -7,8 +7,8 @@
"dependencies": {},
"development": {},
"license": "MIT",
- "main": "jquery.cookie.js",
+ "main": "src/jquery.cookie.js",
"scripts": [
- "jquery.cookie.js"
+ "src/jquery.cookie.js"
]
}
diff --git a/package.json b/package.json
index b15b7ad..569f11b 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "jquery.cookie",
"version": "1.4.1",
"description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies.",
- "main": "jquery.cookie.js",
+ "main": "src/jquery.cookie.js",
"directories": {
"test": "test"
},
@@ -22,6 +22,7 @@
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-uglify": "~0.2.0",
"grunt-contrib-qunit": "~0.2.0",
+ "grunt-contrib-jasmine": "~0.6.4",
"grunt-contrib-watch": "~0.6.1",
"grunt-compare-size": "~0.4.0",
"grunt-saucelabs": "~7.0.0",
@@ -29,11 +30,11 @@
"gzip-js": "~0.3.0"
},
"volo": {
- "url": "https://raw.github.com/carhartl/jquery-cookie/v{version}/jquery.cookie.js"
+ "url": "https://raw.github.com/carhartl/jquery-cookie/v{version}/src/jquery.cookie.js"
},
"jspm": {
"main": "jquery.cookie",
- "files": ["jquery.cookie.js"],
+ "files": ["src/jquery.cookie.js"],
"buildConfig": {
"uglify": true
}
@@ -42,9 +43,9 @@
"dependencies": {
"jquery": ">=1.2"
},
- "main": "jquery.cookie.js",
+ "main": "src/jquery.cookie.js",
"include": [
- "jquery.cookie.js"
+ "src/jquery.cookie.js"
]
}
}
diff --git a/spec/delete_spec.js b/spec/delete_spec.js
new file mode 100644
index 0000000..4e876a8
--- /dev/null
+++ b/spec/delete_spec.js
@@ -0,0 +1,5 @@
+describe("delete", function () {
+ it("test", function () {
+ expect(true).toBe(true);
+ });
+});
diff --git a/spec/read_spec.js b/spec/read_spec.js
new file mode 100644
index 0000000..c147a02
--- /dev/null
+++ b/spec/read_spec.js
@@ -0,0 +1,5 @@
+describe("read", function () {
+ it("test", function () {
+ expect(true).toBe(true);
+ });
+});
diff --git a/spec/write_spec.js b/spec/write_spec.js
new file mode 100644
index 0000000..c69180b
--- /dev/null
+++ b/spec/write_spec.js
@@ -0,0 +1,5 @@
+describe("write", function () {
+ it("test", function () {
+ expect(true).toBe(true);
+ });
+});
diff --git a/jquery.cookie.js b/src/jquery.cookie.js
similarity index 100%
rename from jquery.cookie.js
rename to src/jquery.cookie.js
diff --git a/test/index.html b/test/index.html
index 841310b..ade6830 100644
--- a/test/index.html
+++ b/test/index.html
@@ -6,7 +6,7 @@
-
+
diff --git a/test/malformed_cookie.html b/test/malformed_cookie.html
index 17e8db8..74178d4 100644
--- a/test/malformed_cookie.html
+++ b/test/malformed_cookie.html
@@ -3,7 +3,7 @@
-
+
try {
Object.defineProperty(document, "cookie", { get: function() { return "first=one; ; second=two"; } });
diff --git a/vendor/jasmine-reporter.js b/vendor/jasmine-reporter.js
new file mode 100644
index 0000000..d2180da
--- /dev/null
+++ b/vendor/jasmine-reporter.js
@@ -0,0 +1,396 @@
+/*
+ This file is part of the Jasmine JSReporter project from Ivan De Marino.
+
+ Copyright (C) 2011-2014 Ivan De Marino
+ Copyright (C) 2014 Alex Treppass
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL IVAN DE MARINO BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+(function (jasmine) {
+
+ if (!jasmine) {
+ throw new Error("[Jasmine JSReporter] 'Jasmine' library not found");
+ }
+
+ // ------------------------------------------------------------------------
+ // Jasmine JSReporter for Jasmine 1.x
+ // ------------------------------------------------------------------------
+
+ /**
+ * Calculate elapsed time, in Seconds.
+ * @param startMs Start time in Milliseconds
+ * @param finishMs Finish time in Milliseconds
+ * @return Elapsed time in Seconds */
+ function elapsedSec (startMs, finishMs) {
+ return (finishMs - startMs) / 1000;
+ }
+
+ /**
+ * Round an amount to the given number of Digits.
+ * If no number of digits is given, than '2' is assumed.
+ * @param amount Amount to round
+ * @param numOfDecDigits Number of Digits to round to. Default value is '2'.
+ * @return Rounded amount */
+ function round (amount, numOfDecDigits) {
+ numOfDecDigits = numOfDecDigits || 2;
+ return Math.round(amount * Math.pow(10, numOfDecDigits)) / Math.pow(10, numOfDecDigits);
+ }
+
+ /**
+ * Create a new array which contains only the failed items.
+ * @param items Items which will be filtered
+ * @returns {Array} of failed items */
+ function failures (items) {
+ var fs = [], i, v;
+ for (i = 0; i < items.length; i += 1) {
+ v = items[i];
+ if (!v.passed_) {
+ fs.push(v);
+ }
+ }
+ return fs;
+ }
+
+ /**
+ * Collect information about a Suite, recursively, and return a JSON result.
+ * @param suite The Jasmine Suite to get data from
+ */
+ function getSuiteData (suite) {
+ var suiteData = {
+ description : suite.description,
+ durationSec : 0,
+ specs: [],
+ suites: [],
+ passed: true
+ },
+ specs = suite.specs(),
+ suites = suite.suites(),
+ i, ilen;
+
+ // Loop over all the Suite's Specs
+ for (i = 0, ilen = specs.length; i < ilen; ++i) {
+ suiteData.specs[i] = {
+ description : specs[i].description,
+ durationSec : specs[i].durationSec,
+ passed : specs[i].results().passedCount === specs[i].results().totalCount,
+ skipped : specs[i].results().skipped,
+ passedCount : specs[i].results().passedCount,
+ failedCount : specs[i].results().failedCount,
+ totalCount : specs[i].results().totalCount,
+ failures: failures(specs[i].results().getItems())
+ };
+ suiteData.passed = !suiteData.specs[i].passed ? false : suiteData.passed;
+ suiteData.durationSec += suiteData.specs[i].durationSec;
+ }
+
+ // Loop over all the Suite's sub-Suites
+ for (i = 0, ilen = suites.length; i < ilen; ++i) {
+ suiteData.suites[i] = getSuiteData(suites[i]); //< recursive population
+ suiteData.passed = !suiteData.suites[i].passed ? false : suiteData.passed;
+ suiteData.durationSec += suiteData.suites[i].durationSec;
+ }
+
+ // Rounding duration numbers to 3 decimal digits
+ suiteData.durationSec = round(suiteData.durationSec, 4);
+
+ return suiteData;
+ }
+
+ var JSReporter = function () {
+ };
+
+ JSReporter.prototype = {
+ reportRunnerStarting: function (runner) {
+ // Nothing to do
+ },
+
+ reportSpecStarting: function (spec) {
+ // Start timing this spec
+ spec.startedAt = new Date();
+ },
+
+ reportSpecResults: function (spec) {
+ // Finish timing this spec and calculate duration/delta (in sec)
+ spec.finishedAt = new Date();
+ // If the spec was skipped, reportSpecStarting is never called and spec.startedAt is undefined
+ spec.durationSec = spec.startedAt ? elapsedSec(spec.startedAt.getTime(), spec.finishedAt.getTime()) : 0;
+ },
+
+ reportSuiteResults: function (suite) {
+ // Nothing to do
+ },
+
+ reportRunnerResults: function (runner) {
+ var suites = runner.suites(),
+ i, j, ilen;
+
+ // Attach results to the "jasmine" object to make those results easy to scrap/find
+ jasmine.runnerResults = {
+ suites: [],
+ durationSec : 0,
+ passed : true
+ };
+
+ // Loop over all the Suites
+ for (i = 0, ilen = suites.length, j = 0; i < ilen; ++i) {
+ if (suites[i].parentSuite === null) {
+ jasmine.runnerResults.suites[j] = getSuiteData(suites[i]);
+ // If 1 suite fails, the whole runner fails
+ jasmine.runnerResults.passed = !jasmine.runnerResults.suites[j].passed ? false : jasmine.runnerResults.passed;
+ // Add up all the durations
+ jasmine.runnerResults.durationSec += jasmine.runnerResults.suites[j].durationSec;
+ j++;
+ }
+ }
+
+ // Decorate the 'jasmine' object with getters
+ jasmine.getJSReport = function () {
+ if (jasmine.runnerResults) {
+ return jasmine.runnerResults;
+ }
+ return null;
+ };
+ jasmine.getJSReportAsString = function () {
+ return JSON.stringify(jasmine.getJSReport());
+ };
+ }
+ };
+
+ // export public
+ jasmine.JSReporter = JSReporter;
+
+
+ // ------------------------------------------------------------------------
+ // Jasmine JSReporter for Jasmine 2.0
+ // ------------------------------------------------------------------------
+
+ /*
+ Simple timer implementation
+ */
+ var Timer = function () {};
+
+ Timer.prototype.start = function () {
+ this.startTime = new Date().getTime();
+ return this;
+ };
+
+ Timer.prototype.elapsed = function () {
+ if (this.startTime == null) {
+ return -1;
+ }
+ return new Date().getTime() - this.startTime;
+ };
+
+ /*
+ Utility methods
+ */
+ var _extend = function (obj1, obj2) {
+ for (var prop in obj2) {
+ obj1[prop] = obj2[prop];
+ }
+ return obj1;
+ };
+ var _clone = function (obj) {
+ if (obj !== Object(obj)) {
+ return obj;
+ }
+ return _extend({}, obj);
+ };
+
+ jasmine.JSReporter2 = function () {
+ this.specs = {};
+ this.suites = {};
+ this.rootSuites = [];
+ this.suiteStack = [];
+
+ // export methods under jasmine namespace
+ jasmine.getJSReport = this.getJSReport;
+ jasmine.getJSReportAsString = this.getJSReportAsString;
+ };
+
+ var JSR = jasmine.JSReporter2.prototype;
+
+ // Reporter API methods
+ // --------------------
+
+ JSR.suiteStarted = function (suite) {
+ suite = this._cacheSuite(suite);
+ // build up suite tree as we go
+ suite.specs = [];
+ suite.suites = [];
+ suite.passed = true;
+ suite.parentId = this.suiteStack.slice(this.suiteStack.length -1)[0];
+ if (suite.parentId) {
+ this.suites[suite.parentId].suites.push(suite);
+ } else {
+ this.rootSuites.push(suite.id);
+ }
+ this.suiteStack.push(suite.id);
+ suite.timer = new Timer().start();
+ };
+
+ JSR.suiteDone = function (suite) {
+ suite = this._cacheSuite(suite);
+ suite.duration = suite.timer.elapsed();
+ suite.durationSec = suite.duration / 1000;
+ this.suiteStack.pop();
+
+ // maintain parent suite state
+ var parent = this.suites[suite.parentId];
+ if (parent) {
+ parent.passed = parent.passed && suite.passed;
+ }
+
+ // keep report representation clean
+ delete suite.timer;
+ delete suite.id;
+ delete suite.parentId;
+ delete suite.fullName;
+ };
+
+ JSR.specStarted = function (spec) {
+ spec = this._cacheSpec(spec);
+ spec.timer = new Timer().start();
+ // build up suites->spec tree as we go
+ spec.suiteId = this.suiteStack.slice(this.suiteStack.length -1)[0];
+ this.suites[spec.suiteId].specs.push(spec);
+ };
+
+ JSR.specDone = function (spec) {
+ spec = this._cacheSpec(spec);
+
+ spec.duration = spec.timer.elapsed();
+ spec.durationSec = spec.duration / 1000;
+
+ spec.skipped = spec.status === 'pending';
+ spec.passed = spec.skipped || spec.status === 'passed';
+
+ // totalCount and passedCount will be populated if/when jasmine#575 gets accepted
+ spec.totalCount = spec.totalExpectations || 0;
+ spec.passedCount = spec.passedExpectations ? spec.passedExpectations.length : 0;
+
+ spec.failedCount = spec.failedExpectations.length;
+ spec.failures = [];
+
+ for (var i = 0, j = spec.failedExpectations.length; i < j; i++) {
+ var fail = spec.failedExpectations[i];
+ spec.failures.push({
+ type: 'expect',
+ expected: fail.expected,
+ passed: false,
+ message: fail.message,
+ matcherName: fail.matcherName,
+ trace: {
+ stack: fail.stack
+ }
+ });
+ }
+
+ // maintain parent suite state
+ var parent = this.suites[spec.suiteId];
+ if (spec.failed) {
+ parent.failingSpecs.push(spec);
+ }
+ parent.passed = parent.passed && spec.passed;
+
+ // keep report representation clean
+ delete spec.timer;
+ delete spec.totalExpectations;
+ delete spec.passedExpectations;
+ delete spec.suiteId;
+ delete spec.fullName;
+ delete spec.id;
+ delete spec.status;
+ delete spec.failedExpectations;
+ };
+
+ JSR.jasmineDone = function () {
+ this._buildReport();
+ };
+
+ JSR.getJSReport = function () {
+ if (jasmine.jsReport) {
+ return jasmine.jsReport;
+ }
+ };
+
+ JSR.getJSReportAsString = function () {
+ if (jasmine.jsReport) {
+ return JSON.stringify(jasmine.jsReport);
+ }
+ };
+
+ // Private methods
+ // ---------------
+
+ JSR._haveSpec = function (spec) {
+ return this.specs[spec.id] != null;
+ };
+
+ JSR._cacheSpec = function (spec) {
+ var existing = this.specs[spec.id];
+ if (existing == null) {
+ existing = this.specs[spec.id] = _clone(spec);
+ } else {
+ _extend(existing, spec);
+ }
+ return existing;
+ };
+
+ JSR._haveSuite = function (suite) {
+ return this.suites[suite.id] != null;
+ };
+
+ JSR._cacheSuite = function (suite) {
+ var existing = this.suites[suite.id];
+ if (existing == null) {
+ existing = this.suites[suite.id] = _clone(suite);
+ } else {
+ _extend(existing, suite);
+ }
+ return existing;
+ };
+
+ JSR._buildReport = function () {
+ var overallDuration = 0;
+ var overallPassed = true;
+ var overallSuites = [];
+
+ for (var i = 0, j = this.rootSuites.length; i < j; i++) {
+ var suite = this.suites[this.rootSuites[i]];
+ overallDuration += suite.duration;
+ overallPassed = overallPassed && suite.passed;
+ overallSuites.push(suite);
+ }
+
+ jasmine.jsReport = {
+ passed: overallPassed,
+ durationSec: overallDuration / 1000,
+ suites: overallSuites
+ };
+ };
+
+})(jasmine);
+
+jasmine.getEnv().addReporter(new jasmine.JSReporter2());