Code Monkey home page Code Monkey logo

mastering-react-test-driven-development's Introduction

Mastering React Test-Driven Development

Published by Packt

This is companion repository for the book Mastering React Test-Driven Development by Daniel Irvine, published by Packt.

The repository contains two branches, both of which are their own independent projects with their own READMEs. If you're interested in the contents of the books you can take a look at them now:

  • Appointments, a hair salon booking system
  • Spec Logo, an online Logo environment for building Logo scripts

The book itself has checkpoints that are based on various tags. If you're following along then you'll need to be comfortable switching tags.

Working along with the book

You should fork and then clone this repo to your local machine, and then check out a tag:

git checkout tags/starting-point

You should then branch from this tag before continuing with changes:

git checkout -b starting-point-mine

Note: If you are unable to checkout tags then it may mean tags were not fetched during fork. You can fetch these using the following commands:

cd /path/to/local/repo
git remote add upstream https://github.com/PacktPublishing/Mastering-React-Test-Driven-Development
git fetch --tags upstream
git push -f --tags origin main 

Merging in changes from additional commits

Not all commits are covered in the book. They have been omitted because they are repetitive and teach nothing new. These occasions are clearly marked at the start of each section. You have two choices:

  • You can repeat the process above, starting a new branch and 'losing' all of your previous work in favor of the book's version. Of course, you'll still have the previous branch available that you were working on, it just won't join with your new branch.
  • You can merge in the commits that you were missing. This may not turn out to be straightforward if your code has deviated significantly from the book's code.

You can compare the difference between your current HEAD and the listed tag with git diff:

git diff load-available-time-slots

You can then manually apply those changes.

If you'd rather try to automate those changes, then you can use git merge:

git merge load-available-time-slots

Errata

  • In Chapter 10, the section ‘Focusing the prompt’ on page 349 contains a test that uses the value document.activeElement. In JSDOM 15, this test will no longer function without additional configuration, which is given below. Please apply this change before proceeding with the text. In the file test/domManipulators.js, change the createContainer function to read as below. The second line of the function, which calls the appendChild function on document.body, is new and needs to be inserted, as shown:
export const createContainer = () => {
    const container = document.createElement('div')

    document.body.appendChild(container)
    ... remaining function body goes here ...
}

Get in touch

You can contact the author directly by raising Issues here in GitHub, or by contacting him on Twitter. He is @d_ir.

mastering-react-test-driven-development's People

Contributors

anchita avatar dirv avatar keagancarneiro avatar manikandankurup-packt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mastering-react-test-driven-development's Issues

Update for React 18

Hi, I'm aware that there will be a second edition coming soon but in the meantime, I'm struggling to get the first test working with createRoot, as this doesn't seem to work:

it('renders the customer first name', () => {
const customer = { firstName: 'Ashley'}
const container = document.createElement('div')
const root = createRoot(container)
root.render(<Appointment customer={customer} />)
expect(container.textContent).toMatch('Ashley')
})

container.textContent ends up returning an empty string. Any suggestion what's wrong here? Thank you in advance. I've been enjoying the book so far.

Question about ... syntax in JSX

hope it's appropriate to put this question in here:

I am ankle-deep in Mastering react tdd, and am puzzled by the syntax necessary for the refactoring near the end of chapter 2, specifically the passage below - why couldn't I use {fieldName}: value instead of {...{ [fieldName]: value }}? And what are the ... and [] doing in this context?

const itSubmitsExistingValue = (fieldName, value) =>
  it('saves existing value when submitted', async () => {
    expect.hasAssertions();
    render(
      <CustomerForm
        {...{ [fieldName]: value }}
        onSubmit={props =>
          expect(props[fieldName]).toEqual(value)
        }
      />
    );
    await ReactTestUtils.Simulate.submit(form('customer'));
  });

Test independance violation

I just found a dependency between tests in tag cucumber in files:

  • MenuButtons.test.js
  • sharingSagas.test.js

There is a missing reset of socketSpy variable, which should be set to default state after each test or else it can possibly change the behavior of tests.

Fix is as simple as adding one line into both files:

// MenuButtons.test.js

describe('MenuButtons', () => {
  ...
  describe('sharing button', () => {
    ...
    afterEach(() => {
      ...
      // Add this line
      socketSpy = undefined;
    });
    ...
  });
  ...
});
// sharingSagas.test.js

describe('sharingSaga', () => {
  ...
  afterEach(() => {
    ...
    // Add this line
    socketSpy = undefined;
  });
  ...
});

This unfornately causes the breakage of test dispatches an action of STOP_SHARING when stop sharing is clicked in MenuButtons.test.js due to failure of function notifySocketOpened where the socketSpy is undefined and it is trying to reach its onopen callback property.

Testcase works because socketSpy is set previously in test dispatches an action of START_SHARING when start sharing is clicked and just skipping this test causes test case failure as well.

Solution would be to somehow call startSharing saga that creates WebSocket and therefore sets the onopen callback property . Easiest solution appears to be just adding this line to test:

// sharingSagas.js
...
    it('dispatches an action of STOP_SHARING when stop sharing is clicked', async () => {
      const store = renderWithStore(<MenuButtons />);
      // Add this line
      click(button('Start sharing'));
      store.dispatch({ type: 'STARTED_SHARING' });
      await notifySocketOpened();
      click(button('Stop sharing'));
      return expectRedux(store)
        .toDispatchAnAction()
        .matching({ type: 'STOP_SHARING' });
    });

Hope it helps.

Open index.html in your browser but there's no server?

I was confused by this sentence at the end of Chapter 1.

Open index.html in your browser and behold your creation:

I was wondering where my server was and how to open this file. I was unable to open localhost/index.html (because there is not a web server launched by running npm run build even after adding "build": "webpack --watch --progress" to package.json.

I looked at the code repository and saw there was a folder for "server" but when I looked at the chapter-1-exercises tag, there was no mention of "server".

Finally after some fruitless attempts at getting it to go with npm start and other useless commands, it dawned on me that I could open the file itself to see how the browser would render it. In Visual Studio Code, I had to right click the file itself, get its absolute path, and then paste that full path into a browser search bar to open it in the browser without any server.

Other than that confusion, Chapter 1 was quite good. There was a minor dilemma regarding the "There are no appointments scheduled for today." text that disappeared from some of the partial code but that's easy to crosscheck with the repository.

Missing tags for exercises for chapter 6 and 8

Hi @dirv

First of all a great book.
Thank you.

I try to resolve the exercises for chapter 6. Unfortunately, tags/chapter-6-exercises doesn't work.
I try this same for chapter 8 and it's the same.

Am I missing something?

Problem with document.activeElement

In the section named Focusing the prompt the document.activeElement didnt work for me (I m using jest ^27.0.6 with dependency jest-environment-jsdom 27.0.6 ) meaning it remained set to document body.

The solution was attaching this code in createContainer function:

export const createContainer = () => {
    const container = document.createElement('div')

    // Add this line here
    document.body.appendChild(container)

    ...
}

So basically just attaching container to the body helped me to solve this issue. Hope it will help someone with same problem.

is it correct to write "await ReactTestUtils.Simulate.submit()" ?

Hi @dirv , in chapter 2

  it('saves new first name when submitted', async () => {
    expect.hasAssertions();
    render(
      <CustomerForm
        firstName="Ashley"
        onSubmit={({ firstName }) =>
          expect(firstName).toEqual('Jamie')
        }
      />
    );
    await ReactTestUtils.Simulate.change(firstNameField(), {
      target: { value: 'Jamie' }
    });
    await ReactTestUtils.Simulate.submit(form('customer'));
  });

I noticed that neither ReactTestUtils.Simulate.change() nor ReactTestUtils.Simulate.submit() would return Promise, so I tried to remove async / await and the test still passed.

  it('saves new first name when submitted', () => {
    expect.hasAssertions();
    render(
      <CustomerForm
        firstName="Ashley"
        onSubmit={({ firstName }) =>
          expect(firstName).toEqual('Jamie')
        }
      />
    );
    ReactTestUtils.Simulate.change(firstNameField(), {
      target: { value: 'Jamie' }
    });
    ReactTestUtils.Simulate.submit(form('customer'));
  });

Is it correct to remove async / await?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.