Query regarding the boilerplate

This solution passes the test case, but what bothers me is why are we not calling store.dispatch(loginAction()) here? Without dispath, action object should be undefined in the reducer function.

Is it being called at the backend or I am missing something?

Your code so far


const defaultState = {
login: false
};

const reducer = (state = defaultState, action) => {
// change code below this line
if(action.type === 'LOGIN') {
  return {
    login: true,
  }
}
  else {
    return state
  }
}
// change code above this line

const store = Redux.createStore(reducer);

const loginAction = () => {
return {
  type: 'LOGIN'
}
};

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36.

Challenge: Handle an Action in the Store

Link to the challenge:

Right, they are having you build the pieces. The code that consumes this and tests it occurs offscreen.

And technically, you don’t need dispatch to test an action creator. An AC is just a function that takes state data (usually an object) and an action object. Both are just JS data. When I write unit tests for reducers at work, I don’t use dispatch, I just create fake data for those two parameters and assert what I expect to happen. I’d have to dig through the code, but I’d bet that that’s how they’re testing this.

1 Like

Considering your above statement, is this how we can do then?

To do what? I can’t answer that without understanding what the goal is.

Was I talking about doing that? No, I was not. I was simply pointing out that a reducer isn’t magic - it’s just a function.

For example, if I were writing unit tests for this reducer, I would treat it like any other function - I pass in some data and I expect certain data back. If I were writing Jest tests for this:

const defaultState = {
  login: false,
};

const reducer = (state = defaultState, action) => {
  if (action.type === 'LOGIN') {
    return {
      login: true,
    };
  } else {
    return state;
  }
};

// *** tests

describe('reducer', () => {
  describe('with no state', () => {
    const action = { type: 'does not matter' };
    const expectedReturn = defaultState;
    const actualReturn = reducer(undefined, action);
    it('should return default state', () => {
      expect(actualReturn).toStrictEqual(expectedReturn);
    });
  });

  describe('with state', () => {
    const thisDefaultState = { login: 'dummy data' };
    describe('with type LOGIN', () => {
      const action = { type: 'LOGIN' };
      const expectedReturn = { login: true };
      const actualReturn = reducer(thisDefaultState, action);
      it('should set login to true', () => {
        expect(actualReturn).toStrictEqual(expectedReturn);
      });
    });

    describe('with unrecognized type', () => {
      const action = { type: 'some unrecognizable type' };
      const expectedReturn = thisDefaultState;
      const actualReturn = reducer(thisDefaultState, action);
      it('should return passed state, () => {
        expect(actualReturn).toStrictEqual(expectedReturn);
      });
    });
  });
});

If your not familiar with Jest, you can test manually with something like this:

const reportObjectEqual = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2) ? 'test passes' : 'test fails';

console.group();
console.log('with no state - should return default state');
const action1 = { type: 'does not matter' };
const expectedReturn1 = defaultState;
const actualReturn1 = reducer(undefined, action1);
console.log(reportObjectEqual(actualReturn1, expectedReturn1));
console.groupEnd();

console.group();
console.log('with state - with type LOGIN - should set login to true');
const thisDefaultState2 = { login: 'dummy data' };
const action2 = { type: 'LOGIN' };
const expectedReturn2 = { login: true };
const actualReturn2 = reducer(thisDefaultState2, action2);
console.log(reportObjectEqual(actualReturn2, expectedReturn2));
console.groupEnd();

console.group();
console.log('with state - with unrecognized type - should return passed state');
const thisDefaultState3 = { login: 'dummy data' };
const action3 = { type: 'LOGIN' };
const expectedReturn3 = { login: true };
const actualReturn3 = reducer(thisDefaultState3, action3);
console.log(reportObjectEqual(actualReturn3, expectedReturn3));
console.groupEnd();

Dollars to donuts, if we dug through the FCC code, we’d find something like that.

My point is that a reducer is just a function. It is a pure function - it has no side effects and its output is only dependent on its inputs. that makes it very easy to test.

But back to your original thoughts, that’s why we don’t need dispatch to see if this reducer works the way we expect. FCC is running tests like these behind the scenes. It grabs your function reducer and tests it - without needing dispatch.