diff --git a/src/js/plugins/plugin.resume.js b/src/js/plugins/plugin.resume.js index 3f03ccfb1..5119ef3ea 100644 --- a/src/js/plugins/plugin.resume.js +++ b/src/js/plugins/plugin.resume.js @@ -28,7 +28,7 @@ BookReader.prototype.init = (function(super_) { })(BookReader.prototype.init); /** - * Get's the page resume value, for remembering reader's page + * Gets page resume value, for remembering reader's page * Can be overriden for different implementation * * @return {number|null} @@ -40,7 +40,19 @@ BookReader.prototype.getResumeValue = function() { } /** - * Set's the page resume value, for remembering reader's page + * Return cookie path using pathname up to /page/... or /mode/... + * using window.location.pathname for urlPathPart: + * - matches encoding + * - ignores querystring part + * - ignores fragment part (after #) + * @param {string} urlPathPart - window.location.pathname + */ +BookReader.prototype.getCookiePath = function(urlPathPart) { + return urlPathPart.match('.+?(?=/page/|/mode/|$)')[0]; +} + +/** + * Sets page resume value, for remembering reader's page * Can be overriden for different implementation * * @param {Number} index leaf index @@ -48,6 +60,9 @@ BookReader.prototype.getResumeValue = function() { */ BookReader.prototype.updateResumeValue = function(index, cookieName) { const ttl = new Date(+new Date + 12096e5); // 2 weeks - const path = this.options.resumeCookiePath || window.location.pathname; + // For multiple files in item, leave resumeCookiePath blank + // It's likely we can remove resumeCookiePath using getCookiePath() + const path = this.options.resumeCookiePath + || this.getCookiePath(window.location.pathname); BookReader.docCookies.setItem(cookieName || 'br-resume', index, ttl, path, null, false); -} +} \ No newline at end of file diff --git a/tests/plugins/plugin.resume.test.js b/tests/plugins/plugin.resume.test.js index 08e65f60b..1a8621efa 100644 --- a/tests/plugins/plugin.resume.test.js +++ b/tests/plugins/plugin.resume.test.js @@ -66,11 +66,40 @@ describe('updateResumeValue', () => { }); test('handles resumeCookiePath not set', () => { - const { updateResumeValue } = BookReader.prototype; const setItemSpy = sinon.spy(docCookies, 'setItem'); - const fakeBr = { options: { } }; + // Save function + const saveFn = br.getCookiePath; + br.getCookiePath = jest.fn(() => '/details/foo'); + br.updateResumeValue(16); + expect(setItemSpy.args[0][3]).toEqual('/details/foo'); + // Restore function + br.getCookiePath = saveFn; + }); - updateResumeValue.call(fakeBr, 16); - expect(setItemSpy.args[0][3]).toEqual('/'); + test('handles cookie path from URL with decoration', () => { + const complexPathWithPage = '/details/2008ELMValidityStudyFinalReportRevised/Executive%20Summary%20for%20the%20EPT%26ELM%20Validity%20Studie_20100603%20-%20Copy/page/n1/mode/2up'; + const complexPath = '/details/2008ELMValidityStudyFinalReportRevised/Executive%20Summary%20for%20the%20EPT%26ELM%20Validity%20Studie_20100603%20-%20Copy'; + expect(br.getCookiePath(complexPathWithPage)) + .toEqual(complexPath); + + expect(br.getCookiePath('/details/item/mode/1up')) + .toEqual('/details/item'); + + expect(br.getCookiePath('/details/item/inside/a/long/path/model/is/used')) + .toEqual('/details/item/inside/a/long/path/model/is/used'); + + expect(br.getCookiePath('/details/item/inside/a/long/path/mode/is/used')) + .toEqual('/details/item/inside/a/long/path'); + }); + + test('handles cookie path from URL with no decoration', () => { + expect(br.getCookiePath('/details/item')) + .toEqual('/details/item'); + + expect(br.getCookiePath('/details/item/')) + .toEqual('/details/item/'); + + expect(br.getCookiePath('/details/item/almost/any/kind/of/long/path')) + .toEqual('/details/item/almost/any/kind/of/long/path'); }); });