2020-01-01 13:55:28 +05:30
|
|
|
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
2017-08-17 22:00:37 +05:30
|
|
|
import Autosave from '~/autosave';
|
|
|
|
import AccessorUtilities from '~/lib/utils/accessor';
|
|
|
|
|
|
|
|
describe('Autosave', () => {
|
2019-09-04 21:01:54 +05:30
|
|
|
useLocalStorageSpy();
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
let autosave;
|
2023-03-17 16:20:25 +05:30
|
|
|
const field = document.createElement('textarea');
|
|
|
|
const checkbox = document.createElement('input');
|
|
|
|
checkbox.type = 'checkbox';
|
2018-03-27 19:54:05 +05:30
|
|
|
const key = 'key';
|
2020-01-01 13:55:28 +05:30
|
|
|
const fallbackKey = 'fallbackKey';
|
2020-05-24 23:13:21 +05:30
|
|
|
const lockVersionKey = 'lockVersionKey';
|
|
|
|
const lockVersion = 1;
|
2023-03-17 16:20:25 +05:30
|
|
|
const getAutosaveKey = () => `autosave/${key}`;
|
|
|
|
const getAutosaveLockKey = () => `autosave/${key}/lockVersion`;
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
autosave?.dispose?.();
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
describe('class constructor', () => {
|
|
|
|
beforeEach(() => {
|
2021-11-11 11:23:49 +05:30
|
|
|
jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(true);
|
2019-09-04 21:01:54 +05:30
|
|
|
jest.spyOn(Autosave.prototype, 'restore').mockImplementation(() => {});
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('should set .isLocalStorageAvailable', () => {
|
2018-03-27 19:54:05 +05:30
|
|
|
autosave = new Autosave(field, key);
|
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
expect(AccessorUtilities.canUseLocalStorage).toHaveBeenCalled();
|
2017-08-17 22:00:37 +05:30
|
|
|
expect(autosave.isLocalStorageAvailable).toBe(true);
|
|
|
|
});
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
it('should set .isLocalStorageAvailable if fallbackKey is passed', () => {
|
|
|
|
autosave = new Autosave(field, key, fallbackKey);
|
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
expect(AccessorUtilities.canUseLocalStorage).toHaveBeenCalled();
|
2020-01-01 13:55:28 +05:30
|
|
|
expect(autosave.isLocalStorageAvailable).toBe(true);
|
|
|
|
});
|
2020-05-24 23:13:21 +05:30
|
|
|
|
|
|
|
it('should set .isLocalStorageAvailable if lockVersion is passed', () => {
|
|
|
|
autosave = new Autosave(field, key, null, lockVersion);
|
|
|
|
|
2021-11-11 11:23:49 +05:30
|
|
|
expect(AccessorUtilities.canUseLocalStorage).toHaveBeenCalled();
|
2020-05-24 23:13:21 +05:30
|
|
|
expect(autosave.isLocalStorageAvailable).toBe(true);
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('restore', () => {
|
|
|
|
describe('if .isLocalStorageAvailable is `false`', () => {
|
|
|
|
beforeEach(() => {
|
2023-03-17 16:20:25 +05:30
|
|
|
jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(false);
|
|
|
|
autosave = new Autosave(field, key);
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('should not call .getItem', () => {
|
|
|
|
expect(window.localStorage.getItem).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `true`', () => {
|
|
|
|
it('should call .getItem', () => {
|
2023-03-17 16:20:25 +05:30
|
|
|
autosave = new Autosave(field, key);
|
|
|
|
expect(window.localStorage.getItem.mock.calls).toEqual([[getAutosaveKey()], []]);
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
describe('if saved value is present', () => {
|
|
|
|
const storedValue = 'bar';
|
2019-12-04 20:38:33 +05:30
|
|
|
|
2022-10-11 01:57:18 +05:30
|
|
|
beforeEach(() => {
|
2023-03-17 16:20:25 +05:30
|
|
|
field.value = 'foo';
|
|
|
|
window.localStorage.setItem(getAutosaveKey(), storedValue);
|
2022-10-11 01:57:18 +05:30
|
|
|
});
|
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
it('restores the value', () => {
|
|
|
|
autosave = new Autosave(field, key);
|
|
|
|
expect(field.value).toEqual(storedValue);
|
2022-10-11 01:57:18 +05:30
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
it('triggers native event', () => {
|
|
|
|
const eventHandler = jest.fn();
|
|
|
|
field.addEventListener('change', eventHandler);
|
|
|
|
autosave = new Autosave(field, key);
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
expect(eventHandler).toHaveBeenCalledTimes(1);
|
|
|
|
field.removeEventListener('change', eventHandler);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if field type is checkbox', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
checkbox.checked = false;
|
|
|
|
window.localStorage.setItem(getAutosaveKey(), true);
|
|
|
|
autosave = new Autosave(checkbox, key);
|
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
it('should restore', () => {
|
|
|
|
expect(checkbox.checked).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
2018-03-27 19:54:05 +05:30
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
describe('getSavedLockVersion', () => {
|
|
|
|
describe('if .isLocalStorageAvailable is `false`', () => {
|
|
|
|
beforeEach(() => {
|
2023-03-17 16:20:25 +05:30
|
|
|
jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(false);
|
|
|
|
autosave = new Autosave(field, key);
|
2020-05-24 23:13:21 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('should not call .getItem', () => {
|
2023-03-17 16:20:25 +05:30
|
|
|
autosave.getSavedLockVersion();
|
2020-05-24 23:13:21 +05:30
|
|
|
expect(window.localStorage.getItem).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `true`', () => {
|
|
|
|
beforeEach(() => {
|
2023-03-17 16:20:25 +05:30
|
|
|
autosave = new Autosave(field, key);
|
2020-05-24 23:13:21 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .getItem', () => {
|
2023-03-17 16:20:25 +05:30
|
|
|
autosave.getSavedLockVersion();
|
|
|
|
expect(window.localStorage.getItem.mock.calls).toEqual([
|
|
|
|
[getAutosaveKey()],
|
|
|
|
[],
|
|
|
|
[getAutosaveLockKey()],
|
|
|
|
]);
|
2020-05-24 23:13:21 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
describe('save', () => {
|
|
|
|
beforeEach(() => {
|
2019-09-04 21:01:54 +05:30
|
|
|
autosave = { reset: jest.fn() };
|
2017-08-17 22:00:37 +05:30
|
|
|
autosave.field = field;
|
2023-03-17 16:20:25 +05:30
|
|
|
field.value = 'value';
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `false`', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave.isLocalStorageAvailable = false;
|
|
|
|
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not call .setItem', () => {
|
|
|
|
expect(window.localStorage.setItem).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `true`', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave.isLocalStorageAvailable = true;
|
|
|
|
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .setItem', () => {
|
|
|
|
expect(window.localStorage.setItem).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
2022-10-11 01:57:18 +05:30
|
|
|
|
|
|
|
describe('if field type is checkbox', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave = {
|
|
|
|
field: checkbox,
|
|
|
|
key,
|
|
|
|
isLocalStorageAvailable: true,
|
|
|
|
type: 'checkbox',
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should save true when checkbox on', () => {
|
2023-03-17 16:20:25 +05:30
|
|
|
checkbox.checked = true;
|
2022-10-11 01:57:18 +05:30
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
expect(window.localStorage.setItem).toHaveBeenCalledWith(key, true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call reset when checkbox off', () => {
|
|
|
|
autosave.reset = jest.fn();
|
2023-03-17 16:20:25 +05:30
|
|
|
checkbox.checked = false;
|
2022-10-11 01:57:18 +05:30
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
expect(autosave.reset).toHaveBeenCalled();
|
|
|
|
expect(window.localStorage.setItem).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
describe('save with lockVersion', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave = {
|
|
|
|
field,
|
|
|
|
key,
|
|
|
|
lockVersionKey,
|
|
|
|
lockVersion,
|
|
|
|
isLocalStorageAvailable: true,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('lockVersion is valid', () => {
|
|
|
|
it('should call .setItem', () => {
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
expect(window.localStorage.setItem).toHaveBeenCalledWith(lockVersionKey, lockVersion);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .setItem when version is 0', () => {
|
|
|
|
autosave.lockVersion = 0;
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
expect(window.localStorage.setItem).toHaveBeenCalledWith(
|
|
|
|
lockVersionKey,
|
|
|
|
autosave.lockVersion,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('lockVersion is invalid', () => {
|
|
|
|
it('should not call .setItem with lockVersion', () => {
|
|
|
|
delete autosave.lockVersion;
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
|
|
|
|
expect(window.localStorage.setItem).not.toHaveBeenCalledWith(
|
|
|
|
lockVersionKey,
|
|
|
|
autosave.lockVersion,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
describe('reset', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave = {
|
|
|
|
key,
|
2020-05-24 23:13:21 +05:30
|
|
|
lockVersionKey,
|
2017-08-17 22:00:37 +05:30
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `false`', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave.isLocalStorageAvailable = false;
|
|
|
|
|
|
|
|
Autosave.prototype.reset.call(autosave);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not call .removeItem', () => {
|
|
|
|
expect(window.localStorage.removeItem).not.toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('if .isLocalStorageAvailable is `true`', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave.isLocalStorageAvailable = true;
|
|
|
|
|
|
|
|
Autosave.prototype.reset.call(autosave);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .removeItem', () => {
|
|
|
|
expect(window.localStorage.removeItem).toHaveBeenCalledWith(key);
|
2020-05-24 23:13:21 +05:30
|
|
|
expect(window.localStorage.removeItem).toHaveBeenCalledWith(lockVersionKey);
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
describe('restore with fallbackKey', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
autosave = {
|
|
|
|
field,
|
|
|
|
key,
|
|
|
|
fallbackKey,
|
2020-05-24 23:13:21 +05:30
|
|
|
isLocalStorageAvailable: true,
|
2020-01-01 13:55:28 +05:30
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .getItem', () => {
|
|
|
|
Autosave.prototype.restore.call(autosave);
|
|
|
|
|
|
|
|
expect(window.localStorage.getItem).toHaveBeenCalledWith(fallbackKey);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .setItem for key and fallbackKey', () => {
|
|
|
|
Autosave.prototype.save.call(autosave);
|
|
|
|
|
|
|
|
expect(window.localStorage.setItem).toHaveBeenCalledTimes(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call .removeItem for key and fallbackKey', () => {
|
|
|
|
Autosave.prototype.reset.call(autosave);
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
expect(window.localStorage.removeItem).toHaveBeenCalledWith(fallbackKey);
|
|
|
|
expect(window.localStorage.removeItem).toHaveBeenCalledWith(key);
|
2020-01-01 13:55:28 +05:30
|
|
|
});
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|