Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix FastBoot cookie cache handling #24

Merged
merged 1 commit into from
Jun 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions addon/services/cookies.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ export default Ember.Service.extend({
}).volatile(),

_fastBootCookies: computed(function() {
let fastBootCookies = this.get('_fastBootCookiesCache');
let fastBootCookiesCache = this.get('_fastBootCookiesCache');

if (!fastBootCookies) {
fastBootCookies = this.get('_fastBoot.request.cookies');
this.set('_fastBootCookiesCache', fastBootCookies);
if (!fastBootCookiesCache) {
let fastBootCookies = this.get('_fastBoot.request.cookies');
fastBootCookiesCache = A(keys(fastBootCookies)).reduce((acc, name) => {
let value = fastBootCookies[name];
acc[name] = { value };
return acc;
}, {});
this.set('_fastBootCookiesCache', fastBootCookiesCache);
}

return this._filterCachedFastBootCookies(fastBootCookies);
return this._filterCachedFastBootCookies(fastBootCookiesCache);
}).volatile(),

read(name) {
Expand Down
104 changes: 26 additions & 78 deletions tests/unit/services/cookies-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ describeModule('service:cookies', 'CookiesService', {}, function() {
describe('reading a cookie', function() {
it('returns the cookie value', function() {
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = { value };
this.subject().write(COOKIE_NAME, value);

expect(this.subject().read(COOKIE_NAME)).to.eq(value);
});
Expand All @@ -268,74 +268,47 @@ describeModule('service:cookies', 'CookiesService', {}, function() {

it('returns undefined for a cookie that was written for another path', function() {
this.fakeFastBoot.request.path = '/path';
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value: 'value',
options: {
path: '/some-other-path'
}
};
let value = randomString();
this.subject().write(COOKIE_NAME, value, { path: '/some-other-path' });

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

it('returns the cookie value for a cookie that was written for the same path', function() {
this.fakeFastBoot.request.path = '/path';
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
path: '/path'
}
};
this.subject().write(COOKIE_NAME, value, { path: '/path' });

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

it('returns undefined for a cookie that was written for another domain', function() {
this.fakeFastBoot.request.host = 'example.com';
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value: 'value',
options: {
domain: 'another-domain.com'
}
};
let value = randomString();
this.subject().write(COOKIE_NAME, value, { domain: 'another-domain.com' });

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

it('returns the cookie value for a cookie that was written for the same domain', function() {
this.fakeFastBoot.request.host = 'example.com';
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
domain: 'example.com'
}
};
this.subject().write(COOKIE_NAME, value, { domain: 'example.com' });

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

it('returns the cookie value for a cookie that was written for a parent domain', function() {
this.fakeFastBoot.request.host = 'sub.example.com';
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
domain: 'example.com'
}
};
this.subject().write(COOKIE_NAME, value, { domain: 'example.com' });

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

it('returns undefined for an expired cookie', function() {
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value: 'value',
options: {
expires: new Date(-1)
}
};
let value = randomString();
this.subject().write(COOKIE_NAME, value, { expires: new Date(-1) });

expect(this.subject().read(COOKIE_NAME)).to.be.undefined;
});
Expand All @@ -344,54 +317,37 @@ describeModule('service:cookies', 'CookiesService', {}, function() {
let expirationDate = new Date();
expirationDate.setDate(new Date().getDate() + 1);
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
expires: expirationDate
}
};
this.subject().write(COOKIE_NAME, value, { expires: expirationDate });

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

it('returns undefined for a cookie that reached its max age', function() {
this.subject().write(COOKIE_NAME, 'value', { maxAge: -1 });
let value = randomString();
this.subject().write(COOKIE_NAME, value, { maxAge: -1 });

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

it('returns the cookie value for a cookie that has not yet reached its max age', function() {
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
maxAge: 99999999
}
};
this.subject().write(COOKIE_NAME, value, { maxAge: 99999999 });

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

it('returns undefined for a cookie that was written for another protocol (secure cookies vs. non-secure request)', function() {
this.fakeFastBoot.request.host = 'http';
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value: 'value',
options: {
secure: true
}
};
let value = randomString();
this.subject().write(COOKIE_NAME, value, { secure: true });

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

it('returns the cookie value for a cookie that was written for the same protocol', function() {
this.fakeFastBoot.request.protocol = 'https';
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = {
value,
options: {
secure: true
}
};
this.subject().write(COOKIE_NAME, value, { secure: true });

expect(this.subject().read(COOKIE_NAME)).to.eq(value);
});
Expand All @@ -402,94 +358,86 @@ describeModule('service:cookies', 'CookiesService', {}, function() {

it('writes the value', function() {
let value = randomString();
let subject = this.subject();

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=${value}`);
};

subject.write(COOKIE_NAME, value);
this.subject().write(COOKIE_NAME, value);
});

it('URI-component-encodes the value', function() {
let value = '!"§$%&/()=?"';
let encodedValue = encodeURIComponent(value);
let subject = this.subject();

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=${encodedValue}`);
};

subject.write(COOKIE_NAME, value);
this.subject().write(COOKIE_NAME, value);
});

it('sets the cookie domain', function() {
let domain = 'example.com';
let subject = this.subject();
this.fakeFastBoot.request.host = domain;

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=test; domain=${domain}`);
};

subject.write(COOKIE_NAME, 'test', { domain });
this.subject().write(COOKIE_NAME, 'test', { domain });
});

it('sets the expiration', function() {
let subject = this.subject();
let date = new Date();

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=test; expires=${date.toUTCString()}`);
};

subject.write(COOKIE_NAME, 'test', { expires: date });
this.subject().write(COOKIE_NAME, 'test', { expires: date });
});

it('sets the max age', function() {
let subject = this.subject();
let maxAge = 10;

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=test; max-age=${maxAge}`);
};

subject.write(COOKIE_NAME, 'test', { maxAge });
this.subject().write(COOKIE_NAME, 'test', { maxAge });
});

it('sets the secure flag', function() {
let subject = this.subject();

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=test; secure`);
};

subject.write(COOKIE_NAME, 'test', { secure: true });
this.subject().write(COOKIE_NAME, 'test', { secure: true });
});

it('sets the path', function() {
let subject = this.subject();
let path = '/sample-path';

this.fakeFastBoot.response.headers.append = function(headerName, headerValue) {
expect(headerName).to.equal('set-cookie');
expect(headerValue).to.equal(`${COOKIE_NAME}=test; path=${path}`);
};

subject.write(COOKIE_NAME, 'test', { path });
this.subject().write(COOKIE_NAME, 'test', { path });
});
});

describe('clearing a cookie', function() {
it('clears the cookie', function() {
let value = randomString();
this.fakeFastBoot.request.cookies[COOKIE_NAME] = { value };
this.subject().write(COOKIE_NAME, value);

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

Expand Down