-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: storage options, change priority or use custom
- Loading branch information
Showing
17 changed files
with
1,037 additions
and
616 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@segment/analytics-next': minor | ||
--- | ||
|
||
Adds storage option in analytics client to specify priority of storage (e.g use cookies over localstorage) or use a custom implementation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
packages/browser/src/core/storage/__tests__/cookieStorage.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { CookieStorage } from '../cookieStorage' | ||
import jar from 'js-cookie' | ||
import { disableCookies } from './test-helpers' | ||
|
||
describe('cookieStorage', () => { | ||
function clearCookies() { | ||
document.cookie.split(';').forEach(function (c) { | ||
document.cookie = c | ||
.replace(/^ +/, '') | ||
.replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/') | ||
}) | ||
} | ||
|
||
afterEach(() => { | ||
clearCookies() | ||
}) | ||
|
||
describe('#available', () => { | ||
afterEach(() => { | ||
jest.restoreAllMocks() | ||
}) | ||
|
||
it('is available', () => { | ||
const cookie = new CookieStorage() | ||
expect(cookie.available).toBe(true) | ||
}) | ||
|
||
it("is unavailable if can't write cookies", () => { | ||
disableCookies() | ||
const cookie = new CookieStorage() | ||
expect(cookie.available).toBe(false) | ||
}) | ||
}) | ||
|
||
describe('cookie options', () => { | ||
it('should have default cookie options', () => { | ||
const cookie = new CookieStorage() | ||
expect(cookie['options'].domain).toBe(undefined) | ||
expect(cookie['options'].maxage).toBe(365) | ||
expect(cookie['options'].path).toBe('/') | ||
expect(cookie['options'].sameSite).toBe('Lax') | ||
expect(cookie['options'].secure).toBe(undefined) | ||
}) | ||
|
||
it('should set options properly', () => { | ||
const cookie = new CookieStorage({ | ||
domain: 'foo', | ||
secure: true, | ||
path: '/test', | ||
}) | ||
expect(cookie['options'].domain).toBe('foo') | ||
expect(cookie['options'].secure).toBe(true) | ||
expect(cookie['options'].path).toBe('/test') | ||
expect(cookie['options'].secure).toBe(true) | ||
}) | ||
|
||
it('should pass options when creating cookie', () => { | ||
const jarSpy = jest.spyOn(jar, 'set') | ||
const cookie = new CookieStorage({ | ||
domain: 'foo', | ||
secure: true, | ||
path: '/test', | ||
}) | ||
|
||
cookie.set('foo', 'bar') | ||
|
||
expect(jarSpy).toHaveBeenCalledWith('foo', 'bar', { | ||
domain: 'foo', | ||
expires: 365, | ||
path: '/test', | ||
sameSite: 'Lax', | ||
secure: true, | ||
}) | ||
}) | ||
}) | ||
}) |
70 changes: 70 additions & 0 deletions
70
packages/browser/src/core/storage/__tests__/localStorage.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { LocalStorage } from '../localStorage' | ||
|
||
describe('LocalStorage', function () { | ||
let store: LocalStorage | ||
|
||
beforeEach(() => { | ||
jest.spyOn(console, 'warn').mockImplementation(() => {}) // silence console spam. | ||
store = new LocalStorage() | ||
}) | ||
|
||
afterEach(() => { | ||
localStorage.clear() | ||
}) | ||
|
||
describe('#get', function () { | ||
it('should return null if localStorage throws an error (or does not exist)', function () { | ||
const getItemSpy = jest | ||
.spyOn(global.Storage.prototype, 'getItem') | ||
.mockImplementationOnce(() => { | ||
throw new Error('getItem fail.') | ||
}) | ||
store.set('foo', 'some value') | ||
expect(store.get('foo')).toBeNull() | ||
expect(getItemSpy).toBeCalledTimes(1) | ||
}) | ||
|
||
it('should not get an empty record', function () { | ||
expect(store.get('abc')).toBe(null) | ||
}) | ||
|
||
it('should get an existing record', function () { | ||
store.set('x', { a: 'b' }) | ||
store.set('a', 'hello world') | ||
store.set('b', '') | ||
store.set('c', false) | ||
store.set('d', null) | ||
store.set('e', undefined) | ||
|
||
expect(store.get('x')).toStrictEqual({ a: 'b' }) | ||
expect(store.get('a')).toBe('hello world') | ||
expect(store.get('b')).toBe('') | ||
expect(store.get('c')).toBe(false) | ||
expect(store.get('d')).toBe(null) | ||
expect(store.get('e')).toBe('undefined') | ||
}) | ||
}) | ||
|
||
describe('#set', function () { | ||
it('should be able to set a record', function () { | ||
store.set('x', { a: 'b' }) | ||
expect(store.get('x')).toStrictEqual({ a: 'b' }) | ||
}) | ||
|
||
it('should catch localStorage quota exceeded errors', () => { | ||
const val = 'x'.repeat(10 * 1024 * 1024) | ||
store.set('foo', val) | ||
|
||
expect(store.get('foo')).toBe(null) | ||
}) | ||
}) | ||
|
||
describe('#clear', function () { | ||
it('should be able to remove a record', function () { | ||
store.set('x', { a: 'b' }) | ||
expect(store.get('x')).toStrictEqual({ a: 'b' }) | ||
store.clear('x') | ||
expect(store.get('x')).toBe(null) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.