Skip to content

Instantly share code, notes, and snippets.

@dustingetz
Created November 5, 2019 21:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustingetz/7cdcb182d4edc31ebf1c9f8eb1a41189 to your computer and use it in GitHub Desktop.
Save dustingetz/7cdcb182d4edc31ebf1c9f8eb1a41189 to your computer and use it in GitHub Desktop.
var Mocha = require('mocha')
var assert = require('assert')
var _ = require('lodash')
var mocha = new Mocha()
mocha.suite.emit('pre-require', this, 'solution', mocha)
describe('Test suite', function() {
it('should work', function() {
assert(true)
})
it("can create a store", () => {
const store = createStore(state => state);
assert(typeof store.subscribe === "function");
assert(typeof store.dispatch === "function");
assert(typeof store.getState === "function");
});
it("initializes with initial state", () => {
const initialState = { foo: true, bar: false };
const store = createStore((state, action) => state, initialState);
const state = store.getState();
assert(Object.keys(state).length === 2);
assert(state.foo === true);
assert(state.bar === false);
});
it("can dispatch actions", () => {
const reducer = (state, action) => {
if (action.type !== "SET_NAME") {
return state;
}
return {
...state,
name: action.payload
};
};
const store = createStore(reducer);
store.dispatch({ type: "FOO", payload: "bar" });
assert(store.getState().name === undefined);
store.dispatch({ type: "SET_NAME", payload: "foo" });
assert(store.getState().name === "foo");
});
it("can subscribe and unsubscribe", () => {
const reducer = (state, action) => {
if (action.type !== "SET_NAME") {
return state;
}
return {
...state,
name: action.payload
};
};
const store = createStore(reducer);
let name = undefined;
const unsubscribe = store.subscribe(state => {
name = state.name;
unsubscribe();
});
assert(name === undefined);
store.dispatch({ type: "SET_NAME", payload: "bar" });
assert(name === "bar");
assert(store.getState().name === "bar");
store.dispatch({ type: "SET_NAME", payload: "baz" });
assert(name === "bar");
assert(store.getState().name === "baz");
});
it("can have multiple subscribers", () => {
const store = createStore(state => state);
let callCount1 = 0;
let callCount2 = 0;
let callCount3 = 0;
store.subscribe(() => {
callCount1++;
})
const unsubscribe = store.subscribe(() => {
callCount2++;
unsubscribe();
})
store.subscribe(() => {
callCount3++;
})
store.dispatch({ type: 'foo' });
assert(callCount1 === 1);
assert(callCount2 === 1);
assert(callCount3 === 1);
store.dispatch({ type: 'foo' });
assert(callCount1 === 2);
assert(callCount2 === 1);
assert(callCount3 === 2);
});
it("initializes reducer", () => {
const initialState = { name: "foo" };
const reducer = (state = initialState, action) => {
if (action.type !== "SET_NAME") {
return state;
}
return {
...state,
name: action.payload
};
};
const store = createStore(reducer);
assert(store.getState().name === "foo");
});
})
class Store {
constructor (reducer, initialState) {
this.reducer = reducer;
this.state = initialState || reducer(undefined, {}) || {};
this.subscribers = [];
}
subscribe(f) {
this.subscribers.push(f);
return () => {
this.subscribers = _.without(this.subscribers, f);
}
}
dispatch(action) {
let newState = this.reducer(this.state, action);
this.subscribers.forEach(f => f(newState));
this.state = newState;
}
getState() {
return this.state;
}
}
function createStore (r, initialState) {
return new Store(r, initialState);
}
mocha.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment