Skip to content

Commit 5ea864e

Browse files
jjl014sblaurock
andauthored
[CSL 24] Use exisiting data from cookie/local storage if it exists (#16)
* Initial implementation, passses all tests * Add/update tests * Lint fixes * Add/Update specs * Consistent casing. Co-authored-by: Steve Blaurock <[email protected]>
1 parent ea6f88f commit 5ea864e

File tree

5 files changed

+186
-61
lines changed

5 files changed

+186
-61
lines changed

spec/001-initialization.js

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ describe('ConstructorioID', function () {
1313
'generate_client_id',
1414
'get_local_object',
1515
'set_local_object',
16+
'delete_local_object',
1617
'generate_session_id'
1718
];
1819
expect(actualKeys).to.eql(expectedKeys);
@@ -97,26 +98,38 @@ describe('ConstructorioID', function () {
9798
expect(session.client_id).to.match(/(\w|d|-){36}/);
9899
});
99100

100-
it('should read the client id from local storage if storage location is set to local', function () {
101-
window.localStorage.setItem('dummyname', 'dummyid');
102-
var session = new ConstructorioID({ local_name_client_id: 'dummyname', client_id_storage_location: 'local' } );
103-
expect(session.client_id).to.equal('dummyid');
104-
expect(window.localStorage.getItem('dummyname')).to.equal('dummyid');
105-
});
101+
describe('when the storage location is set to local', function () {
102+
it('should read the client id from local storage', function () {
103+
window.localStorage.setItem('dummyname', 'dummyid');
104+
var session = new ConstructorioID({ local_name_client_id: 'dummyname', client_id_storage_location: 'local' } );
105+
expect(session.client_id).to.equal('dummyid');
106+
expect(window.localStorage.getItem('dummyname')).to.equal('dummyid');
107+
});
106108

107-
it('should read the client id from the default local storage name and storage location is set to local', function () {
108-
window.localStorage.setItem('_constructorio_search_client_id', 'bummyid');
109-
var session = new ConstructorioID({ client_id_storage_location: 'local' });
110-
expect(session.client_id).to.equal('bummyid');
111-
expect(window.localStorage.getItem('_constructorio_search_client_id')).to.equal('bummyid');
112-
});
109+
it('should read the client id from the default local storage name', function () {
110+
window.localStorage.setItem('_constructorio_search_client_id', 'bummyid');
111+
var session = new ConstructorioID({ client_id_storage_location: 'local' });
112+
expect(session.client_id).to.equal('bummyid');
113+
expect(window.localStorage.getItem('_constructorio_search_client_id')).to.equal('bummyid');
114+
});
113115

114-
it('should set the client id if missing and storage location is set to local', function () {
115-
var session = new ConstructorioID({ cookie_name_client_id: 'missingname', client_id_storage_location: 'local' });
116-
expect(session.client_id).to.be.a.string;
117-
expect(session.client_id).to.match(/(\w|d|-){36}/);
116+
it('should read the client id from cookies if it does not exist in local storage and remove it from the cookies', function () {
117+
document.cookie = 'ConstructorioID_client_id=chummyid; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/';
118+
var session = new ConstructorioID({ client_id_storage_location: 'local' });
119+
var cookieData = JSON.parse(helper.getCookie('ConstructorioID_client_id'));
120+
expect(session.client_id).to.equal('chummyid');
121+
expect(window.localStorage.getItem('_constructorio_search_client_id')).to.equal('chummyid');
122+
expect(cookieData).to.equal(null);
123+
});
124+
125+
it('should set the client id if missing from both local storage and cookies', function () {
126+
var session = new ConstructorioID({ client_id_storage_location: 'local' });
127+
expect(session.client_id).to.be.a.string;
128+
expect(session.client_id).to.match(/(\w|d|-){36}/);
129+
});
118130
});
119131

132+
120133
it('should read the session id from local storage data', function () {
121134
window.localStorage.setItem('_constructorio_search_session', JSON.stringify({
122135
sessionId: 42,
@@ -183,17 +196,39 @@ describe('ConstructorioID', function () {
183196
expect(session.session_id).to.equal(1);
184197
});
185198

186-
it('should read the session id from cookie if storage location is set to cookie', function () {
187-
document.cookie = `ConstructorioID_session={"sessionId":42,"lastTime":${Date.now()}}; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/`;
188-
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
189-
expect(session.session_id).to.be.a('number');
190-
expect(session.session_id).to.equal(42);
191-
});
199+
describe('when the storage location is set to cookie', function () {
200+
it('should read the session id from cookie', function () {
201+
document.cookie = `ConstructorioID_session={"sessionId":42,"lastTime":${Date.now()}}; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/`;
202+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
203+
expect(session.session_id).to.be.a('number');
204+
expect(session.session_id).to.equal(42);
205+
});
192206

193-
it('should set the session id to 1 if there is no cookie and storage location is set to cookie', function () {
194-
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
195-
expect(session.session_id).to.be.a('number');
196-
expect(session.session_id).to.equal(1);
207+
it('should read the session id from the default cookie name', function () {
208+
document.cookie = `ConstructorioID_session={"sessionId":42,"lastTime":${Date.now()}}; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/`;
209+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
210+
var cookieData = JSON.parse(helper.getCookie('ConstructorioID_session'));
211+
expect(session.session_id).to.equal(42);
212+
expect(cookieData.sessionId).to.equal(42);
213+
});
214+
215+
it('should read the session id from local storage if there is no cookie and remove it from local storage', function () {
216+
window.localStorage.setItem('_constructorio_search_session', JSON.stringify({
217+
sessionId: '11',
218+
lastTime: Date.now()
219+
}));
220+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' } );
221+
var cookieData = JSON.parse(helper.getCookie('ConstructorioID_session'));
222+
expect(window.localStorage.getItem('_constructorio_search_session')).to.equal(null);
223+
expect(session.session_id).to.equal(11);
224+
expect(cookieData.sessionId).to.equal(11);
225+
});
226+
227+
it('should set the session id to 1 if missing from both local storage and cookies', function () {
228+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' } );
229+
expect(session.session_id).to.be.a('number');
230+
expect(session.session_id).to.equal(1);
231+
});
197232
});
198233

199234
it('should set the session id if cookie data can be parsed into a number', function () {

spec/005-storage.js

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,45 @@ describe('ConstructorioID', function () {
130130
set_cookie.restore();
131131
});
132132

133+
describe('when the storage location is set to cookie', function () {
134+
it('should use session id from local storage if there is no cookie and increment if older than thirty minutes', function () {
135+
var now = Date.now();
136+
window.localStorage.setItem('_constructorio_search_session', JSON.stringify({ sessionId: 42, lastTime: `${now - 1000 * 60 * 30}` }));
137+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
138+
139+
var set_cookie = sinon.spy(ConstructorioID.prototype, 'set_cookie');
140+
var session_id = session.generate_session_id();
141+
expect(session_id).to.be.a('number');
142+
expect(session_id).to.equal(43);
143+
expect(set_cookie.calledTwice).to.be.true;
144+
expect(set_cookie.calledWith('ConstructorioID_session_id')).to.be.true;
145+
expect(set_cookie.calledWith('ConstructorioID_session')).to.be.true;
146+
expect(JSON.parse(set_cookie.getCall(0).args[1])).to.equal(43);
147+
expect(JSON.parse(set_cookie.getCall(1).args[1]).sessionId).to.equal(43);
148+
expect(JSON.parse(set_cookie.getCall(1).args[1]).lastTime).to.be.at.least(now);
149+
150+
set_cookie.restore();
151+
});
152+
153+
it('should set a session id in cookie if missing from both local storage and cookie', function () {
154+
var now = Date.now();
155+
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
156+
document.cookie = '';
157+
158+
var set_cookie = sinon.spy(ConstructorioID.prototype, 'set_cookie');
159+
var session_id = session.generate_session_id();
160+
expect(session_id).to.be.a('number');
161+
expect(session_id).to.equal(1);
162+
expect(set_cookie.calledTwice).to.be.true;
163+
expect(set_cookie.calledWith('ConstructorioID_session_id')).to.be.true;
164+
expect(set_cookie.calledWith('ConstructorioID_session')).to.be.true;
165+
expect(JSON.parse(set_cookie.getCall(0).args[1])).to.equal(1);
166+
expect(JSON.parse(set_cookie.getCall(1).args[1]).sessionId).to.equal(1);
167+
expect(JSON.parse(set_cookie.getCall(1).args[1]).lastTime).to.be.at.least(now);
168+
set_cookie.restore();
169+
});
170+
});
171+
133172
it('should set a session id in local storage if missing', function () {
134173
var now = Date.now();
135174
var session = new ConstructorioID();
@@ -147,23 +186,5 @@ describe('ConstructorioID', function () {
147186
expect(set_local_object.getCall(1).args[1].lastTime).to.be.at.least(now);
148187
set_local_object.restore();
149188
});
150-
151-
it('should set a session id in cookie if missing and storage location is set to cookie', function () {
152-
var now = Date.now();
153-
var session = new ConstructorioID({ session_id_storage_location: 'cookie' });
154-
document.cookie = '';
155-
156-
var set_cookie = sinon.spy(ConstructorioID.prototype, 'set_cookie');
157-
var session_id = session.generate_session_id();
158-
expect(session_id).to.be.a('number');
159-
expect(session_id).to.equal(1);
160-
expect(set_cookie.calledTwice).to.be.true;
161-
expect(set_cookie.calledWith('ConstructorioID_session_id')).to.be.true;
162-
expect(set_cookie.calledWith('ConstructorioID_session')).to.be.true;
163-
expect(JSON.parse(set_cookie.getCall(0).args[1])).to.equal(1);
164-
expect(JSON.parse(set_cookie.getCall(1).args[1]).sessionId).to.equal(1);
165-
expect(JSON.parse(set_cookie.getCall(1).args[1]).lastTime).to.be.at.least(now);
166-
set_cookie.restore();
167-
});
168189
});
169190
});

spec/006-cookies.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ describe('ConstructorioID', function () {
6666
expect(client_id).to.match(/(\w|d|-){36}/);
6767
});
6868

69-
it('should return a client id and set local storage value if storage location is set to local', function () {
70-
var session = new ConstructorioID({ local_name_client_id: 'monster', client_id_storage_location: 'local' });
71-
var client_id = session.generate_client_id();
72-
expect(session.get_local_object('monster')).to.equal(client_id);
73-
expect(client_id).to.be.a.string;
74-
expect(client_id).to.match(/(\w|d|-){36}/);
69+
describe('when the storage location is set to local', function () {
70+
it('should return a client id and set local storage value', function () {
71+
var session = new ConstructorioID({ local_name_client_id: 'monster', client_id_storage_location: 'local' });
72+
var client_id = session.generate_client_id();
73+
expect(session.get_local_object('monster')).to.equal(client_id);
74+
expect(client_id).to.be.a.string;
75+
expect(client_id).to.match(/(\w|d|-){36}/);
76+
});
77+
78+
it('should use client id from cookies if the data is not available in local storage', function () {
79+
document.cookie = 'ConstructorioID_client_id=chummyid; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/';
80+
var session = new ConstructorioID({ client_id_storage_location: 'local' });
81+
expect(session.get_local_object('_constructorio_search_client_id')).to.equal('chummyid');
82+
});
7583
});
7684
});
7785
});

spec/helper.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ function getStorageMock() {
1414
};
1515
}
1616

17+
/*
18+
* Returns a value given the cookie name
19+
*/
20+
function getCookie(name) {
21+
var re = new RegExp(name + '=([^;]+)');
22+
var value = re.exec(document.cookie);
23+
return (value !== null) ? unescape(value[1]) : null;
24+
}
25+
1726
module.exports = {
18-
getStorageMock: getStorageMock
27+
getStorageMock: getStorageMock,
28+
getCookie: getCookie
1929
};

src/constructorio-id.js

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,43 @@
9191
};
9292

9393
ConstructorioID.prototype.generate_client_id = function () {
94-
var client_id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
95-
var r = Math.random() * 16 | 0;
96-
var v = c === 'x' ? r : (r & 0x3 | 0x8);
97-
return v.toString(16);
98-
});
99-
100-
if (this.client_id_storage_location === 'cookie') {
101-
this.set_cookie(this.cookie_name_client_id, client_id);
94+
var client_id;
95+
96+
if (!this.on_node) {
97+
var cookie_persisted_client_id = this.get_cookie(this.cookie_name_client_id);
98+
var local_persisted_client_id = this.get_local_object(this.local_name_client_id);
99+
100+
if (this.client_id_storage_location === 'cookie') {
101+
if (local_persisted_client_id) {
102+
client_id = local_persisted_client_id;
103+
this.set_cookie(this.cookie_name_client_id, client_id);
104+
this.delete_local_object(this.local_name_client_id);
105+
}
106+
}
107+
108+
if (this.client_id_storage_location === 'local') {
109+
if (cookie_persisted_client_id) {
110+
client_id = cookie_persisted_client_id;
111+
this.set_local_object(this.local_name_client_id, client_id);
112+
this.delete_cookie(this.cookie_name_client_id);
113+
}
114+
}
102115
}
103116

104-
if (this.client_id_storage_location === 'local') {
105-
this.set_local_object(this.local_name_client_id, client_id);
117+
if (!client_id) {
118+
client_id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
119+
var r = Math.random() * 16 | 0;
120+
var v = c === 'x' ? r : (r & 0x3 | 0x8);
121+
return v.toString(16);
122+
});
123+
124+
if (this.client_id_storage_location === 'cookie') {
125+
this.set_cookie(this.cookie_name_client_id, client_id);
126+
}
127+
128+
if (this.client_id_storage_location === 'local') {
129+
this.set_local_object(this.local_name_client_id, client_id);
130+
}
106131
}
107132

108133
return client_id;
@@ -143,13 +168,33 @@
143168
}
144169
};
145170

171+
ConstructorioID.prototype.delete_local_object = function (key) {
172+
var localStorage = window && window.localStorage;
173+
174+
if (localStorage && typeof key === 'string') {
175+
try {
176+
localStorage.removeItem(key);
177+
} catch (e) {
178+
// fail silently
179+
}
180+
}
181+
};
182+
146183
ConstructorioID.prototype.generate_session_id = function () {
184+
var cookie_persisted_session_data = this.get_cookie(this.cookie_name_session_data);
185+
var local_persisted_session_data = this.get_local_object(this.local_name_session_data);
147186
var now = Date.now();
148187
var thirtyMinutes = 1000 * 60 * 30;
149188
var sessionData;
150189

151190
if (this.session_id_storage_location === 'local') {
152191
sessionData = this.get_local_object(this.local_name_session_data);
192+
193+
if (!sessionData && cookie_persisted_session_data) {
194+
sessionData = cookie_persisted_session_data;
195+
196+
this.delete_cookie(this.cookie_name_session_data);
197+
}
153198
}
154199

155200
if (this.session_id_storage_location === 'cookie') {
@@ -160,6 +205,12 @@
160205
} catch (e) {
161206
// fail silently
162207
}
208+
209+
if (!sessionData && local_persisted_session_data) {
210+
sessionData = local_persisted_session_data;
211+
212+
this.delete_local_object(this.local_name_session_data);
213+
}
163214
}
164215

165216
var sessionId = 1;

0 commit comments

Comments
 (0)