Skip to content

Commit c1aa987

Browse files
kukulichFagnerMartinsBrack
authored andcommitted
Allow undocumented attributes to be passed when creating a cookie
Closes js-cookiegh-293
1 parent 4e77d05 commit c1aa987

File tree

4 files changed

+68
-19
lines changed

4 files changed

+68
-19
lines changed

src/js.cookie.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
attributes.expires = expires;
5757
}
5858

59+
// We're using "expires" because "max-age" is not supported by IE
60+
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
61+
5962
try {
6063
result = JSON.stringify(value);
6164
if (/^[\{\[]/.test(result)) {
@@ -74,13 +77,19 @@
7477
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
7578
key = key.replace(/[\(\)]/g, escape);
7679

77-
return (document.cookie = [
78-
key, '=', value,
79-
attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
80-
attributes.path ? '; path=' + attributes.path : '',
81-
attributes.domain ? '; domain=' + attributes.domain : '',
82-
attributes.secure ? '; secure' : ''
83-
].join(''));
80+
var stringifiedAttributes = '';
81+
82+
for (var attributeName in attributes) {
83+
if (!attributes[attributeName]) {
84+
continue;
85+
}
86+
stringifiedAttributes += '; ' + attributeName;
87+
if (attributes[attributeName] === true) {
88+
continue;
89+
}
90+
stringifiedAttributes += '=' + attributes[attributeName];
91+
}
92+
return (document.cookie = key + '=' + value + stringifiedAttributes);
8493
}
8594

8695
// Read

test/.jshintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"unescape": true,
1212
"lifecycle": true,
1313
"using": true,
14+
"quoted": true,
1415
"addEvent": true,
1516
"loadFileSync": true
1617
}

test/tests.js

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,31 +182,46 @@ QUnit.test('expires option as days from now', function (assert) {
182182
assert.expect(1);
183183
var sevenDaysFromNow = new Date();
184184
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 21);
185-
var expected = 'c=v; expires=' + sevenDaysFromNow.toUTCString();
186-
var actual = Cookies.set('c', 'v', { expires: 21 }).substring(0, expected.length);
187-
assert.strictEqual(actual, expected, 'should write the cookie string with expires');
185+
var expected = 'expires=' + sevenDaysFromNow.toUTCString();
186+
var actual = Cookies.set('c', 'v', { expires: 21 });
187+
assert.ok(actual.indexOf(expected) !== -1, quoted(actual) + ' includes ' + quoted(expected));
188188
});
189189

190+
// github.com/carhartl/jquery-cookie/issues/246
190191
QUnit.test('expires option as fraction of a day', function (assert) {
191192
assert.expect(1);
192193

193-
var now = new Date().getTime();
194-
var stringifiedDate = Cookies.set('c', 'v', { expires: 0.5 }).split('; ')[1].split('=')[1];
195-
var expires = Date.parse(stringifiedDate);
194+
var findValueForAttributeName = function (createdCookie, attributeName) {
195+
var pairs = createdCookie.split('; ');
196+
var foundAttributeValue;
197+
pairs.forEach(function (pair) {
198+
if (pair.split('=')[0] === attributeName) {
199+
foundAttributeValue = pair.split('=')[1];
200+
}
201+
});
202+
return foundAttributeValue;
203+
};
204+
var now = new Date();
205+
var stringifiedDate = findValueForAttributeName(Cookies.set('c', 'v', { expires: 0.5 }), 'expires');
206+
var expires = new Date(stringifiedDate);
196207

197208
// When we were using Date.setDate() fractions have been ignored
198209
// and expires resulted in the current date. Allow 1000 milliseconds
199-
// difference for execution time.
200-
assert.ok(expires > now + 1000, 'should write expires attribute with the correct date');
210+
// difference for execution time because new Date() can be different,
211+
// even when it's run synchronously.
212+
// See https://github.com/js-cookie/js-cookie/commit/ecb597b65e4c477baa2b30a2a5a67fdaee9870ea#commitcomment-20146048.
213+
var assertion = expires.getTime() > now.getTime() + 1000;
214+
var message = quoted(expires.getTime()) + ' should be greater than ' + quoted(now.getTime());
215+
assert.ok(assertion, message);
201216
});
202217

203218
QUnit.test('expires option as Date instance', function (assert) {
204219
assert.expect(1);
205220
var sevenDaysFromNow = new Date();
206221
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7);
207-
var expected = 'c=v; expires=' + sevenDaysFromNow.toUTCString();
208-
var actual = Cookies.set('c', 'v', { expires: sevenDaysFromNow }).substring(0, expected.length);
209-
assert.strictEqual(actual, expected, 'should write the cookie string with expires');
222+
var expected = 'expires=' + sevenDaysFromNow.toUTCString();
223+
var actual = Cookies.set('c', 'v', { expires: sevenDaysFromNow });
224+
assert.ok(actual.indexOf(expected) !== -1, quoted(actual) + ' includes ' + quoted(expected));
210225
});
211226

212227
QUnit.test('return value', function (assert) {
@@ -235,6 +250,13 @@ QUnit.test('API for changing defaults', function (assert) {
235250
assert.ok(Cookies.set('c', 'v').match(/path=\//), 'should roll back to the default path');
236251
});
237252

253+
QUnit.test('true secure value', function (assert) {
254+
assert.expect(1);
255+
var expected = 'c=v; path=/; secure';
256+
var actual = Cookies.set('c', 'v', {secure: true});
257+
assert.strictEqual(actual, expected, 'should add secure attribute');
258+
});
259+
238260
// github.com/js-cookie/js-cookie/pull/54
239261
QUnit.test('false secure value', function (assert) {
240262
assert.expect(1);
@@ -243,8 +265,18 @@ QUnit.test('false secure value', function (assert) {
243265
assert.strictEqual(actual, expected, 'false should not modify path in cookie string');
244266
});
245267

268+
// github.com/js-cookie/js-cookie/issues/276
269+
QUnit.test('unofficial attribute', function (assert) {
270+
assert.expect(1);
271+
var expected = 'c=v; path=/; unofficial=anything';
272+
var actual = Cookies.set('c', 'v', {
273+
unofficial: 'anything'
274+
});
275+
assert.strictEqual(expected, actual, 'should write the cookie string with unofficial attribute');
276+
});
277+
246278
QUnit.test('undefined attribute value', function (assert) {
247-
assert.expect(4);
279+
assert.expect(5);
248280
assert.strictEqual(Cookies.set('c', 'v', {
249281
expires: undefined
250282
}), 'c=v; path=/', 'should not write undefined expires attribute');
@@ -257,6 +289,9 @@ QUnit.test('undefined attribute value', function (assert) {
257289
assert.strictEqual(Cookies.set('c', 'v', {
258290
secure: undefined
259291
}), 'c=v; path=/', 'should not write undefined secure attribute');
292+
assert.strictEqual(Cookies.set('c', 'v', {
293+
unofficial: undefined
294+
}), 'c=v; path=/', 'should not write undefined unofficial attribute');
260295
});
261296

262297
QUnit.module('remove', lifecycle);

test/utils.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,8 @@
119119
return xhr.status === 200 ? xhr.responseText : null;
120120
};
121121

122+
window.quoted = function (input) {
123+
return '"' + input + '"';
124+
};
125+
122126
}());

0 commit comments

Comments
 (0)