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 i stworzyliśmy komponent zadania które wyświetla właśnie
zadanie możemy kliknąć edytuj i edytować tą treść zadania nie mniej
tutaj wszystko było widoczne cały czas ja pozwoliłem sobie dodać tutaj takie ukrywanie
pierwszego diva i drugiego diva że dopiero jak klikniemy edit to nam się pojawia
drugi dive to jednak spowodowało że wszystkie testy które właśnie
oczekiwały tutaj tego komponentu tego inputa i możliwości edycji
nagle przestały działać bo nie było to widoczne tu szybko
naprawiłem to po prostu wszystkie testy które właśnie wymagają tego trybu edycji objąłem
sobie w dodatkowe tutaj describe i tutaj dodatkowe before each
czyli wszystkie tutaj testy znajdujące się przed tym dodatkowym
describe one wszystkie działają w trybie jakby nie edit mode
czyli w trybie wyświetlania treści nie w trybie edycji natomiast tutaj wszystkie testy
które potrzebują jakiejś właśnie specjalnej opcji specjalnych ustawień nie
musiałem przy każdym tekście kopiować i wklejać dokładnie tego edit mode true edit
mode true żeby przełączyć go za każdym razem tylko właśnie wszystkie te które wymagają tego
edit mode'a po prostu objąłem sobie w dodatkową grupę tak więc teraz mamy
przełączanie pomiędzy trybem tutaj widoczności a trybem edycji okej
to wszystko fajnie ale ten oponent jakby nie nadaje się jeszcze do użytku w aplikacji
czego tu brakuje to faktycznie komunikacji ze światem czyli właśnie
wejść i wyjść input output żeby komponent mógł dostać jakieś dane
zadanie do wyświetlenia i kliknę tutaj akurat kliknę zapisz żebym
mógł te zmiany faktycznie przesłać jakimś rodzicowi wyemitować do
góry poprzez output pytanie jak taki input
output przetestować jak w testach podstawić tutaj dane tak żebym
mógł zobaczyć czy faktycznie te inputy działają prawidłowo tutaj daliśmy tylko message
a chcielibyśmy mieć powiedzmy tutaj cały task czyli powiedzmy chciałbym mieć task
typu task tutaj tymczasowy interfejs
sobie stworzę task powiedzmy że task ma jakieś id i ma
jakiś title string czyli treść tego zadania do
wykonania czyli tutaj chcielibyśmy mieć właśnie taki obiekt typu task i to
chciałbym żeby to był input i teraz jak takie coś przetestować
moglibyśmy stworzyć dodatkowy komponent które wyrenderuje ten komponent
testować je razem jednak chcemy żeby te testy jednostkowe więc jeśli
nie masz specjalnych jakichś wymagań na temat komunikacji nie chcesz testować bindowań
a nie chcesz testować angular tylko chcesz testować logikę twojego komponentu to
bardzo fajną rzeczą jest to że możemy po prostu potraktować taki task tak
samo jak message czyli jako zwykłe pole tej naszej klasy i
tutaj nie skupiać się na bindowaniu testować bindowań tylko przestestować samą logikę
od tego zaczniemy i powinno być jeśli jest potrzeba naprawdę to
jak możemy ewentualnie przetestować faktycznie czy te bindowanie działają prawidłowo
okej czyli na chwilkę tutaj zamknę panel z testami u
nich będzie zmieścimy się jakoś i teraz tak jak to zrobić faktycznie żeby tutaj działał
nam ten input oczywiście musimy teraz przerobić testy dlatego
że testyst oczekują że pracujemy cały czas na message ja poszukam wszędzie gdzie mamy tutaj
message message message okej
i postawimy że to nie będzie message tylko to będzie title to będzie
nasz tytuł naszego taska naszego zadania czyli
tutaj zacznijmy od początku should render task name czyli
na początku oczekuję już jakiegoś tutaj task name więc
zaczniemy żeby na samym początku jak tworzymy komponent żeby już mu przekazać jakiś
task name czyli tutaj mamy jak pamiętasz pierwsze renderowanie przed pierwszym renderowaniem
chciałbym przekazać jakiś task name w ogóle jakiś task czyli tu jak widzisz mogę przypisać sobie
task i przyjmiemy sobie tutaj jakiś taki mockup'owy testowy
task czyli tu będzie title test task
works w
ten sposób i teraz sprawdzimy pierwszy test czy jeśli
wpiszę test task tutaj znajdę
task name to czy task name na starcie jako pierwszy element wyświetli test task
works i oczywiście będzie to błąd skupić na tym teście na razie pojedynczym jak pamiętasz tutaj fit
i zobaczmy jak to naprawić tutaj na
starcie nie musi tu już być message tylko jak już będzie to task title
sprawdźmy i udało się pierwszy
test zadziałał to zobaczmy co dalej okazało
się że jakiś inny test przestał działać tutaj task should render updated
czyli zmiany nie są prawidłowo wyświetlane spróbujemy tutaj komponent
task title updated name zapiszę
mamy sukces jak widzisz w ten sposób można wprowadzić nowe
wymagania nowe do aplikacji aktualizując testy
zmienić jeden dwa testy które nas interesują i przy okazji sprawdzić czy nie popsuliśmy innych testów czyli
wprowadzając nową logikę nowe zachowanie możemy łatwo sprawdzić czy przez przypadek nie
popsuliśmy jakiegoś innego wymagania jakieś innego testu zobaczymy jednak
tutaj co z edit edit tutaj wymaga jeśli kliknę edit to
się przełącza na edit mode to się nie zmieniło zobaczmy jak jesteśmy w edit mode czy
tutaj nam się coś zmieni jeśli stworzysz taką dodatkową sekcję describe to też tutaj fajnie
w raporcie jak widzisz pojawi nam to się jako też wcięcie czyli możesz bardzo
fajnie zagnieździć sobie tutaj tryby logikę stale twoich komponentów że jeśli w tym
konkretnym stanie zachowuje się tak a w tym innym konkretnym stanie zachowuje się na przykład w ten
sposób tu już mamy nasz właśnie komponent wyświetlony w trybie
edit ostatni test tutaj jaki się wykonuje jest wtedy edit czyli byśmy wzięli message
mamy jakiś komunikat błędu i save okej zobaczymy co dalej
czy tu mamy gdzieś jakiś message bo chcemy na message czyli
tutaj should show task name inside
input czyli sprawdzamy czy to samo jest w inpucie czy to samo w message
i tu widzisz jakby ten test nie przechwycił tego że zmienił się message
bo to dalej działa tak samo prawidłowo
czyli zmienił się nam tytuł a pozostała edycja tutaj się nie zmieniła
czyli tutaj widzisz ten test nie przechwycił nam prawidłowo zmiany
nie wychwycił że tutaj coś się popsuło czyli tu trzeba było sprawdzić nie tylko czy
show task name input no właśnie przesłać by komponent
task title czy
to się zgadza zmienimy i będzie to błąd czyli teraz
message works test test works czyli okazuje się że tutaj w inpucie
mamy nieprawidłową wartość musi być to task title
okej teraz kolejny is edit mode should update
task should update task
czyli kolejny test teraz pisał działać i to będzie bardzo podobnie zobaczmy
no tu edit mode jak już jest niepotrzebny dlatego że ten edit mode przeniosłem tutaj do
góry do describe
i teraz update tutaj też gdzieś mamy o właśnie message czyli masę zmieniamy także
na task title jak widzisz
krok po kroku możemy przejść przez wszystkie funkcjonalności aplikacji upewnić się że w
każdym z tych kroków aplikacja nadal działa prawidłowo nawet przy zmianie
tutaj właśnie jej struktury danych i ostatni w tej będzie działał bez żadnych
zmian dlatego żeby sprawdzamy czy nie ma błędów błędy są niezależne od struktury naszych
danych czyli zapisałem jak widzisz input nowy który dodałem bez
problemu działa dlatego że jeśli tutaj podstawie sobie task
pod input to nam to działa jeśli zmienimy tego taska
w ten sposób to
nam się to wyświetli i okej tutaj właściwie
mogę zrobić osobny test który sprawdzi czy jak podmienienie cały
task czy to też zadziała czy możemy też zrobić taki test
który cały task podmieni albo tu od razu możemy spróbować sobie zmienić
nie sam name tylko zmienić task
na should render updated task
czyli podmieniamy całego taska na jakiś inny task o
ten sam po prostu ze zmienionym name'em i sprawdzam czy to się wyrenderuje prawidłowo
okej czyli już można input potraktować tutaj jako zwykłe pole i
po prostu go przypisać do elementu w takim razie pytanie co z outputami
czy na przykład jeśli ktoś kliknie save to jak te informacje
poprzez output przekazać do góry do rodzica ja tutaj przejdę
z naszej sekcji edit mode bo tylko tutaj będziemy mogli nasłuchiwać tych zmian
i tutaj zrobimy sobie it should emit
save event when save
clicked czyli jeśli klikniemy
przycisk to emitujemy zdarzenie i teraz to możemy znowu rozbić na dwa osobne
testy na jeden test który sprawdza czy kliknięcie save wywołuje funkcję
save a drugi czy wywołanie funkcji save emituje zdarzenie byłoby to
troszkę bardziej poprawne spróbujmy zrobić to w ramach jednego testu najwyżej rozbijemy
go na dwa czyli co musimy znaleźć przycisk tak zobaczysz tu
gdzieś już znajduje właśnie save button pożyczymy
sobie save button i teraz jeśli go klikniemy
to się powinna wywołać funkcja save okej czyli
klikniemy button click
zasymulujemy tutaj odpowiednie zdarzenie
moglibyśmy sprawdzić czy ta funkcja savee się faktycznie wykona czy jak
pamiętasz spy on pozwalał nam dodać szpiega na
przykład na komponent save w metodzie save
spy go nazwę szpiega i możemy teraz przetestować po
pierwsze czy funkcja została wykonana czyli expect savespy
to have been called okej
zobaczymy tu coś poszło nie tak
czyli tu w komponencie na click powinno to zadziałać klasa
save button emitujemy
tutaj click i
powinna się wykonać funkcja save czyli coś to się jeszcze nie zgadza
no tak szpiega stworzyliśmy za późno oczywiście muszę szpiega przypiąć
przed clickiem i wszystko powinno być teraz w porządku tak testy przeszły
czyli pamiętasz żeby właśnie zamockować funkcję nim ją klikniemy bo nie
ma to sensu okej teraz co z outputem jak zamockować output zacznijmy tutaj od
końca troszeczkę stworzymy ten output zobaczymy jak go można przetestować zdarzenie
miało nazywać się save event i tu mały problem zróbmy
zdarzenie save
no właśnie bo funkcja nazywa się save zróbmy saved saved
tu oczywiście będzie new event emitter czyli coś na czym
możemy wyemitować to zdarzenie i będziemy tutaj chcieli wyemitować obiekt typu
task czyli wyemitować task który chcemy
zapisać okej i teraz
jak to przetestować bardzo prosta rzecz po prostu zobacz że output jeśli
tu nie będziemy patrzeć na bindowanie to jest po prostu event emitter a event
emitter zobaczymy sobie component saved ma taką metodę jak emit
czyli możemy emitować zdarzenia ma metody subscribe czyli
możemy się też zasubskrybować naprawdę jeśli my używamy nawiasów okrągłych gdzieś
na komponencie żeby się zasubskrybować na przykład na wydarzenie click i tak dalej tutaj na
przykład jak tu się subskrybowalimy na na przykład click'a to tak
naprawdę tutaj jeśli użyje naszego jakiegoś zdarzenia na przykład saved
to wtedy angular w naszym imieniu za nas się zasubskrybuje zanim się wejdzie zobaczę
co to jest za output o nazwie saved i się zasubskrybuje
za nas żeby wykonać tą funkcję która tutaj jest wpisana tutaj
my zasymulujemy angulara żeby nie budować specjalnego komponentu tylko po to żeby to sprawdzić
my zasymulujemy to samo zachowanie zrobił angular czyli
się zasubskrybujemy na to zdarzenie tu
powinniśmy dostać task obiekt typu task i
teraz tak musimy sprawdzić czy to jest ten sam task tu ma
takie same właściwości czy ten który przekazany był tutaj do komponentu czyli
pobierzemy sobie z komponentu task
to save
i sprawdzimy tu będzie ten sam task który był tu wyemitowany czyli component saved
subscribe task i tutaj expect i
sprawdzimy czy task to save i
niech to be bo jeśli ten w środku będziemy je modyfikować to
jest szansa że powstanie kopia czyli nie chcemy porównywać czy to jest ten sam obiekt chcemy porównać czy to jest taki
sam obiekt więc nie to be to equal widzisz to be porównuje po
prostu przy użyciu trzech równa się a to equal porównuje
głęboką tutaj wartość porówna dokładnie wszystkie pola i zobaczmy
czy to będzie tutaj task czy ten który znajduje się
w środku będzie takim samym jak ten który tutaj jest
wyemitowany możesz to sprawdzić jakieś zmiany jeszcze wprowadzić ale
na razie przetestujmy to i uwaga bo jeśli pamiętasz masz jakieś asynchroniczne
operacje to warto by zabezpieczyć się tutaj i
sprawdzić czy to na pewno nam wszystko działa okej spróbujmy
w takim razie odłączyć ten test co masz mi to nie działa jak
widzisz ten test w ogóle nie mam nie sprawdza niczego dlatego że test wykonuje
się i ten expected jakby nigdy nie jest uruchamiany więc musimy tutaj zapewnić
że ten test się wykona możemy spróbować zrobić async ale
nam się tu się nie powinno tutaj nie nie zadziała nam sam async bo de facto
ten subscribe może być synchroniczny czyli jak widzisz też tego na mnie sprawdza trzeba by faktycznie
zrobić sobie tutaj dom czyli callback tu pewnie ten done
na pewno był wykonany i w tej sytuacji o tu
gdzie czekał czekał i jeszcze raz czekał i się nie doczeka na wykonanie tego
testu to jak widzisz tutaj mamy ładnie informacje o tym że ten
expect w środku to nigdy nie został wykonany teraz jak to naprawić no
nasza funkcja safe musi faktycznie wyemitować te zdarzenie save na które
się zasubskrybowaliśmy czyli przy savie tutaj wprowadzimy
sobie this saved emit
i wyemitujemy nasz task okej
i tu jeszcze coś jest nie tak za długo to trwa mamy
dalej timeout czyli tak nie wykonaliśmy funkcji
save musimy najpierw
się zasubskrybować znowu kolejność tu ma znaczenie okej
w ten sposób czyli zobacz najpierw tutaj zadanie
musimy wiedzieć które czekamy aż ono będzie zapisane klikamy
zapisz i dopiero sprawdzamy czy po pierwsze dobre zostało nam
wysłane a po drugie czy funkcja safe spy była wykonana i teraz
to nam jeszcze nie zadziała dlatego że ten szpieg nie przepuści wartości no
to faktycznie zadziałało musimy tutaj and
call true czyli musimy przepuścić okna na funkcje bo inaczej ta funkcja się nigdy nie wykona ona
nigdy nie wyemituje no i ten subscribe nam nigdy nie zadziała
i mamy 14 na 14 sukces więc to się może wydawać skomplikowane ale
na prawdę tutaj kwestia jest tylko właściwego czasu wykonania tych poszczególnych operacji
czyli na początku musimy szpiegować funkcje musimy na początku
określić jakie wartości oczekujemy musimy zasubskrybować się
na nadejście tych wartości i wtedy dopiero mamy wszystko przygotowane dopiero
możemy uruchomić jakieś operacje czy dopiero wtedy możemy zrobić click czyli
faktycznie zapisać i dopiero wtedy możemy sprawdzić czy po pierwsze funkcje była wykonana no
i tu w środku sprawdzić czy faktycznie czy
nasze tutaj wartości invent wyemitował poprawną
wartość taką samą nie tą samą tylko taką samą jak ta której
oczekiwaliśmy jest to prosty i wygodny sposób
testowania inputów outputów aczkolwiek on tutaj jakby
pomija w tym bindowania pomija w tym właśnie podpinanie
tego przez angulara my to troszeczkę symulujemy defacto my to symulujemy robiąc
to własnoręcznie my własnoręcznie podpinamy input tutaj na
przykład w ten sposób wrzucając pod input i własnoręcznie tutaj subskrybujemy
output i to jest w tym momencie ok bo angular robi dokładnie identycznie
to samo jednak i jeśli chciałbyś naprawdę zasymulować to razem
z angularem żeby to angular zrobił to też jest to możliwe ja tutaj
może nie sugerowałbym ale pokażę jak to zrobić zobaczysz wtedy różnicę
i zobaczysz efekt jak będzie identyczny aczkolwiek będzie to dużo więcej pracy żeby
to zrobić trzeba faktycznie mieć komponent symulujący to wiązanie czyli muszę mieć jakiegoś
rodzica żeby jakiś rodzic mógł przekazać nam ten input i output więc ja
tutaj na szybko sobie stworzę komponent komponent
on tu będzie miał szablon na sztywno wpisany
w kodzie i powiedzmy że będzie to class task
list item test host
może tak brzydko go tutaj nazwiemy żeby się wyróżniał task list
item test host okej i tutaj w tym komponencie będziemy
renderowali ten komponent czyli po prostu selector tego komponentu umieszczam
wewnątrz tego drugiego okej i
teraz muszę ten oczywiście dodać do deklaracji i trik polega na tym że nie renderujemy
tego naszego komponentu tylko musimy
stworzyć fixturę rodzica czyli fixturę tego naszego
hosta zróbmy to tutaj create
component i tutaj tworzymy nasz host i instancję
oczywiście gdzie potrzeba naszej instancji więc nie możemy bezpośrednio wyciągnąć
bo nie chcemy tej musimy znaleźć nasz komponent czyli tutaj debug element
query by directive to
już znasz i mogę po prostu poszukać w tym naszym hoście poszukać
naszego komponentu czyli poszukamy nasz
tasklist komponent i to
się prawie zgadza potrzebujemy tu jeszcze component instance
w ten sposób okej i teraz nie będzie
mu przypisywali task tutaj bezpośrednio jak to wyrzuce to nam się powinno popsuć
o właśnie musimy tego taska ustawić w rodzicu
czyli w tym miejscu i rodzic musi to przekazać nam tutaj czyli
tak naprawdę będzie to fixture component
instance task czyli tutaj musi być
zdefiniowany task ewentualnie
możemy też pokusić się o coś takiego jak w fixture
debug element context i po prostu wrzucić tutaj w ten
szablon task okej i teraz
jeśli tu do kontekstu przypiszę task to kontekst tak naprawdę
to jest zmienna która przechowuje wszystkie zmienne tego template'a czyli
ja mogę teraz po prostu zrobić że task czyli nasz tutaj input i
do niego przypisuje task tutaj widzę
nie te cudzysłowia użyłem nie tych co trzeba o
elegancko i teraz ten task tutaj wrzucam luzem
jakby do kontekstu tego template'a teraz nie muszę tu nawet tworzyć pól inputów
po prostu definiuje coś luzem wstrzykuje do szablonu i
do szablonu wstrzykuje task i ten task przypisuje input do tego elementu i
nam wszystko działa i teraz w drugą stronę jeśli chcieli byśmy to obserwować
to teraz tak tutaj
bezpośrednio subskrybowaliśmy się my a
tutaj musielibyśmy się no właśnie i teraz pytanie czy jest sens
bo jeśli zobaczył ten spróbuję zrobić na output
będzie to saved tak
to muszę tutaj jakąś funkcję wykonać tutaj
więc musiałbym tutaj faktycznie zamockować jakąś funkcję
w ten sposób i
wtedy zamiast my ręcznie się subskrybować szpiegować
na save wewnątrz komponentu to musielibyśmy
sobie to saved spy i nie na tym komponencie
tylko na fixture na rodzicu component instance tutaj
szpiegować metodę saved nie przepuścić jej i
po prostu sprawdzić wtedy czy saved czyli tutaj
rodzic ja pokażę może ten komponent jeszcze tutaj z boku żebyśmy go elegancko
widzieli tak
czyli czy ta funkcja output
czy ona wykona funkcje rodzica więc tu musimy tą funkcję szpiegować
czyli saved by kropka
no właśnie kropka to expect to
have been called with with i
nasz task to save czyli jak widzisz jest troszkę mniej kodu
niby nie musimy to jej robić tego done
więc sprawa się teoretycznie uprasza z tej strony ale wymagało to od nas tworzenia
tego całego wielkiego tutaj tego komponentu pomocniczego więc nie wiem
czy jest to wygodniejsze zobaczmy czy to wszystko działa nie zadziała bo kolejność
jest nie taka oczywiście musimy najpierw kliknąć
a później sprawdzić szpiegiem czy wewnętrzna funkcja czyli emiter został
wykonany oraz funkcja rodzica czyli czy faktycznie ta wartość tutaj
nasza została przekazana poziom wyżej do rodzica i 14
razy sukces czyli jak widzisz możemy zrobić też w ten sposób tym razem nie my się subskrybujemy
angular się subskrybuj a my obserwujemy czyta wartość przekazana jest do góry no
i też nie przekazują bezpośrednio do elementu wstrzykujemy to do rodzica
i sprawdzamy czy rodzic jeśli ma takie bindowanie czy nam prawidłowo wejdzie
do elementu to jedną rzecz która nam tu daje to że faktycznie sprawdzamy czy my
input outputy mają właściwe tutaj nazwy w szablonie nie
wiem czy jest to coś co warto sprawdzać szczególnie że chcemy
mieć testy jednostkowe nie integracyjne czyli testujemy bardziej jak komponent reaguje
na dane które dostał i czy emituje odpowiednie iventy a nie
o to jak on się integruje z rodzicem więc nie chcemy na pewno używać
prawdziwego rodzica możemy tu jak widzisz zmockować rodzica nie jest to
zawsze zawsze konieczne szczególnie dlatego właśnie że no
właśnie możemy to samo co angular robić możemy zrobić to ręcznie takie mockowanie przydaje się w jednej
konkretnej sytuacji jeśli tutaj chcemy postawić jakiś content
powiedzmy tak content tutaj
używamy w szablonie naszego teraz komponentu na przykład gdzieś
ng content i chcemy sprawdzić czy to zadziała więc jeśli nie
testujesz właśnie treść nie testujesz zawartości testujesz tylko i wyłącznie bindowania
no to ten właśnie host którego stworzyliśmy czyli
test host wtedy nie jest tutaj specjalnie konieczny okej
to tyle jeśli chodzi o testowanie inputów outputów w kolejnych lekcjach zajmiemy
się testowaniem interakcji między rodzicem a dzieckiem a
także między komponentem usługą i także przetestujemy
sobie observable ale to tylko już w kolejnych lekcjach tak więc do zobaczenia