docbrown/app/javascript/onboarding/__tests__/Onboarding.test.jsx
Jacob Herrington e79ad764bd Onboarding test love (#4878)
* Reduce code duplication in onboarding tests

* Update variable names for consistency

* Improve test descriptions and format

* Refactor a useless test

This test was fairly pointless, but hopefully with this refactor it
could detect a regression? Although, I think it's really just testing
the that the Preact framework's state mechanism is working the way we
expect it to, but it might be worth leaving this test in.
2019-11-22 14:23:57 -05:00

360 lines
10 KiB
JavaScript

import { h } from 'preact';
import { deep } from 'preact-render-spy';
import fetch from 'jest-fetch-mock';
import { axe, toHaveNoViolations } from 'jest-axe';
import Onboarding from '../Onboarding';
import BioForm from '../components/BioForm';
import PersonalInfoForm from '../components/PersonalInfoForm';
import EmailTermsConditionsForm from '../components/EmailListTermsConditionsForm';
import FollowTags from '../components/FollowTags';
import FollowUsers from '../components/FollowUsers';
global.fetch = fetch;
function flushPromises() {
return new Promise(resolve => setImmediate(resolve));
}
function initializeSlides(currentSlide, dataUser = null, mockData = null) {
const onboardingSlides = deep(<Onboarding />);
if (mockData) {
fetch.once(mockData);
}
document.body.setAttribute('data-user', dataUser);
onboardingSlides.setState({ currentSlide });
return onboardingSlides;
}
describe('<Onboarding />', () => {
beforeAll(() => {
expect.extend(toHaveNoViolations);
});
beforeEach(() => {
fetch.resetMocks();
});
const fakeTagsResponse = JSON.stringify([
{
bg_color_hex: '#000000',
id: 715,
name: 'discuss',
text_color_hex: '#ffffff',
},
{
bg_color_hex: '#f7df1e',
id: 6,
name: 'javascript',
text_color_hex: '#000000',
},
{
bg_color_hex: '#2a2566',
id: 630,
name: 'career',
text_color_hex: '#ffffff',
},
]);
const fakeUsersResponse = JSON.stringify([
{
id: 1,
name: 'Ben Halpern',
profile_image_url: 'ben.jpg',
},
{
id: 2,
name: 'Krusty the Clown',
profile_image_url: 'clown.jpg',
},
{
id: 3,
name: 'dev.to staff',
profile_image_url: 'dev.jpg',
},
]);
const dataUser = JSON.stringify({
followed_tag_names: ['javascript'],
});
describe('IntroSlide', () => {
let onboardingSlides;
beforeEach(() => {
onboardingSlides = initializeSlides(0);
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
test('should not have basic a11y violations', async () => {
const results = await axe(onboardingSlides.toString());
expect(results).toHaveNoViolations();
});
test('should advance', () => {
onboardingSlides.find('.next-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(1);
});
});
describe('EmailTermsConditionsForm', () => {
let onboardingSlides;
const codeOfConductCheckEvent = {
target: {
value: 'checked_code_of_conduct',
name: 'checked_code_of_conduct',
},
};
const termsAndConditionsCheckEvent = {
target: {
value: 'checked_terms_and_conditions',
name: 'checked_terms_and_conditions',
},
};
const updateCodeOfConduct = () => {
onboardingSlides
.find('#checked_code_of_conduct')
.simulate('change', codeOfConductCheckEvent);
};
const updateTermsAndConditions = () => {
onboardingSlides
.find('#checked_terms_and_conditions')
.simulate('change', termsAndConditionsCheckEvent);
};
beforeEach(() => {
onboardingSlides = initializeSlides(1, dataUser);
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
// Arguably this test is actually just testing the Preact framework
// but for the sake of detecting a regression I am refactoring it instead
// of removing it (@jacobherrington)
test('should track state changes', () => {
const emailTerms = onboardingSlides.find(<EmailTermsConditionsForm />);
expect(emailTerms.state('checked_code_of_conduct')).toBe(false);
expect(emailTerms.state('checked_terms_and_conditions')).toBe(false);
updateCodeOfConduct();
updateTermsAndConditions();
expect(emailTerms.state('checked_code_of_conduct')).toBe(true);
expect(emailTerms.state('checked_terms_and_conditions')).toBe(true);
});
test('should not advance if required boxes are not checked', () => {
// When none of the boxes are checked
onboardingSlides.find('.next-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(1);
// When only the code of conduct is checked
updateCodeOfConduct();
expect(onboardingSlides.state().currentSlide).toBe(1);
// When only the terms and conditions are checked
updateCodeOfConduct();
updateTermsAndConditions();
onboardingSlides.find('.next-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(1);
});
test('should advance if required boxes are checked', async () => {
fetch.once({});
updateCodeOfConduct();
updateTermsAndConditions();
onboardingSlides.find('.next-button').simulate('click');
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(2);
});
it('should step backward', () => {
onboardingSlides.find('.back-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(0);
});
});
describe('BioForm', () => {
let onboardingSlides;
const meta = document.createElement('meta');
meta.setAttribute('name', 'csrf-token');
document.body.appendChild(meta);
beforeEach(() => {
onboardingSlides = initializeSlides(2, dataUser);
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
test('should allow user to fill forms and advance', async () => {
fetch.once({});
const bioForm = onboardingSlides.find(<BioForm />);
const event = { target: { value: 'my bio', name: 'summary' } };
onboardingSlides.find('textarea').simulate('change', event);
expect(bioForm.state('summary')).toBe(event.target.value);
bioForm.find('.next-button').simulate('click');
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(3);
});
it('should step backward', () => {
onboardingSlides.find('.back-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(1);
});
});
describe('PersonalInformationForm', () => {
let onboardingSlides;
const meta = document.createElement('meta');
meta.setAttribute('name', 'csrf-token');
document.body.appendChild(meta);
beforeEach(() => {
onboardingSlides = initializeSlides(3, dataUser);
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
it('should move to the previous slide upon clicking the back button', () => {
onboardingSlides.find('.back-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(2);
});
test('should allow user to fill forms and advance', async () => {
fetch.once({});
const personalInfoForm = onboardingSlides.find(<PersonalInfoForm />);
const locationEvent = {
target: { value: 'my location', name: 'location' },
};
const titleEvent = {
target: { value: 'my title', name: 'employment_title' },
};
const employerEvent = {
target: { value: 'my employer name', name: 'employer_name' },
};
onboardingSlides.find('#location').simulate('change', locationEvent);
onboardingSlides.find('#employment_title').simulate('change', titleEvent);
onboardingSlides.find('#employer_name').simulate('change', employerEvent);
expect(personalInfoForm.state('location')).toBe(
locationEvent.target.value,
);
expect(personalInfoForm.state('employment_title')).toBe(
titleEvent.target.value,
);
expect(personalInfoForm.state('employer_name')).toBe(
employerEvent.target.value,
);
personalInfoForm.find('.next-button').simulate('click');
fetch.once(fakeTagsResponse);
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(4);
});
});
describe('FollowTags', () => {
let onboardingSlides;
beforeEach(async () => {
onboardingSlides = initializeSlides(4, dataUser, fakeTagsResponse);
await flushPromises();
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
test('should render three tags', async () => {
expect(onboardingSlides.find('.tag').length).toBe(3);
});
test('should allow a user to add a tag', async () => {
fetch.once({});
const followTags = onboardingSlides.find(<FollowTags />);
onboardingSlides
.find('.tag')
.first()
.simulate('click');
expect(followTags.state('selectedTags').length).toBe(1);
onboardingSlides.find('.next-button').simulate('click');
fetch.once(fakeUsersResponse);
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(5);
});
it('should step backward', () => {
onboardingSlides.find('.back-button').simulate('click');
expect(onboardingSlides.state().currentSlide).toBe(3);
});
});
describe('FollowUsers', () => {
let onboardingSlides;
beforeEach(async () => {
onboardingSlides = initializeSlides(5, dataUser, fakeUsersResponse);
await flushPromises();
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
test('should render three users', async () => {
expect(onboardingSlides.find('.user').length).toBe(3);
});
test('should allow a user to select and advance', async () => {
fetch.once({});
const followUsers = onboardingSlides.find(<FollowUsers />);
onboardingSlides
.find('.user')
.first()
.simulate('click');
expect(followUsers.state('selectedUsers').length).toBe(2);
onboardingSlides.find('.next-button').simulate('click');
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(6);
});
it('should step backward', async () => {
fetch.once(fakeTagsResponse);
onboardingSlides.find('.back-button').simulate('click');
await flushPromises();
expect(onboardingSlides.state().currentSlide).toBe(4);
});
});
describe('CloseSlide', () => {
let onboardingSlides;
beforeEach(() => {
onboardingSlides = initializeSlides(6);
});
test('renders properly', () => {
expect(onboardingSlides).toMatchSnapshot();
});
});
});