{"id":18853,"date":"2023-01-30T05:00:00","date_gmt":"2023-01-30T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=18853"},"modified":"2024-12-05T11:17:19","modified_gmt":"2024-12-05T10:17:19","slug":"testy-automatyczne-cypress-czeka-az-wprowadzenie-do-waitow","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/testy-automatyczne-cypress-czeka-az-wprowadzenie-do-waitow\/","title":{"rendered":"Testy automatyczne: Cypress czeka a\u017c&#8230; \u2013 wprowadzenie do wait\u00f3w"},"content":{"rendered":"\n<p>W pracy testera automatyzuj\u0105cego jednym z kluczowych zada\u0144 jest poprawna obs\u0142uga oczekiwa\u0144 na zdarzenie, kt\u00f3ra umo\u017cliwia nam wykonie asercji na przygotowanym ju\u017c elemencie. W \u017cargonie tester\u00f3w spotykamy si\u0119 z okre\u015bleniem \u201ewaity\u201d od metody wait() i ta nomenklatura zosta\u0142a u\u017cyta w tym artykule.<\/p>\n\n\n\n<p>We wpisie om\u00f3wi\u0119 do czego potrzebne s\u0105 waity w testach automatycznych, przedstawi\u0119 por\u00f3wnanie wait\u00f3w dost\u0119pnych w Selenium oraz w Cypressie wraz z przyk\u0142adow\u0105 ich implementacj\u0105 w Cypressie.<\/p>\n\n\n\n<p>Cypress w znacz\u0105cy spos\u00f3b wyr\u00f3\u017cnia si\u0119 na tle innych dost\u0119pnych aplikacji do testowania automatycznego dzi\u0119ki jednemu specyficznemu waitowi, kt\u00f3ry r\u00f3wnie\u017c zostanie om\u00f3wiony wraz z metodami cy.wait() oraz cy.intercept().<\/p>\n\n\n\n<p>Ostatnim aspektem poruszonym w tym artykule b\u0119dzie rekurencja, kt\u00f3ra te\u017c mo\u017ce by\u0107 wykorzystana w Cypressie do waitu na element, jako w\u0142asne niestandardowe podej\u015bcie.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n\n\n\n<p>Na naszym blogu pojawi\u0142 si\u0119 wcze\u015bniej <a aria-label=\" (opens in a new tab)\" href=\"https:\/\/sii.pl\/blog\/cypress-dlaczego-warto-zainteresowac-sie-tym-frameworkiem\/?category=testowanie&amp;tag=cypress,poradnik,zalety-i-wady\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">artyku\u0142 wprowadzaj\u0105cy do Cypressa<\/a>. Zach\u0119cam do przeczytania go w celu zapoznania si\u0119 z pozosta\u0142ymi funkcjonalno\u015bciami narz\u0119dzia. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wait w testach automatycznych<\/strong><\/h2>\n\n\n\n<p>Wait jest jedn\u0105 z podstawowych i kluczowych cz\u0119\u015bci testu automatycznego. Dzi\u0119ki niemu mo\u017cemy wykona\u0107 op\u00f3\u017anienie w te\u015bcie po to, aby strona internetowa b\u0105d\u017a dowolny element na tej stronie poprawnie si\u0119 za\u0142adowa\u0142. Umo\u017cliwi nam to dokonanie sprawdzenia, kt\u00f3re skutkuje pozytywnym b\u0105d\u017a negatywnym zako\u0144czeniem naszego testu.<\/p>\n\n\n\n<p>Z\u0142a implementacja waita mo\u017ce skutkowa\u0107 b\u0142\u0119dnym wynikiem testu np. poprzez pr\u00f3b\u0119 interakcji ze stron\u0105, kt\u00f3ra nie zosta\u0142a do ko\u0144ca za\u0142adowana. Innym popularnym problemem jest niewy\u015bwietlanie elementu, gdy\u017c czeka\u0142 on na przyk\u0142ad na odpowied\u017a serwera. Jednak jedn\u0105 z wi\u0119kszych trudno\u015bci zwi\u0105zan\u0105 ze z\u0142\u0105 implementacj\u0105 waita jest w\u0142a\u015bnie niepotrzebne czekanie, kt\u00f3re wyd\u0142u\u017ca nam czas trwania testu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wait w Selenium<\/strong><\/h2>\n\n\n\n<p>W jednym z najbardziej popularnych narz\u0119dzi do test\u00f3w automatycznych, jakim jest Selenium, mamy do czynienia z trzema rodzajami wait\u00f3w, kt\u00f3re om\u00f3wi\u0119 poni\u017cej.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implicit wait \u2013 oczekiwane niejawne<\/strong><\/h3>\n\n\n\n<p>Polega ono na pr\u00f3bie znalezienia elementu w DOM-ie przez okre\u015blony czas, je\u017celi nie jest on natychmiastowo dost\u0119pny. Domy\u015blna warto\u015b\u0107 tego waita to 0 i kiedy zmienimy t\u0105 warto\u015b\u0107, niejawne oczekiwanie trwa do ko\u0144ca sesji.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/1-1.png\"><img decoding=\"async\" width=\"769\" height=\"140\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/1-1.png\" alt=\"Przyk\u0142ad Selenium \u2013 Implicit wait\" class=\"wp-image-18854\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/1-1.png 769w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/1-1-300x55.png 300w\" sizes=\"(max-width: 769px) 100vw, 769px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 1 Przyk\u0142ad Selenium \u2013 Implicit wait<\/figcaption><\/figure>\n\n\n\n<p>Jak przedstawiono w powy\u017cszym kodzie, implementacja tego rozwi\u0105zania jest bardzo szybka, jednak ma ona pewne ograniczenia. Ten wait <strong>dzia\u0142a tylko z metoda findElement(),<\/strong> co uniemo\u017cliwia nam oczekiwanie na za\u0142adowanie si\u0119 przyk\u0142adowo tekstu w elemencie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Explicit wait \u2013 oczekiwanie jawne<\/strong><\/h3>\n\n\n\n<p>Dzi\u0119ki niemu, mamy mo\u017cliwo\u015b\u0107 zatrzymania testu do momentu, a\u017c oczekiwany przez nas warunek zostanie spe\u0142niony. Sprawdzenie warunku jest wywo\u0142ywane z okre\u015blon\u0105 cz\u0119stotliwo\u015bci\u0105, a\u017c up\u0142ynie limit czasu oczekiwania. Oznacza to, \u017ce gdy warunek zwraca warto\u015b\u0107 fa\u0142szyw\u0105, Selenium b\u0119dzie czeka\u0107 i pr\u00f3bowa\u0107 ponownie.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/2-1.png\"><img decoding=\"async\" width=\"908\" height=\"52\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/2-1.png\" alt=\"Przyk\u0142ad Selenium \u2013 Explicit wait\" class=\"wp-image-18857\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/2-1.png 908w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/2-1-300x17.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/2-1-768x44.png 768w\" sizes=\"(max-width: 908px) 100vw, 908px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 2 Przyk\u0142ad Selenium \u2013 Explicit wait<\/figcaption><\/figure>\n\n\n\n<p>W przedstawionym wy\u017cej kodzie oczekujemy, a\u017c tytu\u0142 naszej strony uzyska spodziewan\u0105 warto\u015b\u0107. Miejmy na uwadze, \u017ce <strong>wait jest teraz u\u017cywany tylko w momencie wywo\u0142ania<\/strong>, a nie jak poprzednio \u2013 globalnie. Tutaj znajdziecie <a href=\"https:\/\/www.selenium.dev\/selenium\/docs\/api\/javascript\/module\/selenium-webdriver\/lib\/until.html\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >list\u0119 dost\u0119pnych oczekiwanych warunk\u00f3w expicit wait dla Selenium<\/a>. &nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>FluentWait<\/strong><\/h3>\n\n\n\n<p>Oczekujemy <strong>w spos\u00f3b jawny<\/strong> na okre\u015blon\u0105 sytuacje przez podan\u0105 liczb\u0119 sekund \u2013 przyk\u0142adowo: poni\u017cszy kod przez 10 sekund b\u0119dzie sprawdza\u0142, czy nasza strona ma oczekiwany tytu\u0142 z cz\u0119stotliwo\u015bci\u0105 jednej sekundy.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"42\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/3-1024x42.png\" alt=\"Przyk\u0142ad Selenium \u2013 FluentWait\" class=\"wp-image-18859\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/3-1024x42.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/3-300x12.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/3-768x32.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/3.png 1159w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Ryc. 3 Przyk\u0142ad Selenium \u2013 FluentWait<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wait w Cypressie<\/strong><\/h2>\n\n\n\n<p>Cypress domy\u015blnie wykorzystuje dynamiczne czekanie na elementy b\u0105d\u017a akcje dost\u0119pne na stronie internetowej u\u017cytej w naszym te\u015bcie automatycznym. Mo\u017cemy wyr\u00f3\u017cni\u0107 przedstawione ni\u017cej sposoby do obs\u0142ugi wait\u00f3w.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Domy\u015blne timeouty<\/strong><\/h3>\n\n\n\n<p>W Cypressie dost\u0119pnych jest 6 domy\u015blnych timeout\u00f3w. Dzi\u0119ki wbudowanemu mechanizmowi re-try, wykonuj\u0105 sprawdzenia w zadanym przez nas lub w za\u0142o\u017conym czasie, podobnie do poprzednio om\u00f3wionego explicit waita:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>defaultCommandTimeout \u2013 jest to czas, w kt\u00f3rym Cypress stara si\u0119 dosta\u0107 do elementu lub akcji podczas wykonywania wi\u0119kszo\u015bci komend na DOM-ie.<\/li>\n\n\n\n<li>execTimeout \u2013 timeout definiuj\u0105cy czas czekania na system, aby zako\u0144czy\u0142 operacje podczas komendy cy.exec().<\/li>\n\n\n\n<li>taskTimeout \u2013 maksymalny czas, w kt\u00f3rym czekamy na wykonanie zadania poprzez komend\u0119 cy.task().<\/li>\n\n\n\n<li>pageLoadTimeout \u2013 oczekuje na tzw. \u201cpage transition event\u201d. Zdarzenie to wyst\u0119puje, gdy u\u017cytkownik odwiedza b\u0105d\u017a opuszcza dan\u0105 stron\u0119 internetow\u0105. Ten domy\u015blny timeout oczekuje r\u00f3wnie\u017c, a\u017c komendy cy.visit(), cy.go(), cy.reload() wykonaj\u0105 load events. S\u0105 one wywo\u0142ywane, gdy ca\u0142a strona oraz wszystkie jej zasoby tj. arkusz styl\u00f3w, skrypty, iframe\u2019y i obrazy, b\u0119d\u0105 za\u0142adowane.<\/li>\n\n\n\n<li>requestTimeout \u2013 maksymalny czas, w kt\u00f3rym czekamy na wykonanie cy.wait().<\/li>\n\n\n\n<li>responseTimeout \u2013 czeka na wykonanie metod cy.request(), cy.wait(), cy.fixture(), cy.getCookie(), cy.getCookies(), cy.setCookie(), cy.clearCookie(), cy.clearCookies() i cy.screenshot().<\/li>\n<\/ul>\n\n\n\n<p>Je\u017celi chcemy nadpisa\u0107 warto\u015bci dla timeout\u00f3w, dokonujemy tego w pliku cypress.json:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/4.png\"><img decoding=\"async\" width=\"407\" height=\"145\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/4.png\" alt=\"Cypress \u2013 cypress.json ustawienie warto\u015bci defaultCommandTimeout\" class=\"wp-image-18862\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/4.png 407w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/4-300x107.png 300w\" sizes=\"(max-width: 407px) 100vw, 407px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 4 Cypress \u2013 cypress.json ustawienie warto\u015bci defaultCommandTimeout<\/figcaption><\/figure>\n\n\n\n<p>Mo\u017cemy r\u00f3wnie\u017c zmieni\u0107 te czasy dla konkretnego \u0142a\u0144cucha akcji b\u0105d\u017a samej metody poprzez przes\u0142anie obiektu z oczekiwanym czasem:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/5.png\"><img decoding=\"async\" width=\"683\" height=\"36\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/5.png\" alt=\"Cypress \u2013 u\u017cyty implicit subject oraz nadpisanie defaultCommandTimeout porzez przes\u0142anie obiektu do metody get\" class=\"wp-image-18864\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/5.png 683w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/5-300x16.png 300w\" sizes=\"(max-width: 683px) 100vw, 683px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 5 Cypress \u2013 u\u017cyty implicit subject oraz nadpisanie defaultCommandTimeout porzez przes\u0142anie obiektu do metody get<\/figcaption><\/figure>\n\n\n\n<p>W powy\u017cszym kodzie u\u017cyli\u015bmy implicit subject do stworzenia asercji dzi\u0119ki metodzie .should(). Najpierw Cypress stara si\u0119 odnale\u017a\u0107 element przycisku w czasie 20 sekund zdefiniowanych w przes\u0142anym obiekcie {timeout: 20000}, a nast\u0119pnie dokonuje asercji na tym przycisku, by sprawdzi\u0107, czy zawiera tekst \u201eSzukaj w Google\u201d. Tutaj ponownie oczekuje do 20 sekund na pojawienie si\u0119 tego tekstu. Timeout mo\u017cemy uzyska\u0107 podczas wykonywania metody cy.get() oraz should(), kt\u00f3ry zaneguje nam ca\u0142y test.<\/p>\n\n\n\n<p>Dla metod get(), find(), cointains() z do\u015bwiadczenia polecam u\u017cywanie timeoutu na \u0142a\u0144cuchu akcji w przypadku, gdy oczekiwanie na element b\u0105d\u017a jego w\u0142a\u015bciwo\u015bci jest wyd\u0142u\u017cone. Natomiast czas ustawiony w cypress.json nale\u017cy ograniczy\u0107 do rozs\u0105dnego minimum, aby unikn\u0105\u0107 niepotrzebnego wyd\u0142u\u017cenia test\u00f3w w przypadku, gdy dostajemy fail.<\/p>\n\n\n\n<p>W Cypress mamy mo\u017cliwo\u015b\u0107 dokonana podobnej asercji z explicit subject poprzez u\u017cycie metody .then() i dokonania asercji na elemencie JQuery:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/6.png\"><img decoding=\"async\" width=\"564\" height=\"72\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/6.png\" alt=\"Przyk\u0142ad Cypress \u2013 asercja z explicit subject\" class=\"wp-image-18866\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/6.png 564w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/6-300x38.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/6-555x72.png 555w\" sizes=\"(max-width: 564px) 100vw, 564px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 6 Przyk\u0142ad Cypress \u2013 asercja z explicit subject<\/figcaption><\/figure>\n\n\n\n<p>W tym przypadku Cypress najpierw oczekuje do 20 sekund na metod\u0119 .get(), a nast\u0119pnie natychmiast wykonuje asercj\u0119 na elemencie, pomijaj\u0105c zdefiniowany defaultCommandTimeout.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Wbudowany Wait<\/strong><\/h3>\n\n\n\n<p>Cypress posiada w\u0142asn\u0105 implementacj\u0119 metody wait, kt\u00f3ra przyjmuje do dw\u00f3ch argument\u00f3w:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Jedn\u0105 z pierwszych warto\u015bci jest warto\u015b\u0107 numeryczna podana w milisekundach. Jest to warto\u015b\u0107 czasu, kt\u00f3ra up\u0142ywa mi\u0119dzy poprzedni\u0105 a nast\u0119pna komend\u0105 w Cypressowym \u0142a\u0144cuchu akcji.<\/li>\n\n\n\n<li>Kolejn\u0105 warto\u015bci\u0105, jak\u0105 mo\u017cemy przes\u0142a\u0107 w miejsce czasu, jest alias b\u0105d\u017a tablica alias\u00f3w. Aliasy to pot\u0119\u017cna konstrukcja w Cypressie, kt\u00f3ra ma wiele zastosowa\u0144 i mo\u017cna o niej napisa\u0107 osobny artyku\u0142. Jednak dla nas, w koncepcji wait\u00f3w, najwa\u017cniejsze jest skupienie si\u0119 na mo\u017cliwo\u015bci przypisania aliasu do API calla. Wykonujemy to poprzez metod\u0119 cy.intercept() oraz metod\u0119 .as(), gdzie metoda as zapisuje nam alias, do kt\u00f3rego mamy dost\u0119p z u\u017cyciem prefixu @.<\/li>\n\n\n\n<li>Ostatni\u0105, opcjonaln\u0105 warto\u015bci\u0105 jest obiekt opcji, kt\u00f3ry pozwala nam nadpisa\u0107 zdefiniowane poprzednio, domy\u015blne czasy dla requestTimeout oraz responseTimeout. Dodatkowo, udost\u0119pnia nam mo\u017cliwo\u015b\u0107 manipulacji widoczno\u015bci\u0105 logowania waita dzi\u0119ki przes\u0142aniu obiektu {log: true\/false}.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/7.png\"><img decoding=\"async\" width=\"451\" height=\"178\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/7.png\" alt=\"Cypress \u2013 sposoby implementacji cy.wait()\" class=\"wp-image-18868\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/7.png 451w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/7-300x118.png 300w\" sizes=\"(max-width: 451px) 100vw, 451px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 7 Cypress \u2013 sposoby implementacji cy.wait()<\/figcaption><\/figure>\n\n\n\n<p>Kod ten przedstawia implementacj\u0119 Cypressowego waita. Ta metoda umo\u017cliwia nam czekanie w konkretnym miejscu w kodzie przez dany czas b\u0105d\u017a do czasu pojawienia si\u0119 odpowiedniego aliasu.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Tworzenie aliasu<\/strong><\/h3>\n\n\n\n<p>Aby odpowiednio stworzy\u0107 wait na alias, potrzebujemy w\u0142a\u015bnie tego aliasu. Jedn\u0105 z metod do jego stworzenia jest podejrzenie zapyta\u0144 wykonywanych przez przegl\u0105dark\u0119 na naszej stronie testowej. Nast\u0119pnie, wybieramy ostatnie zapytanie b\u0105d\u017a kilka ostatnich wykonanych zapyta\u0144, kt\u00f3re z du\u017c\u0105 doz\u0105 prawdopodobie\u0144stwa wska\u017c\u0105 nam, \u017ce strona jest za\u0142adowana.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/8.png\"><img decoding=\"async\" width=\"856\" height=\"186\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/8.png\" alt=\"Lista zapyta\u0144 API na stronie www.google.pl\" class=\"wp-image-18870\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/8.png 856w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/8-300x65.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/8-768x167.png 768w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 8 Lista zapyta\u0144 API na stronie www.google.pl<\/figcaption><\/figure>\n\n\n\n<p>Gdy znajdziemy ju\u017c zapytanie, kt\u00f3re nas interesuje, pozostaje nam wykorzysta\u0107 metod\u0119 cy.intercept(). Pozwala nam ona \u015bledzi\u0107 i zarz\u0105dza\u0107 \u017c\u0105daniami oraz odpowiedziami po sieci. Dzi\u0119ki niej mo\u017cemy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mockowa\u0107 dane,<\/li>\n\n\n\n<li>walidowa\u0107 zapytania API,<\/li>\n\n\n\n<li>a dzi\u0119ki kombinacji z cy.wait(), czeka\u0107 na zako\u0144czenie danego zapytania API.<\/li>\n<\/ul>\n\n\n\n<p>Nast\u0119pnie, korzystaj\u0105c z metody .as(), mo\u017cemy zapisa\u0107 \u015bledzone \u017c\u0105danie jako alias.<\/p>\n\n\n\n<p><strong>Implementacja intercepta<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/9.png\"><img decoding=\"async\" width=\"542\" height=\"94\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/9.png\" alt=\"Przyk\u0142ad Cypress \u2013 implementacja metody cy.intercept()\" class=\"wp-image-18872\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/9.png 542w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/9-300x52.png 300w\" sizes=\"(max-width: 542px) 100vw, 542px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 9 Przyk\u0142ad Cypress \u2013 implementacja metody cy.intercept()<\/figcaption><\/figure>\n\n\n\n<p>Powy\u017cej przedstawiona zosta\u0142a implementacja intercepta, kt\u00f3ry nast\u0119pnie wykorzystujemy w te\u015bcie. Ma on za zadanie:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Odwiedzi\u0107 stron\u0119 Google.pl.<\/li>\n\n\n\n<li>Zaakceptowa\u0107 ciasteczka.<\/li>\n\n\n\n<li>Wpisa\u0107 Sii w pole wyszukiwarki oraz nacisn\u0105\u0107 przycisk Enter.<\/li>\n\n\n\n<li>Czeka\u0107 na alias @finishedGoogleSearch.<\/li>\n\n\n\n<li>Dokona\u0107 sprawdzenia, czy na za\u0142adowanej stronie jest widoczny tekst \u201eOko\u0142o\u201d.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/10.png\"><img decoding=\"async\" width=\"564\" height=\"195\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/10.png\" alt=\"Przyk\u0142ad Cypress \u2013 kod testu wykorzystuj\u0105cy czekanie na alias\" class=\"wp-image-18874\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/10.png 564w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/10-300x104.png 300w\" sizes=\"(max-width: 564px) 100vw, 564px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 10 Przyk\u0142ad Cypress \u2013 kod testu wykorzystuj\u0105cy czekanie na alias<\/figcaption><\/figure>\n\n\n\n<p><strong>Doradzam unika\u0107 wait\u00f3w<\/strong> <strong>na zadany czas<\/strong> <strong>i skupi\u0107 si\u0119 na czekaniu na aliasy<\/strong>. Dzi\u0119ki temu nasze testy b\u0119d\u0105 kr\u00f3tsze, a kod bardziej zoptymalizowany i w znacznym stopniu wolny od nieoczekiwanych wyj\u0105tk\u00f3w.<\/p>\n\n\n\n<p>Jedn\u0105 z dodatkowych paczek do ESLinta jest Cypress ESLint Plugin, kt\u00f3ry pozwala nam zdefiniowa\u0107 regu\u0142\u0119 &#8222;cypress\/no-unnecessary-waiting&#8221;: &#8222;error&#8221; i wykrywa\u0107 te waity podczas tworzenia test\u00f3w automatycznych.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>W\u0142asna implementacja wait\u00f3w<\/strong><\/h3>\n\n\n\n<p>W przypadku, gdy potrzebujemy w\u0142asnego waita, kt\u00f3ry nie kwalifikuje si\u0119 do wcze\u015bniej om\u00f3wionego cy.wait(), mo\u017cemy u\u017cy\u0107 rekurencyjnego czekania ze sprawdzeniem warunku co odwo\u0142anie.<\/p>\n\n\n\n<p><strong>Rekurencja<\/strong>, nazywana r\u00f3wnie\u017c rekursj\u0105, <strong>jest odwo\u0142aniem funkcji lub definicji do samej siebie<\/strong>. Wyst\u0119puje ona w matematyce (algorytm Euklidesa, ci\u0105g Fibonacciego), programowaniu, a nawet sztuce (obraz w obrazie b\u0105d\u017a umieszczenie naprzeciw siebie dw\u00f3ch luster \u2013 dok\u0142adnie wtedy powstaje nam odbicie w odbiciu).<\/p>\n\n\n\n<p>Wr\u00f3\u0107my jednak do programowania oraz naszego przyk\u0142adu. Chcemy napisa\u0107 waita, kt\u00f3ry b\u0119dzie czeka\u0142, a\u017c oczekiwany element pojawi si\u0119 na stronie.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/11.png\"><img decoding=\"async\" width=\"846\" height=\"643\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/11.png\" alt=\"Przyk\u0142ad Cypress \u2013 implementacja rekurencyjnego waita na pojawienie si\u0119 elementu\" class=\"wp-image-18877\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/11.png 846w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/11-300x228.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/11-768x584.png 768w\" sizes=\"(max-width: 846px) 100vw, 846px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 11 Przyk\u0142ad Cypress \u2013 implementacja rekurencyjnego waita na pojawienie si\u0119 elementu<\/figcaption><\/figure>\n\n\n\n<p>Wait realizuje to zadanie w nast\u0119puj\u0105cej kolejno\u015bci:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Pobranie zawarto\u015bci body dzi\u0119ki metodzie .get().<\/li>\n\n\n\n<li>Nast\u0119pnie, zamienienie tego obiektu na obiekt JQuery, wywo\u0142anie na nim metody .find(locator) i finalnie .length, kt\u00f3ra zwraca 0, gdy element nie znajduje si\u0119 w body.<\/li>\n\n\n\n<li>Oczekiwanie w czasie splitu \u2013 czyli czas, po up\u0142ywie kt\u00f3rego chcemy dokona\u0107 kolejnego sprawdzenia, czy element spe\u0142nia zadany warunek.<\/li>\n\n\n\n<li>Zdefiniowanie totalTime i rozpocz\u0119cie zwi\u0119kszania go o zadany czas przerwy (splitu) przy ka\u017cdym nast\u0119pnym rekurencyjnym wywo\u0142aniu.<\/li>\n\n\n\n<li>Sprawdzenie, czy totalTime jest mniejszy b\u0105d\u017a r\u00f3wny od timeoutu. Zale\u017cnie od wyniku warunku rekurencyjnie wywo\u0142uje funkcje checkForElement(), b\u0105d\u017a wywo\u0142uje cy.get(resultText) w celu negacji testu.<\/li>\n\n\n\n<li>Na koniec, wywo\u0142anie cy.get(resultsText), gdy warunek body.find(elementID).length === 0 nie jest spe\u0142niony, co zamyka rekurencj\u0119.<\/li>\n<\/ol>\n\n\n\n<p>Nie jest to idealne rozwi\u0105zanie tego problemu i <strong>powinno by\u0107 u\u017cywane w ostateczno\u015bci<\/strong>, poniewa\u017c mamy tutaj do czynienia z utrudnion\u0105 czytelno\u015bci\u0105 kodu oraz trudno\u015bci\u0105 w utrzymaniu kodu.<\/p>\n\n\n\n<p>Powy\u017cszy kod bardzo ci\u0119\u017cko debuguje si\u0119 w Cypressie i nieumiej\u0119tne u\u017cywanie rekurencji b\u0105d\u017a p\u0119tli mo\u017ce skutkowa\u0107 wpadni\u0119ciem w niesko\u0144czon\u0105 p\u0119tl\u0119 tzw. infinity loop. Istnieje mo\u017cliwo\u015b\u0107 jej powstania podczas mieszania kodu synchronicznego i asynchronicznego b\u0105d\u017a podczas b\u0142\u0119dnego sterowanie warunkami inkrementacji. Ostatecznie, niesko\u0144czona p\u0119tla spowoduj\u0119 b\u0142\u0105d testu i przegl\u0105darka przestanie odpowiada\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Dost\u0119pne zewn\u0119trzne paczki wait\u00f3w<\/strong><\/h2>\n\n\n\n<p>W tym rozdziale om\u00f3wi\u0119 dwie znane mi paczki, kt\u00f3re mo\u017cemy u\u017cy\u0107 w naszych testach.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cypress-wait-until \u2013 pozwala ona na oczekiwanie na wszystko, na co nie oczekuje cy.wait(). Metoda cy.waitUntil() przyjmuje dwa argumenty. Pierwszym jest funkcja, kt\u00f3ra wykonuje Cypressow\u0105 metod\u0119, metody b\u0105d\u017a ca\u0142y \u0142a\u0144cuch akcji. Nast\u0119pnym argumentem jest obiekt opcji, kt\u00f3ry umo\u017cliwia sterowanie timeoutem oraz interwa\u0142em. Kod stara si\u0119 dosta\u0107 do pola przegl\u0105darki przez trzy sekundy z interwa\u0142em&nbsp;jednosekundowym. Dzi\u0119ki edycji warto\u015bci domy\u015blnych, mo\u017cemy dowolnie sterowa\u0107 warto\u015bciami timeout oraz interval. Domy\u015blnymi warto\u015bciami dla tego waita jest timeout=5000, interval=200.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/12.png\"><img decoding=\"async\" width=\"660\" height=\"159\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/12.png\" alt=\"\" class=\"wp-image-18880\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/12.png 660w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/12-300x72.png 300w\" sizes=\"(max-width: 660px) 100vw, 660px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 12 Cypress \u2013 przyk\u0142adowa implementacja cypress-wait-until<\/figcaption><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cypress-recurse \u2013 paczka udost\u0119pnia rekurencyjne czekanie, a\u017c oczekiwany warunek zwr\u00f3ci warto\u015b\u0107 True. Naszym spodziewanym warunkiem w tym przypadku jest expect(button).to.have.value(\u2018Szukaj w Google\u2019)}. Metoda zaneguje test, je\u017celi w ci\u0105gu 30 sekund ten warunek nie zwr\u00f3ci warto\u015bci True. Sam warunek b\u0119dzie sprawdzany z cz\u0119stotliwo\u015bci\u0105 0,5 sekundy. Domy\u015blne warto\u015bci dla metody to: timeout=4000, limit=15, delay=800.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/13.png\"><img decoding=\"async\" width=\"455\" height=\"313\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/13.png\" alt=\"Cypress \u2013 przyk\u0142adowa implementacja cypress-recurse\" class=\"wp-image-18885\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/13.png 455w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/13-300x206.png 300w\" sizes=\"(max-width: 455px) 100vw, 455px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 13 Cypress \u2013 przyk\u0142adowa implementacja cypress-recurse<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/oferty-pracy\/all\/it-testing-qa\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"737\" height=\"170\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/12\/praca-m-20.jpg\" alt=\"oferty pracy\" class=\"wp-image-29820\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/12\/praca-m-20.jpg 737w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/12\/praca-m-20-300x69.jpg 300w\" sizes=\"(max-width: 737px) 100vw, 737px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Selenium a Cypress waits<\/strong><\/h2>\n\n\n\n<p>Poszukajmy zatem <strong>podobie\u0144stw<\/strong> mi\u0119dzy waitami z Selenium a waitami z Cypressa.<\/p>\n\n\n\n<p>Zacznijmy od impicit wait. Podobne zachowanie obserwujemy w Cypressie \u2013 poprzez sterowanie \u201edefaultCommandTimeout\u201d b\u0105d\u017a samym timeoutem mo\u017cemy czeka\u0107 na pojawienie si\u0119 elementu na stronie dzi\u0119ki metodzie cy.get() w zadanym przez nas czasie.<\/p>\n\n\n\n<p>Explicit wait w Cypressie jest do\u015b\u0107 kontrowersyjnym tematem, poniewa\u017c ma on sprawdza\u0107 warunek. Cypressowa metoda .should(\u2018be.visible\u2019) mo\u017ce by\u0107 traktowana jako odpowiednik expected condition w Selenium elementIsVisible(element).<\/p>\n\n\n\n<p>Jednak: <strong>czy asercja to wait?<\/strong> Je\u017celi przyjmiemy, \u017ce tak, to wszystkie asercje .should() mo\u017cemy potraktowa\u0107 jako explicit wait. Jestem pewien, \u017ce zdania, co do tej teorii, s\u0105 podzielone, dlatego pozostawiam odpowied\u017a na to pytanie do w\u0142asnej, czytelniczej interpretacji \ud83d\ude0a<\/p>\n\n\n\n<p>Nie zapominajmy o cy.wait(@alias). To w\u0142a\u015bnie ten wait mo\u017ce zosta\u0107 <strong>rozwa\u017cony jako pe\u0142noprawny explicit.<\/strong> Przedstawionym zewn\u0119trznym paczkom cypress-wait-until oraz cypress-recurse jest bli\u017cej do explicit, a nawet fluent waita, ze wzgl\u0119du na mo\u017cliwo\u015b\u0107 sterowania interwa\u0142em, zgodnie z kt\u00f3rym sprawdzony jest warunek.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>W artykule przedstawi\u0142em dost\u0119pne sposoby czekania na elementy w Selenium oraz Cypressie tzw. waity, kt\u00f3re umo\u017cliwiaj\u0105 swobodn\u0105 prac\u0119 na wi\u0119kszo\u015bci element\u00f3w. Zaprezentowa\u0142em r\u00f3\u017cnic\u0119 w czasie z Cypressowymi asercjami. Przygotowa\u0142em przyk\u0142adowy kod z w\u0142asnym waitem oraz om\u00f3wi\u0142em dwie zewn\u0119trzne paczki, z kt\u00f3rymi mo\u017cemy pracowa\u0107 w Cypressie w zale\u017cno\u015bci od naszych potrzeb.<\/p>\n\n\n\n<p>Je\u017celi zaczynacie przygod\u0119 z Cypressem, warto, aby\u015bcie ju\u017c na pocz\u0105tku przyswoili wiedz\u0119 z obszaru cy.wait(\u2018@Alias\u2019). Jest to podstawowa funkcjonalno\u015b\u0107 narz\u0119dzia, kt\u00f3ra podnosi jako\u015b\u0107 kodu w naszych testach automatycznych oraz wyklucza konieczno\u015b\u0107 oczekiwania na \u0142adowanie si\u0119 elementu. Powodzenia!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u0179r\u00f3d\u0142a<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.selenium.dev\/documentation\/webdriver\/waits\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Selenium \u2013 Documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.cypress.io\/guides\/overview\/why-cypress\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Why Cypress?<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/cypress-io\/eslint-plugin-cypress\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >GitHub \u2013 Cypress ESLint Plugin<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/NoriSte\/cypress-wait-until\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >GitHub \u2013 Cypress wait until<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/bahmutov\/cypress-recurse\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >GitHub \u2013 Cypress recurse<\/a><\/li>\n<\/ul>\n\n\n\n<p>***<\/p>\n\n\n\n<p>Je\u017celi interesuje Ci\u0119 tematyka Cypressa, Selenium lub automatyzacji test\u00f3w, zach\u0119camy do zapoznania <a href=\"https:\/\/sii.pl\/blog\/testowanie\/\" target=\"_blank\" aria-label=\"z innymi artyku\u0142ami naszych ekspert\u00f3w.  (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">z innymi artyku\u0142ami naszych ekspert\u00f3w. <\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;18853&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;43&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;4.8&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;4.8\\\/5 ( votes: 43)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Testy automatyczne: Cypress czeka a\u017c... \u2013 wprowadzenie do wait\u00f3w&quot;,&quot;width&quot;:&quot;133.7&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 133.7px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            4.8\/5 ( votes: 43)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>W pracy testera automatyzuj\u0105cego jednym z kluczowych zada\u0144 jest poprawna obs\u0142uga oczekiwa\u0144 na zdarzenie, kt\u00f3ra umo\u017cliwia nam wykonie asercji na &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/testy-automatyczne-cypress-czeka-az-wprowadzenie-do-waitow\/\">Continued<\/a><\/p>\n","protected":false},"author":460,"featured_media":19760,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":9,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1317],"tags":[1605,354,1051,230,932],"class_list":["post-18853","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-testowanie","tag-wait","tag-automatyzacja","tag-cypress","tag-selenium","tag-testy-automatyczne"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2022\/08\/Testy-automatyczne-Cypress-czeka-az\u2026-\u2013-wprowadzenie-do-waitow.jpg","category_names":["Testowanie"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/18853"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/460"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=18853"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/18853\/revisions"}],"predecessor-version":[{"id":29822,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/18853\/revisions\/29822"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/19760"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=18853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=18853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=18853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}