Hallo I'm Tiffany.
Engineer at ExpediaGroup and newbie speaker 🐣.
Mentor for freeCodeCamp Montreal
Work on terminal shell Starship sometimes.
twitter/sirmerr
github.com/sirmerr
linkedin.com/in/tiffanyln
This visual test caught that the image changed from Banff National Park to a screaming frog 🐸
Type your answers in the group chat 🕐
This snapshot test caught that the DOM structure for the heading has changed.
The dev removed a div.
<div>
<h1>
Find hotels near Banff National Park, Alberta
</h1>
</div>
<h1>
Find hotels near Banff National Park, Alberta
</h1>
--<div>
--</div>
Type your answers in the group chat 🕐
<div>
<h1>
Find hotels near Banff National Park, Alberta
</h1>
</div>
<h1>
Find hotels near Banff National Park, Alberta
</h1>
--<div>
--</div>
please don't use snapshot tests they're 99% chaotic bad and will make your devs cry more than usual
please don't use snapshot tests they're 99% chaotic bad and will make your devs cry more than usual
All customers
Want to enter dates and search for properties
Want to enter dates and search for properties
Data Analysts
Want to track events of the customer through the funnel
All customers
Bots (SEO)
Want to enter dates and search for properties
Wants good metadata, performance and accessibility
Data Analysts
Want to track events of the customer through the funnel
All customers
Visual
modified testing pyramid by Kent C. Dodds & Martin Fowler
🐇
🐢
cross-device
💵
💰💰💰
- Using class-based selectors to find elements
- Using DOM structure to find elements
- Manually triggering the re-rendering of components
- Using fixed-duration waits when expecting state changes
- Simulating browser events
// Instead of using
const usernameInput = container.querySelectorAll('input')[0];
const passwordInput = wrapper.find('input').last();
// ...or using
const usernameInput = wrapper.find('.sign-in-modal .username-field');
const passwordInput = container.querySelector('.sign-in-modal .password-field');
// Instead of using
// const usernameInput = container.querySelectorAll('input')[0];
// const passwordInput = wrapper.find('input').last();
// ...or using
// const usernameInput = wrapper.find('.sign-in-modal .username-field');
// const passwordInput = container.querySelector('.sign-in-modal .password-field');
// We should consider
const usernameInput = getByLabelText('Username');
const passwordInput = getByLabelText('Password');
// A shortcut for document.querySelector(`[data-testid="${yourId}"]`)
// <input data-testid="username-input" />
const usernameInputElement = getByTestId(container, 'username-input')
Should only be used in situations where all other selectors don't work for your use case.
// In a situation where you'd want to select a specific item in a list
const thirdLiInUl = container.querySelector('ul > li:nth-child(3)')
// You can include an index or ID in your attribute
const items = [
/* your items */
]
const thirdItem = getByTestId(`item-${items[2].id}`)
All customers
Data Analysts
All customers
Data Analysts
Checking the inputs and images are in the DOM
expect(queryByLabelText('Check-in')).tobeIntheDocument();
expect(queryByAltText('Frog screaming')).toBeInTheDocument();
All customers
Data Analysts
Checking the inputs and images are in the DOM
Checking the track event sent on click
expect(queryByLabelText('Check-in')).tobeIntheDocument();
expect(queryByAltText('Frog screaming')).toBeInTheDocument();
const searchButton = getByText('Search');
search.click();
expect(trackEvent).toHaveBeenCalledWith(...);
All customers
Data Analysts
Checking the inputs and images are in the DOM
expect(queryByLabelText('Check-in')).tobeIntheDocument();
expect(queryByAltText('Frog screaming')).toBeInTheDocument();
const searchButton = getByText('Search');
search.click();
expect(trackEvent).toHaveBeenCalledWith(...);
or Checking error states from bad customer input and bad API responses
Checking the track event sent on click
All customers
Actually building and running the app locally or in CI and interacting with the page the way a user would
All customers
// Enter check in and out dates
cy.findByLabelText('Check-in').type('June 23, 2020');
cy.findByLabelText('Check-out').type('June 24, 2020');
// Submit dates
cy.findByText('Send').click();
// Check it sends to the correct url with query params
cy.location().should(loc => {
expect(loc.pathname).to.eq('/Hotel-Search');
expect(loc.search).to.eq('?startDate=2020-06-23&endDate=2020-06-23')
})
All customers
Most smaller applications don't need this
Useful when you have external UI libraries. Beware of CI font differences.
All customers
cy.matchScreenshot();
Bots (SEO)
All customers
All customers
All customers