Browse Source

Add first implementation

Herbert Vojčík 8 years ago
parent
commit
6bca4167ec
1 changed files with 42 additions and 0 deletions
  1. 42 0
      index.js

+ 42 - 0
index.js

@@ -0,0 +1,42 @@
+/*
+ * Helpers for testing Redux.
+ */
+
+const FINISHED = "@@test/SPYSHOULDBEFINISHED";
+
+/**
+ * Creates the middleware that checks if specified actions are dispatched.
+ * Use it like `const spy = spyInTheMiddle(fn1, fn2, ...), store = applyMiddleware(..., spy)(reducer);`.
+ * The fn1, ... get action in the parameter and should return truthy value if it is the expected one,
+ * in which case the expectation will be removed; and shoudl return falsy value if it can be ignored.
+ * For the moment, only first expectation in the list is checked until it returns true, then it is removed and the next one will be used,
+ * In case the action is invalid (like, it has right type but wrong payload), the expectation fn can (and should) throw,
+ * for example using the test assertion (in chai/expect, assertions are truthy, so your expectation fn can look like below)
+ *
+ *     ({type, payload: {foo}}) => type == "FOOIFY" && expect(foo).to.equal("bar")
+ *
+ * All actions are passed downstream, unless you threw.
+ *
+ * @param expectations
+ */
+export const spyInTheMiddle = (...expectations) => store => next => action => {
+    if (action.type == FINISHED && expectations.length > 0) throw new Error(`Expectations left unfulfilled: ${expectations.length}`);
+    if (expectations[0] && expectations[0](action)) {
+        expectations.shift();
+    }
+    return next(action);
+};
+
+/**
+ * Call `store.dispatch(SPY_VERIFY)` at the end of the test.
+ * It will pass if all expectations were fulfilled and fail if there are still some hanging there.
+ * @type {{type: string}}
+ */
+export const SPY_VERIFY = {type: FINISHED};
+
+/**
+ * Reducer that always returns unchanged state.
+ * @param state
+ * @param action
+ */
+export const dumbReducer = (state, action) => state;