FormidableLabs / freactal

Clean and robust state management for React and React-like libs.
MIT License
1.65k stars 46 forks source link

Testing State Example doesn't work #46

Closed pyrossh closed 7 years ago

pyrossh commented 7 years ago

The testing the state container part of the Readme doesn't work.

const wrapComponentWithState = provideState({
  initialState: () => ({
    givenName: "Walter",
    familyName: "Harriman"
  }),
  effects: {
    setGivenName: softUpdate((state, val) => ({ givenName: val })),
    setFamilyName: softUpdate((state, val) => ({ familyName: val }))
  },
  computed: {
    fullName: ({ givenName, familyName }) => `${givenName} ${familyName}`,
    greeting: ({ fullName }) => `Hi, ${fullName}, and welcome!`
  }
});

const { effects, getState } = wrapComponentWithState();
console.log(wrapComponentWithState())
getState().fullName.should.equal("Walter Harriman");

This is the output I'm getting,

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
{ [Function: StatefulComponent]
  childContextTypes: { freactal: { [Function: bound checkType] isRequired: [Function: bound checkType] } },
  contextTypes: { freactal: { [Function: bound checkType] isRequired: [Function: bound checkType] } } }
/home/pyros2097/Code/rad/test/abc.js:56
getState().fullName.should.equal("Walter Harriman");
^

TypeError: getState is not a function
    at Object.<anonymous> (/home/pyros2097/Code/rad/test/abc.js:49:1)
    at Module._compile (module.js:571:32)
    at loader (/home/pyros2097/Code/rad/node_modules/babel-cli/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.(anonymous function) [as .js] (/home/pyros2097/Code/rad/node_modules/babel-cli/node_modules/babel-register/lib/node.js:154:7)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Function.Module.runMain (module.js:605:10)
    at Object.<anonymous> (/home/pyros2097/Code/rad/node_modules/babel-cli/lib/_babel-node.js:154:22)
    at Module._compile (module.js:571:32)

I'm using, babel-node 6.24.0

henryluki commented 7 years ago

I got same problem here.

I fixed this problem by modifying this line:

const { effects, getState } = wrapComponentWithState();

to

const { effects, getState } = new (wrapComponentWithState())(null, {});

This can pass the test, but i think it's kind of weird...

Actually, I also find some other test example a few small problems:

Like, state template:

import { provideState } from "freactal";

export const wrapComponentWithState = provideState({
  initialState: () => ({
    givenName: "Walter",
    familyName: "Harriman"
  }),
  effects: {
    setGivenName: softUpdate((state, val) => ({ givenName: val })), // softUpdate not imported
    setFamilyName: softUpdate((state, val) => ({ familyName: val }))
  },
  computed: {
    fullName: ({ givenName, familyName }) => `${givenName} ${familyName}`,
    greeting: ({ fullName }) => `Hi, ${fullName}, and welcome!`
  }
});

It should import softUpdate the first line.

import { provideState, softUpdate } from "freactal";

Also, Stateless functional components:

/*** app.spec.js ***/

import { mount } from "enzyme";
// Make sure to import the _unwrapped_ component here!
import { App } from "./app";

// We'll be re-using these values, so let's put it here for convenience.
const state = {
  givenName: "Charlie",
  familyName: "In-the-box",
  fullName: "Charlie In-the-box",
  greeting: "Howdy there, kid!"
};

describe("my app", () => {
  it("displays a greeting to the user", () => {
    // This test should be easy - all we have to do is ensure that
    // the string that is passed in is displayed correctly!

    // We're not doing anything with effects here, so let's not bother
    // setting them for now...
    const effects = {};

    // First, we mount the component, providing the expected state and effects.
    const el = mount(<App state={state} effects={effects}>); 

    // And then we can make assertions on the output.
    expect(el.find("#greeting").text()).to.equal("Howdy there, kid!");
  });

  it("accepts changes to the given name", () => {
    // Next we're testing the conditions under which our component might
    // interact with the provided effects.
    const effects = {
      setGivenName: sinon.spy(),
      setFamilyName: sinon.spy()
    };

    const el = mount(<App state={state} effects={effects}>);

    // Using `sinon-chai`, we can make readable assertions about whether
    // a spy function has been called.  We don't expect our effect to
    // be invoked when the component mounts, so let's make that assertion
    // here.
    expect(effects.setGivenName).not.to.have.been.called;
    // Next, we can simulate a input-box value change.
    el.find("input.given").simulate("change", {
      target: { value: "Eric" }
    });
    // And finally, we can assert that the effect - or, rather, the Sinon
    // spy that is standing in for the effect - was invoked with the expected
    // value.
    expect(effects.setGivenName).to.have.been.calledWith("Eric");
  });
});
 const el = mount(<App state={state} effects={effects}>); 

This component does't have a close tag, so it can't pass...

Should be fixed:

const el = mount(<App state={state} effects={effects}/>)
divmain commented 7 years ago

Thanks the insight @henryluki (for the docs PR!). @pyros2097, this is now fixed in master and will be released on npm shortly.