You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/test/store/index.js

240 lines
4.7 KiB

import fs from 'fs';
import assert from 'assert';
import MagicString from 'magic-string';
import { parse } from 'acorn';
import { Store } from '../../store.js';
describe('store', () => {
it('is written in ES5', () => {
const source = fs.readFileSync('store.js', 'utf-8');
const ast = parse(source, {
sourceType: 'module'
});
const magicString = new MagicString(source);
ast.body.forEach(node => {
if (/^(Im|Ex)port/.test(node.type)) magicString.remove(node.start, node.end);
});
parse(magicString.toString(), {
ecmaVersion: 5
});
});
describe('get', () => {
it('gets a specific key', () => {
const store = new Store({
foo: 'bar'
});
assert.equal(store.get('foo'), 'bar');
});
it('gets the entire state object', () => {
const store = new Store({
foo: 'bar'
});
assert.deepEqual(store.get(), { foo: 'bar' });
});
});
describe('set', () => {
it('sets state', () => {
const store = new Store();
store.set({
foo: 'bar'
});
assert.equal(store.get('foo'), 'bar');
});
});
describe('observe', () => {
it('observes state', () => {
let newFoo;
let oldFoo;
const store = new Store({
foo: 'bar'
});
store.observe('foo', (n, o) => {
newFoo = n;
oldFoo = o;
});
assert.equal(newFoo, 'bar');
assert.equal(oldFoo, undefined);
store.set({
foo: 'baz'
});
assert.equal(newFoo, 'baz');
assert.equal(oldFoo, 'bar');
});
});
describe('onchange', () => {
it('fires a callback when state changes', () => {
const store = new Store();
let count = 0;
let args;
store.onchange((state, changed) => {
count += 1;
args = { state, changed };
});
store.set({ foo: 'bar' });
assert.equal(count, 1);
assert.deepEqual(args, {
state: { foo: 'bar' },
changed: { foo: true }
});
// this should be a noop
store.set({ foo: 'bar' });
assert.equal(count, 1);
// this shouldn't
store.set({ foo: 'baz' });
assert.equal(count, 2);
assert.deepEqual(args, {
state: { foo: 'baz' },
changed: { foo: true }
});
});
});
it('allows user to cancel state change callback', () => {
const store = new Store();
const handler = store.onchange(() => {});
assert.doesNotThrow(() => {
handler.cancel();
}, TypeError, 'this._changeHandlers is undefined');
});
describe('computed', () => {
it('computes a property based on data', () => {
const store = new Store({
foo: 1
});
store.compute('bar', ['foo'], foo => foo * 2);
assert.equal(store.get('bar'), 2);
const values = [];
store.observe('bar', bar => {
values.push(bar);
});
store.set({ foo: 2 });
assert.deepEqual(values, [2, 4]);
});
it('computes a property based on another computed property', () => {
const store = new Store({
foo: 1
});
store.compute('bar', ['foo'], foo => foo * 2);
store.compute('baz', ['bar'], bar => bar * 2);
assert.equal(store.get('baz'), 4);
const values = [];
store.observe('baz', baz => {
values.push(baz);
});
store.set({ foo: 2 });
assert.deepEqual(values, [4, 8]);
});
it('prevents computed properties from being set', () => {
const store = new Store({
foo: 1
});
store.compute('bar', ['foo'], foo => foo * 2);
assert.throws(() => {
store.set({ bar: 'whatever' });
}, /'bar' is a read-only property/);
});
it('allows multiple dependents to depend on the same computed property', () => {
const store = new Store({
a: 1
});
store.compute('b', ['a'], a => a * 2);
store.compute('c', ['b'], b => b * 3);
store.compute('d', ['b'], b => b * 4);
assert.deepEqual(store.get(), { a: 1, b: 2, c: 6, d: 8 });
// bit cheeky, testing a private property, but whatever
assert.equal(store._sortedComputedProperties.length, 3);
});
it('prevents cyclical dependencies', () => {
const store = new Store();
assert.throws(() => {
store.compute('a', ['b'], b => b + 1);
store.compute('b', ['a'], a => a + 1);
}, /Cyclical dependency detected/);
});
});
describe('immutable', () => {
it('observing state only changes on immutable updates', () => {
let newFoo;
let oldFoo;
let callCount = 0;
let value1 = {};
let value2 = {};
const store = new Store({
foo: value1
}, { immutable: true });
store.observe('foo', (n, o) => {
callCount++;
newFoo = n;
oldFoo = o;
});
assert.equal(callCount, 1);
assert.equal(newFoo, value1);
assert.equal(oldFoo, undefined);
store.set({
foo: value1
});
assert.equal(callCount, 1);
assert.equal(newFoo, value1);
assert.equal(oldFoo, undefined);
store.set({
foo: value2
});
assert.equal(callCount, 2);
assert.equal(newFoo, value2);
assert.equal(oldFoo, value1);
});
});
});