Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Slaughter <pslaughter@gitlab.com>2019-05-24 21:14:24 +0300
committerPaul Slaughter <pslaughter@gitlab.com>2019-06-04 20:14:50 +0300
commita9850b25c3624fe31d0230ad3f0df00fec6b7d48 (patch)
tree8f10492f2d6376a2ad2bb903d9f1027780979910 /spec/frontend
parent2bf5135af31a2ff133f3682f59323954458cc2c3 (diff)
Jestify autosave spec and add localStorage helper
The helper was needed because `jest.spyOn` would not work on this special window object property. The only way we could successfully spy on `localStorage` was with this helper.
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/autosave_spec.js151
-rw-r--r--spec/frontend/helpers/local_storage_helper.js41
2 files changed, 192 insertions, 0 deletions
diff --git a/spec/frontend/autosave_spec.js b/spec/frontend/autosave_spec.js
new file mode 100644
index 00000000000..4d9c8f96d62
--- /dev/null
+++ b/spec/frontend/autosave_spec.js
@@ -0,0 +1,151 @@
+import $ from 'jquery';
+import Autosave from '~/autosave';
+import AccessorUtilities from '~/lib/utils/accessor';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
+
+describe('Autosave', () => {
+ useLocalStorageSpy();
+
+ let autosave;
+ const field = $('<textarea></textarea>');
+ const key = 'key';
+
+ describe('class constructor', () => {
+ beforeEach(() => {
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(true);
+ jest.spyOn(Autosave.prototype, 'restore').mockImplementation(() => {});
+ });
+
+ it('should set .isLocalStorageAvailable', () => {
+ autosave = new Autosave(field, key);
+
+ expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
+ expect(autosave.isLocalStorageAvailable).toBe(true);
+ });
+ });
+
+ describe('restore', () => {
+ beforeEach(() => {
+ autosave = {
+ field,
+ key,
+ };
+ });
+
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = false;
+
+ Autosave.prototype.restore.call(autosave);
+ });
+
+ it('should not call .getItem', () => {
+ expect(window.localStorage.getItem).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ beforeEach(() => {
+ autosave.isLocalStorageAvailable = true;
+ });
+
+ it('should call .getItem', () => {
+ Autosave.prototype.restore.call(autosave);
+
+ expect(window.localStorage.getItem).toHaveBeenCalledWith(key);
+ });
+
+ it('triggers jquery event', () => {
+ jest.spyOn(autosave.field, 'trigger').mockImplementation(() => {});
+
+ Autosave.prototype.restore.call(autosave);
+
+ expect(field.trigger).toHaveBeenCalled();
+ });
+
+ it('triggers native event', done => {
+ autosave.field.get(0).addEventListener('change', () => {
+ done();
+ });
+
+ Autosave.prototype.restore.call(autosave);
+ });
+ });
+
+ describe('if field gets deleted from DOM', () => {
+ beforeEach(() => {
+ autosave.field = $('.not-a-real-element');
+ });
+
+ it('does not trigger event', () => {
+ jest.spyOn(field, 'trigger');
+
+ expect(field.trigger).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('save', () => {
+ beforeEach(() => {
+ autosave = { reset: jest.fn() };
+ autosave.field = field;
+ field.val('value');
+ });
+
+ 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();
+ });
+ });
+ });
+
+ describe('reset', () => {
+ beforeEach(() => {
+ autosave = {
+ key,
+ };
+ });
+
+ 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);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/helpers/local_storage_helper.js b/spec/frontend/helpers/local_storage_helper.js
new file mode 100644
index 00000000000..48e66b11767
--- /dev/null
+++ b/spec/frontend/helpers/local_storage_helper.js
@@ -0,0 +1,41 @@
+/**
+ * Manage the instance of a custom `window.localStorage`
+ *
+ * This only encapsulates the setup / teardown logic so that it can easily be
+ * reused with different implementations (i.e. a spy or a [fake][1])
+ *
+ * [1]: https://stackoverflow.com/a/41434763/1708147
+ *
+ * @param {() => any} fn Function that returns the object to use for localStorage
+ */
+const useLocalStorage = fn => {
+ const origLocalStorage = window.localStorage;
+ let currentLocalStorage;
+
+ Object.defineProperty(window, 'localStorage', {
+ get: () => currentLocalStorage,
+ });
+
+ beforeEach(() => {
+ currentLocalStorage = fn();
+ });
+
+ afterEach(() => {
+ currentLocalStorage = origLocalStorage;
+ });
+};
+
+/**
+ * Create an object with the localStorage interface but `jest.fn()` implementations.
+ */
+export const createLocalStorageSpy = () => ({
+ clear: jest.fn(),
+ getItem: jest.fn(),
+ setItem: jest.fn(),
+ removeItem: jest.fn(),
+});
+
+/**
+ * Before each test, overwrite `window.localStorage` with a spy implementation.
+ */
+export const useLocalStorageSpy = () => useLocalStorage(createLocalStorageSpy);