Yuki Takei 7 лет назад
Родитель
Сommit
ab6d8af311

+ 3 - 1
packages/growi-commons/package.json

@@ -34,6 +34,7 @@
     "eslint-plugin-jest": "^22.4.1",
     "eslint-plugin-react": "^7.12.4",
     "jest": "^24.7.1",
+    "jest-localstorage-mock": "^2.4.0",
     "module-alias": "^2.2.0",
     "prettier-stylelint": "^0.4.2"
   },
@@ -45,7 +46,8 @@
     "moduleNameMapper": {
       "@root/(.+)": "<rootDir>/$1",
       "@src/(.+)": "<rootDir>/src/$1"
-    }
+    },
+    "setupFiles": ["jest-localstorage-mock"]
   },
   "engines": {
     "node": ">=8.11.1 <11",

+ 2 - 0
packages/growi-commons/src/index.js

@@ -4,4 +4,6 @@ module.exports = {
   // plugin
   ArgsParser: require('./plugin/util/args-parser'),
   OptionParser: require('./plugin/util/option-parser'),
+  // service
+  LocalStorageService: require('./service/local-storage-manager'),
 };

+ 3 - 0
packages/growi-commons/src/service/index.js

@@ -0,0 +1,3 @@
+module.exports = {
+  LocalStorageManager: require('./localstorage-manager'),
+};

+ 56 - 0
packages/growi-commons/src/service/localstorage-manager.js

@@ -0,0 +1,56 @@
+let instance = null;
+class LocalStorageManager {
+
+  static getInstance() {
+    if (instance == null) {
+      instance = new LocalStorageManager();
+    }
+
+    return instance;
+  }
+
+  /**
+   * retrieve and return parsed JSON object
+   * @param {string} namespace
+   * @param {string} key
+   * @returns {object}
+   */
+  retrieveFromSessionStorage(namespace, key) {
+    const item = JSON.parse(sessionStorage.getItem(namespace)) || {};
+    if (key != null) {
+      return item[key];
+    }
+    return item;
+  }
+
+  /**
+   * save JavaScript object as stringified JSON object
+   *
+   * @param {string} namespace
+   * @param {string | object} cacheObjOrKey cache object or key (if third param is undefined)
+   * @param {object} cacheObj
+   */
+  saveToSessionStorage(namespace, cacheObjOrKey, cacheObj) {
+    let item = JSON.parse(sessionStorage.getItem(namespace)) || {};
+    if (cacheObj !== undefined) {
+      const key = cacheObjOrKey;
+      item[key] = cacheObj;
+    }
+    else {
+      item = cacheObjOrKey;
+    }
+    sessionStorage.setItem(namespace, JSON.stringify(item));
+  }
+
+  /**
+   * clear all state caches
+   *
+   * @param {string} namespace
+   */
+  static clearAllStateCaches(namespace) {
+    sessionStorage.removeItem(namespace);
+  }
+
+}
+
+module.exports = LocalStorageManager;

+ 85 - 0
packages/growi-commons/src/test/service/localstorage-manager.test.js

@@ -0,0 +1,85 @@
+require('module-alias/register');
+
+const LocalStorageManager = require('@src/service/localstorage-manager');
+
+let localStorageManager = null;
+
+beforeEach(() => {
+  localStorageManager = LocalStorageManager.getInstance();
+
+  // == init jest-localstorage-mock
+  // reset the storage
+  localStorage.clear();
+  sessionStorage.clear();
+  // set preset data
+  sessionStorage.setItem('localstorage-manager-test', JSON.stringify({ foo: 'bar' }));
+  // reset mocks
+  localStorage.setItem.mockClear();
+  sessionStorage.setItem.mockClear();
+});
+
+describe('LocalStorageManager', () => {
+  test('.getInstance() returns the same instance', () => {
+    expect(LocalStorageManager.getInstance()).toBe(localStorageManager);
+  });
+
+  test('.retrieveFromSessionStorage() with unknown namespace returns the empty object', () => {
+    const item = localStorageManager.retrieveFromSessionStorage('unknown namespace');
+    expect(item).toEqual({});
+  });
+
+  test('.retrieveFromSessionStorage() without key returns the preset data', () => {
+    const item = localStorageManager.retrieveFromSessionStorage('localstorage-manager-test');
+    expect(item).toEqual({ foo: 'bar' });
+  });
+
+  test('.retrieveFromSessionStorage() with key returns the preset data', () => {
+    const item = localStorageManager.retrieveFromSessionStorage('localstorage-manager-test', 'foo');
+    expect(item).toBe('bar');
+  });
+
+  test('.saveToSessionStorage() without key works fine', () => {
+    localStorageManager.saveToSessionStorage(
+      'localstorage-manager-test',
+      { foo: { qux: 'quux' } },
+    );
+
+    expect(sessionStorage.__STORE__.length).toBe(1);
+    expect(sessionStorage.setItem)
+      .toHaveBeenLastCalledWith(
+        'localstorage-manager-test',
+        JSON.stringify({ foo: { qux: 'quux' } }),
+      );
+  });
+
+  test('.saveToSessionStorage() with key works fine', () => {
+    localStorageManager.saveToSessionStorage(
+      'localstorage-manager-test',
+      'baz',
+      { qux: 'quux' },
+    );
+
+    expect(sessionStorage.__STORE__.length).toBe(1);
+    expect(sessionStorage.setItem)
+      .toHaveBeenLastCalledWith(
+        'localstorage-manager-test',
+        JSON.stringify({ foo: 'bar', baz: { qux: 'quux' } }),
+      );
+  });
+
+  test('.saveToSessionStorage() with unknown key works fine', () => {
+    localStorageManager.saveToSessionStorage(
+      'localstorage-manager-test-unknown-key',
+      'baz',
+      { qux: 'quux' },
+    );
+
+    expect(sessionStorage.__STORE__.length).toBe(2);
+    expect(sessionStorage.setItem)
+      .toHaveBeenLastCalledWith(
+        'localstorage-manager-test-unknown-key',
+        JSON.stringify({ baz: { qux: 'quux' } }),
+      );
+  });
+
+});

+ 5 - 0
packages/growi-commons/yarn.lock

@@ -3382,6 +3382,11 @@ jest-leak-detector@^24.7.0:
   dependencies:
     pretty-format "^24.7.0"
 
+jest-localstorage-mock@^2.4.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/jest-localstorage-mock/-/jest-localstorage-mock-2.4.0.tgz#c6073810735dd3af74020ea6c3885ec1cc6d0d13"
+  integrity sha512-/mC1JxnMeuIlAaQBsDMilskC/x/BicsQ/BXQxEOw+5b1aGZkkOAqAF3nu8yq449CpzGtp5jJ5wCmDNxLgA2m6A==
+
 jest-matcher-utils@^24.7.0:
   version "24.7.0"
   resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz#bbee1ff37bc8b2e4afcaabc91617c1526af4bcd4"