Storage Mocks for SSR/Node

by JakobJingleheimer

JavaScript

const _cookieSym = Symbol('Cookie');

class StorageMock {}

function storageMockFactory(type) {
    /**
     * A symbol is used to avoid accidentally accessing the underlying implementation.
     * @var {Symbol} sym - A unique key.
     */
    const sym = Symbol(`${type}Storage`);

    return Object.create(StorageMock.prototype, {
        clear: {
            value() {
                return this[sym].clear();
            },
        },
        getItem: {
            value(k) {
                const val = this[sym].get(k);

                return typeof val === 'undefined'
                    ? null
                    : val;
            },
        },
        key: {
            value(n) {
                return [...this[sym].keys()][n]; // eslint-disable-line
            },
        },
        length: {
            enumerable: true,
            get() {
                return this[sym].size;
            },
        },
        removeItem: {
            value(k) {
                return this[sym].delete(k);
            },
        },
        setItem: {
            value(k, v) {
                return this[sym].set(k, v);
            },
        },
        [sym]: { value: new Map() },
    });
}

const document = Object.create(Object.prototype, {
    [_cookieSym]: {
        value: new Map(),
    },
    cookie: {
        enumerable: true,
        get() {
            const items = [
                ...this[_cookieSym],
            ];

            return _map(items, (item) => item.join('='))
                .join('; ');
        },
        set(input) { // eslint-disable-line consistent-return
            if (!input) {
                console.warn(`[CookieMock] Provided value "${input}"" is invalid. Aborting.`);

                return void 0;
            }

            if (input === '__VOID_CLEAR__') { // for specs
                return this[_cookieSym].clear();
            }

            const pieces = input.split(/[=;]/);
            const key = pieces.shift().trim();
     ...