w Praktyce
7 godz. 1 min · Angular · Full-stack i Programowanie
Mateusz KuleszaSenior Software Developer, Konsultant, TrenerPodstawą produktywnej pracy z angularem jest możliwość zagwarantowania że wszystko działa bez potrzeby wielokrotnego “przeklikiwania” poszczególnych ekranów. W pierwszej części kursu omawiam więc temat testów automatycznych.Już po obejrzeniu pierwszych lekcji zobaczysz dlaczego warto testować kod i jak dzięki narzędziom dostarczonym z angularem jest to proste. Zobaczysz jak testowanie automatyczne pozwoli zaoszczędzić Ci wiele godzin spędzonych na szukaniu błędów.
Za jakość aplikacji odpowiada nie tylko to czy działa ona poprawnie, ale w dużej mierze decyduje o tym dobry interfejs użytkownika oraz UX, czyli user experience. Dwie kolejne sekcje kursu poświęcone są właśnie dobremu UI oraz UX. Omawiam typowe problemy w oparciu o zasady i wskazówki specyfikacji Google Material Design - jednej z najbardziej szczegółowych specyfikacji UX. Wszystkie przykłady UI zarówno w wariantach desktopowych jak i mobilnych omówione są na przykładzie Angulara oraz obszernej biblioteki komponentów Angular Material. Zobaczysz nie tylko jak korzystając z gotowych komponentów błyskawicznie budować nowe funkcjonalności, ale przy okazji omówimy wiele praktycznych wskazówek oraz dobrych praktyk UX które warto wykorzystać w Twoich aplikacjach.
W ramach budowania interfejsów skupimy się na najmniejszych szczegółach takich jak prawidłowe zachowanie linków, przycisków oraz wskaźników przechodząc stopniowo do coraz większych elementów aplikacji takich jak nawigacja, układ strony, paski nawigacyjne czy okna dialogowe. Przy każdym etapie czeka Cię masa wskazówek, przykładów i rozwiązań typowych problemów user experience.
Jednak UX to nie tylko wygląd i zachowanie pojedynczych elementów. W ostatnich sekcjach kursu dowiesz się jak projektować bardziej złożone interakcje z użytkownikiem. Zobaczysz wieloetapowe formularze kreatora oraz dowiesz się jak zarządzać stanem aplikacji oraz różnymi źródłami danych. Pokaże Ci jak zbudować samodzielnie sortowane, filtrowane i stronicowane źródła danych oraz połączyć je z różnymi komponentami UI takimi jak listy czy datagrid.
Na koniec kursu zobaczysz jak możemy różne gotowe elementy UI połączyć w przepływ ekranów budując ścieżkę użytkownika. Zobaczysz jak prawidłowo zaprojektowane komponenty wraz z dobrze zaplanowanym UX pozwalają być niesamowicie produktywnym jednocześnie nie poświęcając jakości czy dobrej architektury aplikacji.
Jest to kurs dla osób które już pracowały z angularem i chciałyby wyjść poza pojedyncze techniki oraz poznać proces projektowania aplikacji w praktyce z uwzględnieniem najlepszych praktyk programistycznych oraz user experience. Zarówno w wariancie webowym jak i projektując pod urządzenia mobilne.
Angular 6, 7, 8+
W poprzedniej lekcji testowaliśmy interakcje tutaj z użytkownikiem
czyli zasymulowaliśmy kliknięcie w przycisk tutaj
korzystając z trigger event handler a następnie przy użyciu szpiega
przypiętego na metodzie tutaj edit naszego komponentu określiliśmy
że tamta została wykonana ale także przepuściliśmy tutaj szpiega
do oryginalnej metody żeby zobaczyć także czy udało tutaj tryb edit
mode na true w tej lekcji zrobimy coś bardziej złożonego
dodamy sobie tutaj jeszcze powiedzmy input czyli pole tekstowe
tutaj zwykły tekst i zobaczymy tutaj jak zrobić interakcje
nie jest przyciskiem nie kliknięcie tylko interakcje tutaj w dwie strony z
takim elementem input i teraz pierwsza rzecz zapisze sobie to pierwsza
rzecz w naszym polu input powinno się
pojawić ta sama wiadomość ten sam tutaj tekst który znajduje się w tym
polu żebyśmy mogli to edytować czyli it should nie it should
no właśnie it should show task
name inside input i tutaj
może zrobimy też bardzo podobnie jak dodamy sobie klasę żeby łatwiej taki element znaleźć
class class name powiedzmy input
okej czyli chcemy sprawdzić czy
po wyrenderowaniu czy w tym inpucie czy jego value jego wartość tego
pola tutaj formularza jest taka sama jak tutaj message czyli
zobaczymy znajdziemy po pierwsze ten element czyli const powiedzmy input
znajdziemy go używając znowu fixture debug element
query by css i
użyję tej naszej klasy task name input okej
i chcemy sprawdzić czy input native
element tutaj cały czas nie mają podpowiadania więc warto
by się zastanowić tutaj nad tym żeby w ogóle określić sobie typ że to jest as
html input element tutaj
jeszcze brakuje średnika teraz i teraz mamy wszystkie
podpowiedzi które dotyczą elementów html typu input więc
powinniśmy mieć na przykład tutaj value może w ten sposób no
i możemy sprawdzić teraz czy to value czyli możemy zrobić expect i
sprawdzić czy value to equal no i tutaj powinniśmy
mieć tą samą wartość co wcześniej czyli powinniśmy mieć message
works tu oryginalny tekst zrobię to jeszcze inaczej sprawdzę
czy faktycznie ma on wartość tu jest komponent message po ten tekst dokładnie taki
sam tutaj jak wcześniej sprawdzaliśmy teraz zapisze no
i okazuje się że jest problem bo w nim może znaleźć tutaj tego elementu czyli native element
of null tu jeszcze raz zapisze i mamy task name input
szukamy task name input
click niezapisany tu jak widzisz już mamę dokładnie
problem czy udało się znaleźć element ale on nie zawiera nie ma prawidłowej
wartości czyli tu nie pojawiła się wartość w środku no bo oczywiście w html'u
nie mamy takiego bindowania więc spróbuj naprawić tutaj tą sytuację dopiszę
sobie tutaj odpowiednie bindowanie że value tego elementu ma być równe
dokładnie temu naszemu message zobaczmy teraz my
mamy sukces czyli jak widzisz można bardzo łatwo znaleźć pole określić
sobie jakieś jego dowolne właściwości na przykład value i zobaczyć czy bindowanie
działa prawidłowo to jest w jedną stronę my chcemy wyświetlić
tutaj informacje spróbuj teraz zrobić to w drugą stronę czyli
zobaczyć co się stanie kiedy użytkownik wprowadzi jakieś zmiany no i wtedy czy
te zmiany będą zsynchronizowane z powrotem do naszego message czyli
w kolejnym teście it should
no właśnie it should update
task name
when input value
changes i tutaj trzeba być bardzo ostrożnym co to znaczy
tutaj changes co znaczy że zostały wprowadzone zmiany jak wiesz pole
tekstowe tutaj może reagować na każdy klawisz na key up key down
key press może być na change czyli dopiero na opuszczenie pola
ale mamy też taki nowy event która nazywa się input który reaguje na każdą zmianę
tego pola niezależnie od powodu tak żeby control z czy wytnę treść
nie ważne czy używasz klawiatury czy myszki czy pole się samo wypełnia
na przykład przy użyciu jakieś automatycznego wypełniania w przeglądarce to input tutaj bardzo
fajnie zadziała więc spróbujmy może w ten sposób znowu znajdę sobie ten element
input tak samo jak zrobiłem to wcześniej i teraz ja chcę ustawić
wartość i zobaczyć czy ona się pojawi u nas tutaj w message czyli
chcemy na końcu w teście sprawdzić czy w drugą
stronę komponent message tym razem tu i
equal changed value
na przykład w taki sposób jak byśmy ten changed value przypisali do naszego
elementu czyli jeszcze raz ja zrobię tutaj const może tutaj się równa
input native element as html
input element i do elem do value przypiszę
sobie nasz zmieniony tekst i niby wszystko w porządku bo znaleźliśmy
element tutaj html do elementu html przypisuje
nową wartość no i teraz tutaj właśnie test
powinien pokazać że to jest nieprawda tak mamy błąd
mamy message works a chcielibyśmy changed value czyli jak widzisz tutaj zmiana wartości nie
zmienia naszego message mamy te bindowania teraz w angularze
nie ma takiej opcji to jeżeli sobie mógł obserwować zmiany value i automatycznie
zmieniał w angularze muszę obsłużyć jakieś zdarzenie czyli muszę tutaj wymyślić
jakieś zdarzenie które będzie na to reagowało teraz jeśli zrobię tutaj sobie na przykład key
app key down to okej ale ja chcę żebyś to jeszcze
szybciej chciał żeby przy każdej zmianie czyli jeżeli użyję tego zdarzenia typu input i
przy każdej zmianie w każdej zmianie wartości tą nową
wartość przypiszemy do message czyli message równa się event target
value czyli przy każdej zmianie tutaj w
wartości naszego input'a ja chcę aktualizować ten
message czy on się tutaj zaktualizował nam wewnątrz komponentu zapiszę i
niestety to nadal nam nie działa to się nie zmienia żeby
przetestować taką sytuację żeby przetestować wiązanie my musimy faktycznie zasymulować
wystąpień takiego zdarzenia jak input jeśli ja po zmianie tej
wartości zrobię sobie coś takiego jak input czyli nasz tutaj
element tutaj input i zrobimy tak jak
wcześniej miałem przy clicku trigger event handler input może
tutaj zmienę troszkę nazwę aby to się nie myliło i
tu musimy przekazać jeszcze szczegóły zdarzenia teraz mimo że ja wykonałem
to zdarzenie to nadal to się nie zmienia zwróć uwagę że ja
wartość pobieram event target value czyli tutaj
jak chcesz symulować tego typu zdarzenia to musisz także zasymulować właściwości
tego zdarzenia czyli jeśli ja to wyciągam wartość z event target value to
po tej stronie muszę zasymulować dokładnie taki obiekt zdarzenia który zawiera ten target
który tutaj mam i zawiera value
tak się składa że nasz element html w którym my ten value ustawiliśmy on
tutaj możemy po prostu podstawić go jako target i on powinien sobie pobrać
value wtedy automatycznie zobaczymy jak widzisz masz
teraz 11 na 11 sukces jest to fajna metoda bo
pozwala tobie jak widzisz przekazać swoje własne szczegóły eventów własne
szczegóły zdarzenia masz bardzo ścisłą kontrolę nad tym co się dzieje nie
mniej jest to troszeczkę pracy tutaj żeby to zrobić część osób szczególnie
jeśli to zdarzenie jest bardziej skomplikowane preferuję wykorzystać natywne zdarzenie
przeglądarki czyli zamiast trigger event handler po prostu na elemencie dispatch
event new event tutaj nazwa event'a input i
to już praktycznie wystarczy event stworzony w ten sposób czyli
natywny obiekt event z przeglądarki zdispatch'owany w ten sposób
czyli także natywnie będzie automatycznie miał wszystkie te pola w
tym target value i tak dalej ustawiony przez przeglądarkę jak widzisz jest to troszeczkę
krótszy troszkę szybszy sposób ma on jednak tą wadę że
tutaj nie mamy kontroli na tym eventem tutaj łatwo zasymulować bardzo skomplikowany cały
event ale nie możemy żadnych opcji zmienić tutaj natomiast mamy
pełną kontrolę ale niestety ta kontrola wymaga od nas zbudowania
wszystkich szczegółów zdarzenia ja oczywiście polecam zapamiętać że jest to
opcja alternatywna ale w testach polecam tobie zawsze pamiętać tutaj o tej
wersji bo tutaj faktycznie mamy kontrolę nad tym co my
symulujemy co my podstawiamy pod event i nie ma sytuacji że
nasz event przez przypadek bo przeglądarka stworzyć coś innego że będziemy mieli nieoczekiwane rezultaty
tak więc może spotkasz się z taką wersją z natywnym uruchamianiem
prawdziwych zdarzeń przeglądarki ja polecam tobie tą wersję angularową gdzie my
symulujemy zdarzenie i musimy zasymulować niestety wtedy jakby
te właściwości ale tylko te właściwości które chcemy tutaj przetestować więc
jeśli nasz komponent zostanie rozbudowany dodamy jakieś nowe funkcje będziemy sprawdzać jakieś
nowe opcje eventów no to wtedy ten test automatycznie przestanie nam działać i będziemy
wiedzieli że coś popsuliśmy więc takie podejście jakby jest o tyle lepsze że ja
tylko testuję konkretne właściwości eventu te z których faktycznie korzystam
i przypadkiem się nie pojawią inne tutaj eventy czyli jak
widzisz w ten sposób możesz w dwie strony zsynchronizować tutaj pole formularza i możemy
przetestować zarówno czy wartości się pojawiły w tym polu pamiętaj zawsze
jakbyś chciał je zmienić żeby jeszcze detect changes wykonać no
i tutaj jeśli chcemy obserwować jakie zdarzenia to tak jak przy clicku możemy
tutaj triggerować dowolne zdarzenie key up key down input pamiętaj
tylko żeby przekazać wszystkie tutaj potrzebne informacje na temat tego eventu
który chcesz zasymulować czyli w ten sposób możesz
łatwo tutaj testować interakcje z elementami formularza tak
samo zasada byłaby tu dla checkbox'a dla selecta dla radio box żeby
pamiętać o odpowiednim tutaj evencie i odpowiedniej tutaj właściwości
odpowiedniej dla danego typu pola oczywiście w dużych aplikacjach
rozbudowanych aplikacjach nie zarządzamy polami ręcznie w ten sposób tylko
on ma tego odpowiednie mechanizmy taki jak ng model czy formularze
reaktywne i te też można testować jednak testuje
się troszeczkę w inny sposób niż tutaj ale o tym powiemy sobie
już kolejnej lekcji tak więc do zobaczenia