Skip to content

Commit

Permalink
feat: correct the delete last one cookie value and format the cookie (#4
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wqcstrong committed May 31, 2023
1 parent aa199fb commit 059b777
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare module '*.svg' {

interface CookieChangeEvent extends Event {
changed: CookieStoreValue[];
deleted: CookieStoreValue[];
}
type OptionName = {
name: string;
Expand Down
48 changes: 34 additions & 14 deletions src/plugins/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,27 @@ export class StoragePlugin implements PageSpyPlugin {
});

if (window.cookieStore) {
const sendCookie = () => {
window.cookieStore.getAll().then((cookies) => {
cookies.forEach((cookie) => {
const data = { type: 'cookie', action: 'get', ...cookie } as Omit<
SpyStorage.DataItem,
'id'
>;
if (!data.domain) {
data.domain = window.location.hostname;
}
window.cookieStore.getAll().then((cookies) => {
cookies.forEach((cookie) => {
const data = StoragePlugin.formatCookieInfo(cookie);
sendStorageItem(data);
});
});
window.cookieStore.addEventListener('change', (e) => {
const { changed, deleted } = e as CookieChangeEvent;
if (changed.length > 0) {
changed.forEach((cookie) => {
const data = StoragePlugin.formatCookieInfo(cookie, 'set');
sendStorageItem(data);
});
});
};
sendCookie();
window.cookieStore.addEventListener('change', sendCookie);
}
if (deleted.length > 0) {
deleted.forEach((cookie) => {
const data = StoragePlugin.formatCookieInfo(cookie, 'remove');
sendStorageItem(data);
});
}
});
} else {
document.cookie.split('; ').forEach((item) => {
const [name, value] = item.split('=');
Expand All @@ -53,6 +58,21 @@ export class StoragePlugin implements PageSpyPlugin {
initStorageProxy();
}

private static formatCookieInfo(
cookie: CookieStoreValue,
action: SpyStorage.ActionType = 'get',
) {
const result: Omit<SpyStorage.DataItem, 'id'> = {
type: 'cookie',
action,
...cookie,
};
if (!result.domain) {
result.domain = window.location.hostname;
}
return result;
}

private static sendStorageItem(info: Omit<SpyStorage.DataItem, 'id'>) {
const data = makeMessage(DEBUG_MESSAGE_TYPE.STORAGE, info);
socketStore.broadcastMessage(data);
Expand Down
85 changes: 85 additions & 0 deletions tests/__mocks__/cookie-store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const initCookieStoreValue = (...args) => {
if (args.length > 2) {
throw new TypeError(`Expect 1 or 2 arguments, you passed ${args.length}.`);
}
const defaultValue = {
name: '',
value: '',
domain: null,
path: '',
partitioned: false,
secure: false,
sameSite: 'none',
expires: null,
};
if (typeof args[0] === 'string' && args.length === 2) {
return {
...defaultValue,
name: args[0],
value: args[1],
};
}
if (typeof args[0] === 'object') {
return {
...defaultValue,
...args[0],
};
}
throw new TypeError('Cannot handle the cookieStore arguments, please check.');
};

class CookieChangeEvent extends Event {
changed = [];
deleted = [];

constructor(type, data) {
super(type);
this.changed = data.changed;
this.deleted = data.deleted;
}
}

class CookieStore extends EventTarget {
mockStoreValue = [];

async getAll() {
// Mock value
return this.mockStoreValue;
}

async set(name, value) {
return new Promise((resolve) => {
const storeValue = initCookieStoreValue(name, value);
this.mockStoreValue.push(storeValue);
this.dispatchEvent(
new CookieChangeEvent('change', {
changed: [storeValue],
deleted: [],
}),
);
resolve();
});
}

async delete(name) {
const result = [];
const deleted = [];
this.mockStoreValue.forEach((item) => {
if (item.name === name) {
deleted.push(item);
} else {
result.push(item);
}
});
if (deleted.length === 0) return;
this.mockStoreValue = result;
this.dispatchEvent(
new CookieChangeEvent('change', {
changed: [],
deleted,
}),
);
}
}

window.cookieStore = new CookieStore();
33 changes: 22 additions & 11 deletions tests/plugins/storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
import { StoragePlugin } from 'src/plugins/storage';

const trigger = jest.fn();
// @ts-ignore
jest.spyOn(StoragePlugin, 'sendStorageItem').mockImplementation(trigger);
const trigger = jest.spyOn(StoragePlugin, 'sendStorageItem');

beforeEach(() => {
localStorage.clear();
sessionStorage.clear();
document.cookie = '';
});
afterEach(() => {
jest.restoreAllMocks();
});

describe('Storage plugin', () => {
it('Storage action', () => {
localStorage.setItem('1', '1');
sessionStorage.setItem('2', '2');
document.cookie = '3=3';
it('cookieStore / localStorage /sessionStorage', async () => {
new StoragePlugin().onCreated();
await cookieStore.set('1', '1');
await cookieStore.set('2', '2');
expect(trigger).toHaveBeenCalledTimes(3);

localStorage.removeItem('1');
sessionStorage.removeItem('1');
await cookieStore.delete('1');
await cookieStore.delete('2');
expect(trigger).toHaveBeenCalledTimes(5);

localStorage.setItem('1', '1');
sessionStorage.setItem('2', '2');
expect(trigger).toHaveBeenCalledTimes(7);
localStorage.removeItem('1');
sessionStorage.removeItem('2');
expect(trigger).toHaveBeenCalledTimes(9);
localStorage.clear();
sessionStorage.clear();
expect(trigger).toHaveBeenCalledTimes(7);
expect(trigger).toHaveBeenCalledTimes(11);
});
});
4 changes: 4 additions & 0 deletions tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ global.navigator.sendBeacon = jest.fn<boolean, any>((...args: any) => {
return true;
});

// mock window.alert
window.alert = () => {};

// mock window.cookieStore
import './__mocks__/cookie-store';

0 comments on commit 059b777

Please sign in to comment.