SlideShare a Scribd company logo
WARSZTATY
DEMO
STACK
▸ React
▸ Redux
▸ Create React App
▸ Enzyme
▸ Jest
▸ Jasmine
TDD
TDD
▸ Test-Driven Development
▸ nie służy stricte testowaniu
▸ pomaga wyeliminować błędy w
zrozumieniu działania
CZYM JEST TDD?
TDD
STRUKTURA TESTU
function add(a, b) { ... }
describe('Adding function', () => {
it('adds two numbers', () => {
expect(add(1, 2)).toBe(3);
});
it('fails when on wrong params given', () => {
expect(add()).toBeNull();
})
});
ENZYME
TDD
describe('My React Component', () => {
it('renders a number passed through a prop', () => {
// ?
});
});
TDD
describe('My React Component', () => {
it('renders a number passed through a prop', () => {
const wrapper = render(<Component prop={2}/>,
document.getElementById('app'));
expect(wrapper.find('span').text()).toEqual('2');
});
});
TDD
import { shallow, mount } from 'enzyme';
describe('My React Component', () => {
it('renders a number passed through a prop', () => {
const wrapper = shallow(<Component prop={2}/>);
expect(wrapper.find('span').text()).toEqual('2');
});
it('renders a number passed through a prop', () => {
const connect = jest.fn();
const wrapper = mount(<Component onconnect={connect}/>);
expect(connect).toBeCalled();
});
});
TDD
▸ Instalacja paczek
▸ yarn add enzyme
▸ yarn add react-addons-test-utils
▸ Test dla komponentu licznika osób na stronie
▸ Counter component displays a number passed to a prop
▸ Counter component displays 0 if props hasn’t been passed
▸ Komponent licznika
ZADANIE 1 - PIERWSZY KOMPONENT I TESTY
http://airbnb.io/enzyme/docs/api/index.html
REDUX
REDUX
CZYM JEST REDUX?
Redux jest przewidywalnym kontenerem stanu aplikacji JS.
TRZY ZASADY
‣ Single source of truth
‣ Stan jest tylko do odczytu
‣ Zmiany wykonujemy za pomocą „czystych” funkcji
REDUX
ACTIONS & ACTION CREATORS
const ADD_TODO = 'todos/ADD_TODO';
{
type: ADD_TODO,
payload: { text: 'Build my first Redux app' }
}
const addTodo = (text) => ({
type: ADD_TODO,
payload: { text }
});
REDUX
REDUCER
const initialState = [];
const todoReducer = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
REDUX
REDUCER
const initialState = { todos: [] };
const todoReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return [
...state.todos,
{
text: action.payload.text,
completed: false
}
];
default:
return state;
}
};
REDUX
SKŁADANIE REDUCERÓW
import { combineReducers } from 'redux';
const appReducer = combineReducers({
todo: todoReducer,
routing: routerReducer
});
REDUX
▸ Tworzymy akcję do aktualizacji stanu licznika
▸ Tworzymy reducer, obsługujący aktualizację
▸ Pamiętamy o testach
▸ Users actions creates update action
▸ Users reducer returns default state
▸ Users reducer updates counter
ZADANIE 2 - AKCJE I REDUCERY
{
"users": {
"count": 2
}
}
CONTAINER
CONTAINER
▸ „pomost” pomiędzy komponentem, a reduxem
▸ umożliwia użycie z reduxem już istniejących komponentów bez potrzeby
ingerowania w ich kod
▸ ułatwia separację zadań
▸ pobieranie/przetwarzanie danych
▸ prezentacja danych
CZYM JEST KONTENER?
CONTAINER
CONNECT()
connect(

[mapStateToProps],

[mapDispatchToProps],

[mergeProps], 

[options]

)
odpalana przy każdej 

zmianie zawartości store’a
zazwyczaj nie 

są potrzebne ;-)
CONTAINER
import { connect } from 'react—redux';
import { ToDo } from './todo.component';
import { addTask } from '../todo/todo.actions';
const mapStateToProps = (state) => ({
list: state.taskList
});
const mapDispatchToProps = (dispatch) => ({
add: task => dispatch(addTask(task))
});
export const ToDoContainer = connect(
mapStateToProps,
mapDispatchToProps
)(ToDo);
CONTAINER
▸ Tworzymy kontener dla naszego komponentu
ZADANIE 3 - REDUX + REACT
TESTOWANIE

ZACHOWANIA
KOMPONENTÓW
TESTOWANIE ZACHOWANIA KOMPONENTÓW
TESTOWANIE WYWOŁANIA FUNKCJI
const myProps = {

mockFn: jest.fn()

};

myProps.mockFn(10);


expect(myProps.mockFn).toBeCalledWith(10);
TESTOWANIE ZACHOWANIA KOMPONENTÓW
SYMULOWANIE ZMIANY PARAMETROW
const connect = jest.fn();
const wrapper = shallow(<SomeComponent displayButton={false} />);
expect(wrapper.find('button').length).toBe(0);
wrapper.setProps({displayButton: true});
expect(wrapper.find('button').length).toBe(1);
TESTOWANIE ZACHOWANIA KOMPONENTÓW
SYMULOWANIE INTERAKCJI
const clear = jest.fn();
const wrapper = shallow(<MyComponent clearFields={clear} />);
wrapper.find(‚button').simulate('click');
expect(clear).toBeCalled();
TESTOWANIE ZACHOWANIA KOMPONENTÓW
▸ Komponent wyświetlający aktualny stan połączenia z socketem (connected,
not-connected, connecting)
▸ Komponent pozwalający wykonać akcję podłączenia się do systemu
▸ Akcje i reducery do komunikacji z socketem
▸ Pamiętamy o testach :)
ZADANIE 4 - PRZYGOTOWANIE DO IMPLEMENTACJI KOMUNIKACJI Z SOCKETEM
{
"socket": {
"status": "connected"
}
}
WEBSOCKET
WEBSOCKET
OD CZEGO ZACZYNAMY ?
const ws = new WebSocket(url);
const ws = new WebSocket(process.env.REACT_APP_SOCKET_URL);
PRZECHOWYWANIE ADRESU SERWERA
REACT_APP_SOCKET_URL=ws://localhost:8080
WEBSOCKE
METODY
ws.onmessage = ({data}) => {...};
ws.onopen = () => {...};
WEBSOCKET
PRZEKAZYWANIE INFORMACJI
{

data: '{"type":"users","count":10}'

}
WEBSOCKET

+

REDUX
WEBSOCKET + REDUX
DISPATCH MIDDLEWARE
MIDDLEWARE
MIDDLEWARE
REDUCERS
WEBSOCKET + REDUX
MIDDLEWARE
export const middleware = function(store) {

return function (next) {

return function (action) {

next(action);

}

}

};
WERSJA ES6
export const socketMiddleware = store => next => action => {...}
INTEGRACJA Z REDUX
const store = createStore(

appReducer,

compose(

applyMiddleware(

socketMiddleware,

routerMiddleware(browserHistory)

),

window.devToolsExtension ? window.devToolsExtension() : f => f

)

);
WEBSOCKET + REDUX
MOCKOWANIE WEBSOCKETU
window.WebSocket = window.WebSocket || function () {};
MOCKOWANIE TWORZENIA OBIEKTU
WEBSOCKET + REDUX
const myFakeObject = {

mockFn: jest.fn()

};



window.MySuperObject = jest.fn(() => myFakeObject);
WEBSOCKET + REDUX
▸ Tworzymy middleware obsługujący komunikację z websocketem i reduxem
▸ Pamiętamy o testach :)
ZADANIE 5 - KOMUNIKACJA Z SOCKETEM
Adres serwera: ws://192.168.88.84:8080
{

data: '{"type":"users","count":10}'

}

More Related Content

PDF
Budowa elementów GUI za pomocą biblioteki React - szybki start
PPTX
Prezentacja php3
DOCX
Zajecia4 progbiz
PPT
Podstawy php
PPT
Podstawy php
PDF
TypeScript as a runtime error terminator
PDF
Podstawy AngularJS
PDF
Ansible w 5 minut
Budowa elementów GUI za pomocą biblioteki React - szybki start
Prezentacja php3
Zajecia4 progbiz
Podstawy php
Podstawy php
TypeScript as a runtime error terminator
Podstawy AngularJS
Ansible w 5 minut

Similar to React Ninja - Warsztaty TDD + React + Redux + Websockets (6)

PDF
DreamLab Academy #12 Wprowadzenie do React.js
PDF
react-pl.pdf
PPTX
Aplikacje internetowe real-time w oparciu o React/Redux
PDF
Wprowadzenie do React
PDF
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
PDF
Elm jako inspiracja
DreamLab Academy #12 Wprowadzenie do React.js
react-pl.pdf
Aplikacje internetowe real-time w oparciu o React/Redux
Wprowadzenie do React
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Elm jako inspiracja
Ad

More from The Software House (20)

PDF
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
PDF
Uszanowanko Podsumowanko
PDF
Jak efektywnie podejść do certyfikacji w AWS?
PDF
O co chodzi z tą dostępnością cyfrową?
PDF
Chat tekstowy z użyciem Amazon Chime
PDF
Migracje danych serverless
PDF
Jak nie zwariować z architekturą Serverless?
PDF
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
PDF
Feature flags na ratunek projektu w JavaScript
PDF
Typowanie nominalne w TypeScript
PDF
Serverless Compose vs hurtownia danych
PDF
Testy API: połączenie z bazą danych czy implementacja w pamięci
PDF
Jak skutecznie read model. Case study
PDF
Firestore czyli ognista baza od giganta z Doliny Krzemowej
PDF
Jak utrzymać stado Lambd w ryzach
PDF
Jak poskromić AWS?
PDF
O łączeniu Storyblok i Next.js
PDF
Amazon Step Functions. Sposób na implementację procesów w chmurze
PDF
Od Figmy do gotowej aplikacji bez linijki kodu
PDF
Co QA może i czego nie powinien się bać?
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Uszanowanko Podsumowanko
Jak efektywnie podejść do certyfikacji w AWS?
O co chodzi z tą dostępnością cyfrową?
Chat tekstowy z użyciem Amazon Chime
Migracje danych serverless
Jak nie zwariować z architekturą Serverless?
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Feature flags na ratunek projektu w JavaScript
Typowanie nominalne w TypeScript
Serverless Compose vs hurtownia danych
Testy API: połączenie z bazą danych czy implementacja w pamięci
Jak skutecznie read model. Case study
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Jak utrzymać stado Lambd w ryzach
Jak poskromić AWS?
O łączeniu Storyblok i Next.js
Amazon Step Functions. Sposób na implementację procesów w chmurze
Od Figmy do gotowej aplikacji bez linijki kodu
Co QA może i czego nie powinien się bać?
Ad

React Ninja - Warsztaty TDD + React + Redux + Websockets

  • 3. STACK ▸ React ▸ Redux ▸ Create React App ▸ Enzyme ▸ Jest ▸ Jasmine
  • 4. TDD
  • 5. TDD ▸ Test-Driven Development ▸ nie służy stricte testowaniu ▸ pomaga wyeliminować błędy w zrozumieniu działania CZYM JEST TDD?
  • 6. TDD STRUKTURA TESTU function add(a, b) { ... } describe('Adding function', () => { it('adds two numbers', () => { expect(add(1, 2)).toBe(3); }); it('fails when on wrong params given', () => { expect(add()).toBeNull(); }) });
  • 8. TDD describe('My React Component', () => { it('renders a number passed through a prop', () => { // ? }); });
  • 9. TDD describe('My React Component', () => { it('renders a number passed through a prop', () => { const wrapper = render(<Component prop={2}/>, document.getElementById('app')); expect(wrapper.find('span').text()).toEqual('2'); }); });
  • 10. TDD import { shallow, mount } from 'enzyme'; describe('My React Component', () => { it('renders a number passed through a prop', () => { const wrapper = shallow(<Component prop={2}/>); expect(wrapper.find('span').text()).toEqual('2'); }); it('renders a number passed through a prop', () => { const connect = jest.fn(); const wrapper = mount(<Component onconnect={connect}/>); expect(connect).toBeCalled(); }); });
  • 11. TDD ▸ Instalacja paczek ▸ yarn add enzyme ▸ yarn add react-addons-test-utils ▸ Test dla komponentu licznika osób na stronie ▸ Counter component displays a number passed to a prop ▸ Counter component displays 0 if props hasn’t been passed ▸ Komponent licznika ZADANIE 1 - PIERWSZY KOMPONENT I TESTY http://airbnb.io/enzyme/docs/api/index.html
  • 12. REDUX
  • 13. REDUX CZYM JEST REDUX? Redux jest przewidywalnym kontenerem stanu aplikacji JS. TRZY ZASADY ‣ Single source of truth ‣ Stan jest tylko do odczytu ‣ Zmiany wykonujemy za pomocą „czystych” funkcji
  • 14. REDUX ACTIONS & ACTION CREATORS const ADD_TODO = 'todos/ADD_TODO'; { type: ADD_TODO, payload: { text: 'Build my first Redux app' } } const addTodo = (text) => ({ type: ADD_TODO, payload: { text } });
  • 15. REDUX REDUCER const initialState = []; const todoReducer = (state = initialState, action) => { switch (action.type) { default: return state; } };
  • 16. REDUX REDUCER const initialState = { todos: [] }; const todoReducer = (state = initialState, action) => { switch (action.type) { case ADD_TODO: return [ ...state.todos, { text: action.payload.text, completed: false } ]; default: return state; } };
  • 17. REDUX SKŁADANIE REDUCERÓW import { combineReducers } from 'redux'; const appReducer = combineReducers({ todo: todoReducer, routing: routerReducer });
  • 18. REDUX ▸ Tworzymy akcję do aktualizacji stanu licznika ▸ Tworzymy reducer, obsługujący aktualizację ▸ Pamiętamy o testach ▸ Users actions creates update action ▸ Users reducer returns default state ▸ Users reducer updates counter ZADANIE 2 - AKCJE I REDUCERY { "users": { "count": 2 } }
  • 20. CONTAINER ▸ „pomost” pomiędzy komponentem, a reduxem ▸ umożliwia użycie z reduxem już istniejących komponentów bez potrzeby ingerowania w ich kod ▸ ułatwia separację zadań ▸ pobieranie/przetwarzanie danych ▸ prezentacja danych CZYM JEST KONTENER?
  • 22. CONTAINER import { connect } from 'react—redux'; import { ToDo } from './todo.component'; import { addTask } from '../todo/todo.actions'; const mapStateToProps = (state) => ({ list: state.taskList }); const mapDispatchToProps = (dispatch) => ({ add: task => dispatch(addTask(task)) }); export const ToDoContainer = connect( mapStateToProps, mapDispatchToProps )(ToDo);
  • 23. CONTAINER ▸ Tworzymy kontener dla naszego komponentu ZADANIE 3 - REDUX + REACT
  • 25. TESTOWANIE ZACHOWANIA KOMPONENTÓW TESTOWANIE WYWOŁANIA FUNKCJI const myProps = {
 mockFn: jest.fn()
 };
 myProps.mockFn(10); 
 expect(myProps.mockFn).toBeCalledWith(10);
  • 26. TESTOWANIE ZACHOWANIA KOMPONENTÓW SYMULOWANIE ZMIANY PARAMETROW const connect = jest.fn(); const wrapper = shallow(<SomeComponent displayButton={false} />); expect(wrapper.find('button').length).toBe(0); wrapper.setProps({displayButton: true}); expect(wrapper.find('button').length).toBe(1);
  • 27. TESTOWANIE ZACHOWANIA KOMPONENTÓW SYMULOWANIE INTERAKCJI const clear = jest.fn(); const wrapper = shallow(<MyComponent clearFields={clear} />); wrapper.find(‚button').simulate('click'); expect(clear).toBeCalled();
  • 28. TESTOWANIE ZACHOWANIA KOMPONENTÓW ▸ Komponent wyświetlający aktualny stan połączenia z socketem (connected, not-connected, connecting) ▸ Komponent pozwalający wykonać akcję podłączenia się do systemu ▸ Akcje i reducery do komunikacji z socketem ▸ Pamiętamy o testach :) ZADANIE 4 - PRZYGOTOWANIE DO IMPLEMENTACJI KOMUNIKACJI Z SOCKETEM { "socket": { "status": "connected" } }
  • 30. WEBSOCKET OD CZEGO ZACZYNAMY ? const ws = new WebSocket(url); const ws = new WebSocket(process.env.REACT_APP_SOCKET_URL); PRZECHOWYWANIE ADRESU SERWERA REACT_APP_SOCKET_URL=ws://localhost:8080
  • 31. WEBSOCKE METODY ws.onmessage = ({data}) => {...}; ws.onopen = () => {...};
  • 34. WEBSOCKET + REDUX DISPATCH MIDDLEWARE MIDDLEWARE MIDDLEWARE REDUCERS
  • 35. WEBSOCKET + REDUX MIDDLEWARE export const middleware = function(store) {
 return function (next) {
 return function (action) {
 next(action);
 }
 }
 }; WERSJA ES6 export const socketMiddleware = store => next => action => {...}
  • 36. INTEGRACJA Z REDUX const store = createStore(
 appReducer,
 compose(
 applyMiddleware(
 socketMiddleware,
 routerMiddleware(browserHistory)
 ),
 window.devToolsExtension ? window.devToolsExtension() : f => f
 )
 ); WEBSOCKET + REDUX
  • 37. MOCKOWANIE WEBSOCKETU window.WebSocket = window.WebSocket || function () {}; MOCKOWANIE TWORZENIA OBIEKTU WEBSOCKET + REDUX const myFakeObject = {
 mockFn: jest.fn()
 };
 
 window.MySuperObject = jest.fn(() => myFakeObject);
  • 38. WEBSOCKET + REDUX ▸ Tworzymy middleware obsługujący komunikację z websocketem i reduxem ▸ Pamiętamy o testach :) ZADANIE 5 - KOMUNIKACJA Z SOCKETEM Adres serwera: ws://192.168.88.84:8080 {
 data: '{"type":"users","count":10}'
 }