Skip to content

Commit

Permalink
Allow options when deleting cookies (#48)
Browse files Browse the repository at this point in the history
* Allow options when deleting cookie

When using `.clear(COOKIE_NAME}`, there should be a way to specify options such as "path" and "domain". Otherwise a cookie might persist if you try to delete it from a different route than the one you set it on.

I believe the most common use case is that, after the user logs in, you want to set a cookie which persists on every route (therefore specifying "/" as the path). Then, if you log out, you need to specify the path "/" for the cookie if you log out from a route that's not "/".

* Add tests for `clear` options

* Update README for `clear` options
  • Loading branch information
bdelaforest authored and marcoow committed Feb 23, 2017
1 parent 508ade1 commit e573c21
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ The `cookies` service has methods for reading and writing cookies:
`String`.
* `write(name, value, options = {})`: writes a cookie with the given name and
value; options can be used to set `domain`, `expires`, `path` and `secure`.
* `clear(name)`: clears the cookie so that future reads do not return a value
* `clear(name)`: clears the cookie so that future reads do not return a value;
options can be used to specify `domain`, `path` or `secure`.

## License

Expand Down
7 changes: 5 additions & 2 deletions addon/services/cookies.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ export default Service.extend({
}
},

clear(name) {
this.write(name, null, { expires: new Date('1970-01-01') });
clear(name, options = {}) {
assert('Expires or Max-Age options cannot be set when clearing cookies', isEmpty(options.expires) && isEmpty(options.maxAge));

options.expires = new Date('1970-01-01');
this.write(name, null, options);
},

_writeDocumentCookie(name, value, options = {}) {
Expand Down
130 changes: 128 additions & 2 deletions tests/unit/services/cookies-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ describe('CookiesService', function() {
});
}

function itValidatesClearOptions() {
it('throws when the expires option is set', function() {
expect(() => {
this.subject().clear(COOKIE_NAME, 'test', { expires: new Date() });
}).to.throw();
});

it('throws when the max-age option is set', function() {
expect(() => {
this.subject().clear(COOKIE_NAME, 'test', { maxAge: 1000 });
}).to.throw();
});
}

function itReadsAfterWrite() {
it('reads a cookie that was just written', function() {
let value = randomString();
Expand Down Expand Up @@ -227,6 +241,8 @@ describe('CookiesService', function() {
});

describe('clearing a cookie', function() {
itValidatesClearOptions.apply(this);

it('clears the cookie', function() {
let value = randomString();
document.cookie = `${COOKIE_NAME}=${value};`;
Expand All @@ -235,7 +251,60 @@ describe('CookiesService', function() {

this.subject().clear(COOKIE_NAME);

expect(this.subject().read(COOKIE_NAME)).to.eq(undefined);
expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

describe('with a path option', function() {
it('clears the cookie set without path', function() {
let value = randomString();
let pathname = window.location.pathname;
let path = pathname.substring(0, pathname.lastIndexOf('/'));
this.subject().write(COOKIE_NAME, value);

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { path });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

it('clears the cookie set for a given path', function() {
let path = '/';
let value = randomString();
this.subject().write(COOKIE_NAME, value, { path });

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { path });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});
});

describe('with a domain option', function() {
it('clears the cookie set without domain', function() {
let domain = window.location.hostname;
let value = randomString();
this.subject().write(COOKIE_NAME, value);

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { domain });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

it('clears the cookie set for a given domain', function() {
let domain = window.location.hostname;
let value = randomString();
this.subject().write(COOKIE_NAME, value, { domain });

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { domain });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});
});
});

Expand Down Expand Up @@ -453,6 +522,8 @@ describe('CookiesService', function() {
});

describe('clearing a cookie', function() {
itValidatesClearOptions.apply(this);

it('clears the cookie', function() {
let value = randomString();
this.subject().write(COOKIE_NAME, value);
Expand All @@ -461,7 +532,62 @@ describe('CookiesService', function() {

this.subject().clear(COOKIE_NAME);

expect(this.subject().read(COOKIE_NAME)).to.eq(undefined);
expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

describe('with a path option', function() {
it('clears the cookie set without path', function() {
this.fakeFastBoot.request.path = '/path';
let value = randomString();
this.subject().write(COOKIE_NAME, value);

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { path: '/path' });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

it('clears the cookie set for a given path', function() {
let path = '/path';
this.fakeFastBoot.request.path = path;
let value = randomString();
this.subject().write(COOKIE_NAME, value, { path });

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { path });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});
});

describe('with a domain option', function() {
it('clears the cookie set without domain', function() {
let domain = 'example.com';
this.fakeFastBoot.request._host = domain;
let value = randomString();
this.subject().write(COOKIE_NAME, value);

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { domain });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});

it('clears the cookie set for a given domain', function() {
let domain = 'example.com';
this.fakeFastBoot.request._host = domain;
let value = randomString();
this.subject().write(COOKIE_NAME, value, { domain });

expect(this.subject().read(COOKIE_NAME)).to.eq(value);

this.subject().clear(COOKIE_NAME, { domain });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});
});
});

Expand Down

0 comments on commit e573c21

Please sign in to comment.