{"id":475024,"date":"2025-09-15T03:18:36","date_gmt":"2025-09-15T03:18:36","guid":{"rendered":""},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"zapiski-odnogo-qa-chast-2-sovety-i-priyomy-v-avtotestah-na-playwright","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=475024","title":{"rendered":"\u0417\u0430\u043f\u0438\u0441\u043a\u0438 \u043e\u0434\u043d\u043e\u0433\u043e QA. \u0427\u0430\u0441\u0442\u044c 2: \u0421\u043e\u0432\u0435\u0442\u044b \u0438 \u043f\u0440\u0438\u0451\u043c\u044b \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0430 Playwright"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u0439\u043d\u0443\u0440\u0430.<\/p>\n<p>\u0418 \u0442\u0430\u043a\u0441, \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u044f \u0434\u043e\u0431\u0440\u0430\u043b\u0430\u0441\u044c \u0434\u043e \u0447\u0430\u0441\u0442\u0438, \u0433\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \ud83d\ude05.<\/p>\n<div class=\"floating-image\">\n<figure class=\"float full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85d\/7ff\/f85\/85d7fff85a0775ec80407eca8830ba12.png\" alt=\"\u041d\u0435 \u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0447\u0442\u043e \u0445\u0430\u043e\u0441 \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u0435\u043d, \u043e\u043d \u043e\u043f\u0430\u0441\u0435\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445\" title=\"\u041d\u0435 \u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0447\u0442\u043e \u0445\u0430\u043e\u0441 \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u0435\u043d, \u043e\u043d \u043e\u043f\u0430\u0441\u0435\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445\" width=\"1024\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/85d\/7ff\/f85\/85d7fff85a0775ec80407eca8830ba12.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/85d\/7ff\/f85\/85d7fff85a0775ec80407eca8830ba12.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041d\u0435 \u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0447\u0442\u043e \u0445\u0430\u043e\u0441 \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u0435\u043d, \u043e\u043d \u043e\u043f\u0430\u0441\u0435\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/942656\/\" rel=\"noopener noreferrer nofollow\">(\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432)<\/a>, \u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435, \u044f \u043e\u0442\u043c\u0435\u0442\u0438\u043b\u0430 \u0447\u0442\u043e <strong><em>\u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430<\/em><\/strong>, \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0443\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438\u00a0\u2014 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0445\u0430\u043e\u0441\u0430 \u0432\u00a0\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0438\u043b\u0438\u00a0\u043f\u0440\u0438\u00a0\u0435\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438, \u0441\u043c\u043e\u0447\u044c \u0435\u0433\u043e \u0440\u0430\u0437\u0433\u0440\u0435\u0441\u0442\u0438.<\/p>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c \u0435\u0449\u0435 \u0440\u0430\u0437 \u0447\u0442\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0432\u0430\u0436\u0435\u043d\u00a0\u2014 \u043f\u0440\u043e\u0449\u0435 \u0432\u043e\u0432\u0440\u0435\u043c\u044f \u00ab\u043f\u0440\u0438\u0431\u0440\u0430\u0442\u044c\u0441\u044f\u00bb, \u0447\u0435\u043c \u043f\u043e\u0442\u043e\u043c \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u043b\u044c\u043d\u0443\u044e \u0443\u0431\u043e\u0440\u043a\u0443. \u041e\u0442\u043c\u0430\u0437\u043a\u0438 \u0432\u0440\u043e\u0434\u0435 \u00ab\u0434\u043e\u0434\u0435\u043b\u0430\u044e \u043f\u043e\u0442\u043e\u043c\u00bb, \u00ab\u043f\u043e\u0436\u0438\u0432\u0451\u043c\u00a0\u2014 \u0443\u0432\u0438\u0434\u0438\u043c\u00bb, \u00ab\u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435\u00bb\u00a0\u2014 \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442!!!! (\u041d\u043e \u044d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043b\u0438\u0448\u044c \u043c\u043e\u0451 \u043c\u043d\u0435\u043d\u0438\u0435 \ud83d\ude42)<\/p>\n<\/div>\n<blockquote>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0435\u043c\u044b:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 <code>.spec<\/code><\/p>\n<\/li>\n<li>\n<p>\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 <code>.spec<\/code><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0445\u0443\u043a\u043e\u0432 <code>beforeEach \/ afterEach \/ describe<\/code><\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0446\u0438\u044f <code>test.step<\/code><\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0433\u043e\u0432 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>Smoke tests<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a smoke \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>E2E (end-to-end) \u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>Codegen\u00a0\u2014 \u043a\u0430\u043a\u00a0\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 e2e (<a href=\"http:\/\/test.info\" rel=\"noopener noreferrer nofollow\"><code>test.info<\/code><\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0431\u043e\u0440 e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 <\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435<\/p>\n<\/li>\n<li>\n<p>\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (\u0442\u0430\u0439\u043c\u0430\u0443\u0442\u044b) \u0432 e2e<\/p>\n<\/li>\n<li>\n<p>API-\u0442\u0435\u0441\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0421\u0445\u0435\u043c\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 (Schemas)<\/p>\n<\/li>\n<li>\n<p>apiRoutes (\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b)<\/p>\n<\/li>\n<li>\n<p>API-\u0445\u0435\u043b\u043f\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>Step pattern \u0434\u043b\u044f API-\u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<\/blockquote>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044e \u043f\u0440\u0430\u0432\u0438\u043b \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u2b50 <strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p><strong><u>\u0434\u043e\u043b\u0436\u0435\u043d:<\/u><\/strong><\/p>\n<\/li>\n<\/ul>\n<ol>\n<li>\n<p><em> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043e\u0434\u0438\u043d \u043a\u0435\u0439\u0441.<\/em><\/p>\n<p>\u041e\u0434\u0438\u043d \u0442\u0435\u0441\u0442 = \u043e\u0434\u0438\u043d \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u041d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442.<\/p>\n<\/li>\n<li>\n<p><em> \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439. <\/em><\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 PageObject (locators, components, helpers), constants, helpers, step pattern, snapshots, components.<\/p>\n<\/li>\n<li>\n<p><em> \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 constants, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 1\u00a0\u0440\u0430\u0437\u0430<\/em>. <\/p>\n<p>\u0425\u0440\u0430\u043d\u0438\u0442\u0435 \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0436\u0435\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u00a0\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u0445 \u0430\u00a0\u043d\u0435\u00a0\u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0442\u0435\u0441\u0442.<\/p>\n<\/li>\n<li>\n<p><em>\u0438\u043c\u0435\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435.<\/em> <\/p>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c, \u0447\u0442\u043e\u00a0\u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><em>\u0431\u044b\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437\u00a0\u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. <\/em><\/p>\n<p>\u0427\u0435\u043c \u043f\u0440\u043e\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0442\u0435\u0441\u0442, \u0442\u0435\u043c \u043e\u043d \u043d\u0430\u0434\u0451\u0436\u043d\u0435\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435. \u0422\u043e \u0435\u0441\u0442\u044c, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u044b \u0447\u0451\u0442\u043a\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0438\u0445 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430\u00a0\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430 \u0438\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u00ab\u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u0435\u043c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0430\u00bb. \u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0431\u043b\u043e\u043a\u0438 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0439\u0442\u0435 \u0432 test.step.<\/p>\n<\/li>\n<li>\n<p> <em>\u044f\u0432\u043d\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<\/em>, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u043b\u043e\u0433\u0438 \u0438\u043b\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0432\u0440\u0443\u0447\u043d\u0443\u044e. <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: userId, orderId, experimentBucket, priceBefore\/priceAfter. <\/p>\n<p>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>test.step('\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f', \u2026)<\/code> \u0441 \u0430\u0441\u0441\u0435\u0440\u0442\u0430\u043c\u0438 \u0432\u0438\u0434\u0430 <code>expect(keyValue, { message: keyValue }).toBeTruthy()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0435 \/ \u043d\u0435 null \/ \u043d\u0435 0, \u043b\u0438\u0431\u043e \u0447\u0435\u0440\u0435\u0437 <code>testInfo.attach<\/code><\/p>\n<\/li>\n<\/ol>\n<ul>\n<li>\n<p><strong><u>\u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d:<\/u><\/strong><\/p>\n<\/li>\n<\/ul>\n<ol>\n<li>\n<p><em>\u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/em><\/p>\n<p>\u0422\u0435\u0441\u0442 \u21162 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0448\u0451\u043b \u0442\u0435\u0441\u0442 \u21161. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0431\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0440\u0435\u0441\u0443\u0440\u0441.<\/p>\n<\/li>\n<li>\n<p><em>\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434.<\/em><\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u043a\u043e\u0434 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445\u00a0\u2014 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0435 \u0435\u0433\u043e \u0432 common(support). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 <strong>helpers<\/strong> \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435, \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438 \u0442. \u0434.), \u0432 <strong>steps<\/strong> \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0448\u0430\u0433\u043e\u0432 \u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0437 PageObject.<\/p>\n<\/li>\n<li>\n<p><em>\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0433\u0438, \u0433\u0434\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0438\u043b\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. <\/em><\/p>\n<p>\u0415\u0441\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b (<code>parametrize tests<\/code>) \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430.<a href=\"https:\/\/playwright.dev\/docs\/test-parameterize#parameterized-projects\" rel=\"noopener noreferrer nofollow\"> Parametirize tests<\/a><\/p>\n<\/li>\n<li>\n<p><em>\u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u0432<\/em> (<code>sleep<\/code>, <code>waitForTimeout<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<\/li>\n<\/ol>\n<ul>\n<li>\n<p><strong><u>\u0441\u043b\u0435\u0434\u0443\u0435\u0442<\/u><\/strong>:<\/p>\n<\/li>\n<\/ul>\n<ol>\n<li>\n<p><em> \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443.<\/em><br \/><em><br \/><\/em>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0442\u0435\u0433\u0438, \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p>\u2b50 <strong>\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432:<\/strong><\/p>\n<ol>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043e\u0440\u043e\u0436\u0435, \u0447\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d \u0438\u043b\u0438 \u0434\u0435\u0448\u0435\u0432\u043b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u2192 \u0442\u0430\u043a\u0438\u0435 \u043a\u0435\u0439\u0441\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438.<\/p>\n<p>\u041e\u043d\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u0435 \u043a\u00a0\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c.<\/p>\n<p>\u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0433\u0434\u0430 \u0447\u0442\u043e\u00a0\u2014 \u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435\u00a0\u0442\u0430\u043a!<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0435\u0439\u0441 \u043d\u0430\u00a0\u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u043d\u043e\u00a0\u0431\u044d\u043a\u0435\u043d\u0434 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d \u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b, \u0432\u043b\u0438\u044f\u044e\u0449\u0438\u0435 \u043d\u0430\u00a0\u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0434\u043b\u044f\u00a0\u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f.<br \/>\u041f\u0440\u0438\u00a0\u044d\u0442\u043e\u043c, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 API\u2011\u0442\u0435\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u044d\u0442\u043e\u0442\u00a0\u0436\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u043d\u0430\u00a0\u043a\u043e\u0434 \u0438 \u043e\u0431\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 (\u0431\u0435\u0437 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438).<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p><strong>\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c .spec:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 PascalCase, \u0433\u0434\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c <strong>\u0441\u0443\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438<br \/><\/strong><br \/>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <code>ProfileSettings.spec.ts<\/code> &#8212; \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, <code>ForgotPassword.spec.ts<\/code> &#8212; \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c .spec<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u0438\u0445 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0438\u0447\u0443 \u0432 \u0446\u0435\u043b\u043e\u043c.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u0441\u0442\u044b ProfileView.spec.ts \u0438 <code>ProfileEdit.spec.ts <\/code>\u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u0439 \u043f\u0430\u043f\u043a\u0435 <code>tests\/e2e\/profile<\/code>, \u0430 \u0444\u0438\u0447\u0430 Authorization \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b <code>ForgotPassword.spec.ts <\/code>\u0438 <code>SignUp.spec.ts<\/code>, \u0433\u0434\u0435 \u043f\u0443\u0442\u044c <code>tests\/e2e\/Authorization\/<\/code> \u0438\u043b\u0438 <code>tests\/api\/AuthCheck\/<\/code><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<p><strong>\u2757\u0412\u0430\u0436\u043d\u043e<\/strong>: <strong><u>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <\/u><\/strong><u>beforeeEach \/ afterEach \/describe <\/u><strong><u>hooks <\/u><\/strong><\/p>\n<p>\u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f (beforeEach), \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f (afterEach) \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 (describe) &#8212; \u044d\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Playwright Test, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b\u0435 \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u0438\u0434\u0430\u043c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 (API, e2e, smoke)<\/p>\n<p><strong><em><u>\u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u043e\u043c:<\/u><\/em><\/strong><\/p>\n<p><strong>BeforeEach <\/strong>\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f: \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043b\u043e\u0433\u0438\u043d, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0442\u0438\u043f\u043e \u0442\u043e\u0433\u043e.<\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0448\u0430\u0433\u0438 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e spec.ts \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>beforeEach<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f beforeEach<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { test, expect } from '@playwright\/test';let createdProducts = {}test.beforeEach(async ({ page, request }) =&gt; {\u00a0\u00a0\/\/ \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e API \u0432\u0435\u0440\u043d\u0451\u0442 \u0441\u043f\u0438\u0441\u043e\u043a\u00a0\u00a0\u00a0\/\/ \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0433\u0434\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f = \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430\u00a0\u00a0createdProducts = await request.post('\/api\/products\/create', {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: { count: 5, category: 'electronics' },\u00a0\u00a0});\u00a0 const createdProducts = await resp.json();\u00a0  \/\/ 2. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \"\u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430\"\u00a0\u00a0await page.goto('\/products\/electronics');\u00a0\u00a0\/\/ 3. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c = 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432\u00a0\u00a0const items = page.locator('[data-testid=\"product-item\"]');\u00a0\u00a0const count = await items.count();\u00a0\u00a0expect(count).toBeGreaterThanOrEqual(5);\u00a0\u00a0\/\/ 4. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430 \u0438\u0437 API\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0 \u00a0const item = page.locator([data-testid=\"product-item\"][data-id=\"${product.id}\"]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0432\u00a0spec.ts \u0432\u00a0beforeEach \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u00a0API, \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u00a0\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438. \u0414\u043b\u044f\u00a0\u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u043d\u043e\u00a0\u043f\u043b\u043e\u0445\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432\u00a0\u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 (\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438\u00a0\u0442.\u00a0\u0434.), \u0442\u043e \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0441\u043a\u0438 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435\u00a0\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u0438 \u0442\u043e\u0436\u0435\u00a0\u2014 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0441\u0435 \u0447\u0442\u043e\u00a0\u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0432\u00a0\u0445\u0435\u043b\u043f\u0435\u0440\u044b \u0438\u043b\u0438\u00a0\u0432\u00a0pageObject (\u0441\u043c. \u043f\u0440\u0438\u043c\u0435\u0440)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u0440\u0435\u0444\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e beforeEach<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/common\/helpers\/products-helper.tsimport { APIRequestContext} from '@playwright\/test';import { PRODUCT_CREATE} from 'playwrightTests\/common\/apiRoutes';\/**\u00a0* \u0421\u043e\u0437\u0434\u0430\u0451\u0442 n \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\u00a0\u00a0*\/export async function createManyProductsByCategory(\u00a0\u00a0request: APIRequestContext,\u00a0\u00a0categoryName: string,\u00a0\u00a0totalCount: number) {\u00a0\u00a0try {\u00a0\u00a0\u00a0\u00a0const resp = await request.post(PRODUCT_CREATE, {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: { count: totalCount, category: categoryName },\u00a0\u00a0\u00a0\u00a0});\u00a0\u00a0\u00a0\u00a0if (!resp.ok()) {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error(\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432. Status: ' + resp.status()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0const data = await resp.json();\u00a0\u00a0\u00a0\u00a0if (!Array.isArray(data)) {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error('API \u0432\u0435\u0440\u043d\u0443\u043b\u043e \u041d\u0415 \u043c\u0430\u0441\u0441\u0438\u0432');\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0return data;\u00a0\u00a0} catch (err) {\u00a0\u00a0\u00a0\u00a0throw err\u00a0\u00a0}}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0414\u0430\u043b\u0435\u0435, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 test.step \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/strong><\/p>\n<pre><code>\u0411\u044b\u043b\u043e----------------------\/\/ 3. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c &gt; 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432\u00a0\u00a0const items = page.locator('[data-testid=\"product-item\"]');\u00a0\u00a0const count = await items.count();\u00a0\u00a0expect(count).toBeGreaterThan(limit);---------------------\u0421\u0442\u0430\u043b\u043e: \u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 - \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 steptest.step('\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c &gt; 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432',\u00a0\u00a0\u00a0async () =&gt; {\u00a0\u00a0\u00a0const item = page.getByTestId(PRODUCT_ITEM);\u00a0\u00a0\u00a0const count = await item.count();\u00a0\u00a0\u00a0expect(count).toBeGreaterOrEqual(limit);})---------------------\u0421\u0442\u0430\u043b\u043e: \u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 - \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject (\u043b\u0443\u0447\u0448\u0435)\/\/ common\/pages\/ProductListPage.tsasync checkProductsCount(limit: number) {\u00a0\u00a0const count = await this.item.count();\u00a0\u00a0await expect(count).toBeGreaterThanOrEqual(limit);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0442\u043e \u044d\u0442\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 id \u0442\u043e\u0432\u0430\u0440\u0430 \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0442\u043e\u0432\u0430\u0440\u0430<\/strong><\/p>\n<pre><code>\u0411\u044b\u043b\u043e-----------------------\/\/ 4. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0\u00a0const item = page.locator([data-testid=\"product-item\"][data-id=\"${product.id}\"]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible(); \u00a0\u00a0}\u0421\u0442\u0430\u043b\u043e\u00a0----------------\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 - \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 steptest.step('\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430', async () =&gt; {\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0\u00a0const item = page.getByTestId(PRODUCT_ITEM).locator([data-id=\"${product.id}\"]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}});-------------------\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 - \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject (\u043b\u0443\u0447\u0448\u0435)\/\/ common\/locators\/product-locators.tsexport function getProductCardById(id: number): string {\u00a0\u00a0return [data-testid=\"${PRODUCT_ITEM}\"][data-id=\"${id}\"];}\/\/ common\/pages\/ProductListPage.tsasync verifyProductCardsVisible(products: { id: number }[]) {\u00a0\u00a0for (const product of products) {\u00a0\u00a0\u00a0const item = this.page.locator(getProductCardById(product.id));\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0438\u0434 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/strong><\/p>\n<pre><code>import { test, expect } from '@playwright\/test';import { createManyProductsByCategory} from '..\/..\/common\/helpers\/products-helper';import { ProductListPage } from '..\/..\/pages\/ProductListPage';import { CATEGORIE_NAMES, PRODUCT_ITEM } from '..\/..\/common\/constants\/....';\/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c storageState \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435test.use({ storageState: AUTH_ROLE_STATES.customer.first });let createdProducts: {}\u00a0test.beforeEach(async ({ page, request }) =&gt; {  productsPage\u00a0 \u00a0 = new ProductListPage(page);\u00a0\u00a0createdProducts = await createManyProductsByCategory(\u00a0\u00a0\u00a0\u00a0request,\u00a0\u00a0\u00a0\u00a0CATEGORIE_NAMES.electronics,\u00a0\u00a0\u00a0\u00a0LIMIT\u00a0\u00a0);  test.step('\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0438', async () =&gt; {\u00a0\u00a0\u00a0\u00a0\u00a0await page.goto('\/products?category=' + CATEGORIE_NAMES.electronics);\u00a0\u00a0})\u00a0\u00a0await productsPage.checkProductsCount(LIMIT);\u00a0\u00a0await productsPage.verifyProductCardsVisible(createdProducts);});  <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong><em><u>\u041f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430:<\/u><\/em><\/strong><\/p>\n<p><strong>AfterEach<\/strong> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f: \u043e\u0447\u0438\u0441\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0435, \u0441\u0431\u0440\u043e\u0441\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<p>\u0427\u0430\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0447\u0438\u0449\u0430\u0442\u044c \u0437\u0430 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043e 5\u00a0\u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432\u00a0\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u00ab\u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430\u00bb. \u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 \u044d\u0442\u0438 \u0442\u043e\u0432\u0430\u0440\u044b \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<\/p>\n<p>\u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0442\u043e \u0435\u0441\u0442\u044c \u0445\u0443\u043a <strong>afterEach<\/strong> (\u0438\u043b\u0438 afterAll, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u0449\u0438\u0435 \u043d\u0430 \u0432\u0435\u0441\u044c \u043d\u0430\u0431\u043e\u0440 \u0442\u0435\u0441\u0442\u043e\u0432).<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f afterEach<\/summary>\n<div class=\"spoiler__content\">\n<p><strong><em>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432 \u0444\u0430\u0439\u043b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c .spec.ts \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f ProductListActions. \u0412 \u043d\u0435\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 3 \u0442\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0443\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 1 \u0442\u043e\u0432\u0430\u0440\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/em><\/strong><\/p>\n<p><strong><em>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:<\/em><\/strong><\/p>\n<pre><code>\/\/ playwrightTests\/tests\/e2e\/ProductListActions.spec.tstest('\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0438\u00a0\u00a0\u00a0\u00a0\u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0445 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f', async () =&gt; {\u00a0\u00a0...});test('\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u0432\u0430\u0440\u0430 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443', async () =&gt; {\u00a0\u00a0...});test('\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u0438\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435', async () =&gt; {\u00a0\u00a0...});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong><em>\u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430, \u0445\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u0441\u0440\u0430\u0437\u0443 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0442\u043e\u0432\u0430\u0440\u044b \u0432\u00a0\u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0438. \u0423\u0434\u0430\u043b\u044f\u0442\u044c \u0442\u043e\u0432\u0430\u0440\u044b \u043d\u0443\u0436\u043d\u043e \u0432\u00a0\u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0438\u00a0\u2014 afterEach.<\/em><\/strong><\/p>\n<p><strong><em>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 api \u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0442\u043e\u0432\u0430\u0440 \u043f\u043e \u0435\u0433\u043e id.<\/em><\/strong><\/p>\n<pre><code>\/\/common\/helpers\/products-helper.tsimport { APIRequestContext} from '@playwright\/test';import { PRODUCT_CREATE} from 'playwrightTests\/common\/apiRoutes';\/**\u00a0* \u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0442\u043e\u0432\u0430\u0440 \u043f\u043e \u0435\u0433\u043e Id\u00a0*\/export async function deleteProductById(\u00a0\u00a0\u00a0request: APIRequestContext,\u00a0\u00a0\u00a0\u00a0id: number) {  const resp = await request.delete(API_ENDPOINTS.PRODUCTS, {\u00a0\u00a0\u00a0\u00a0 \u00a0data: { productId: id },\u00a0\u00a0 });\u00a0\u00a0 expect(resp.status()).toBe(200);});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u0430 \u043f\u043e \u0435\u0433\u043e id \u0432 \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0438:<\/strong><\/p>\n<pre><code>\/\/ playwrightTests\/tests\/e2e\/ProductListActions.spec.ts\/* * \u041f\u043e\u0434\u0449\u0438\u0449\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u044b\u0435 \u0442\u043e\u0432\u0430\u0440\u044b \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430*\/test.afterEach(async ({ request }) =&gt; {\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0\u00a0await deleteProductById(request, product.id);\u00a0\u00a0}});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong><u>\u0425\u0443\u043a test.describe (\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432):<\/u><\/strong><\/p>\n<p>\u0425\u0443\u043a test.describe \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u0441\u0442\u043e\u0432 <strong>\u0432 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443 <\/strong>\u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e spec.ts. <\/p>\n<p>\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c <strong>\u0441\u0432\u043e\u0438<\/strong> <code>beforeEach<\/code>\/<code>afterEach<\/code> \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0433\u0440\u0443\u043f\u043f. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0430\u0431\u043e\u0440 \u0442\u0435\u0441\u0442\u043e\u0432 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445. \u0422\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 <strong>\u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/strong>, \u0447\u0435\u043c \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u2192 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <code>describe<\/code>, \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0437\u0430\u0447\u0435\u043c \u0438\u043d\u043e\u0433\u0434\u0430 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u0440\u0438\u043c\u0435\u0440.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0432 \u0444\u0430\u0439\u043b\u0435 \u0435\u0441\u0442\u044c 5 \u0442\u0435\u0441\u0442\u043e\u0432: \u0434\u043b\u044f 3 \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435\/\u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u0430 \u0434\u043b\u044f 2\u00a0\u0442\u0435\u0441\u0442\u043e\u0432\u00a0\u2014 \u043d\u0435\u0442, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 5\u00a0\u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043d\u0430\u00a0\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0430 20, \u043f\u0440\u0438\u0447\u0451\u043c \u0432\u00a0\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u00ab\u0442\u043e\u0432\u0430\u0440\u044b \u0434\u043b\u044f\u00a0\u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445\u00bb \u0441\u00a0\u0446\u0435\u043b\u044c\u044e \u00ab\u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e\u00a0\u0446\u0435\u043d\u0435 \u0438\u043b\u0438\u00a0\u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438\u00bb.<\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u044d\u0442\u0438 2\u00a0\u0442\u0435\u0441\u0442\u0430 \u0432\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u044f\u00a0\u043d\u0435\u0433\u043e \u0438\u043c\u044f, \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u044f\u043c\u043e \u0432\u00a0\u0442\u043e\u043c\u00a0\u0436\u0435 \u0444\u0430\u0439\u043b\u0435\u00a0\u2014 \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0438 \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e spec.ts<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0442\u043e\u0432 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b\u00a0\u2014 test.describe<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b &#8212; test.describe<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>test.describe('\u041f\u0435\u0440\u0432\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430', () =&gt; {  \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c storageState \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u0442\u0435\u0441\u0442\u043e\u0432  test.use({ storageState: AUTH_ROLE_STATES.customer.first });  let createdProducts: {};  const LIMIT = 5;  test.beforeEach(async ({ page, request }) =&gt; {    const productsPage = new ProductListPage(page);    createdProducts = await createManyProductsByCategory(      request,      CATEGORIE_NAMES.electronics,      LIMIT    );    await test.step('\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0438', async () =&gt; {      await page.goto('\/products?category=' + CATEGORIE_NAMES.electronics);    });    await productsPage.checkProductsCount(LIMIT);    await productsPage.verifyProductCardsVisible(createdProducts);  });  test('\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0445 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f', async () =&gt; {    \/\/ ...  });  test('\u0422\u0435\u0441\u0442 \u21162', async () =&gt; {    \/\/ ...  });  test('\u0422\u0435\u0441\u0442 \u21163', async () =&gt; {    \/\/ ...  });  test.afterEach(async ({ request }) =&gt; {    for (const product of createdProducts) {      await deleteProductById(request, product.id);    }  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0412 \u044d\u0442\u043e\u043c \u0436\u0435 <\/strong><code><strong>.spec.ts<\/strong><\/code><strong> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443 \u0442\u0435\u0441\u0442\u043e\u0432<\/strong><\/p>\n<pre><code>\/\/ \u0412\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430test.describe('\u0412\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430', () =&gt; {  \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c storageState \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435  \/\/ \u0423\u0436\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c  test.use({ storageState: AUTH_ROLE_STATES.customer.second });  let createdProducts: {};  const LIMIT = 20;  test.beforeEach(async ({ page, request }) =&gt; {    const productsPage = new ProductListPage(page);    createdProducts = await createManyProductsByCategory(      request,      CATEGORIE_NAMES.animalCare,      LIMIT    );    await test.step('\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0434\u043b\u044f \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445', async () =&gt; {      await page.goto('\/products?category=' + CATEGORIE_NAMES.animalCare);    });    await productsPage.checkProductsCount(LIMIT);    await productsPage.verifyProductCardsVisible(createdProducts);  });  test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435', async () =&gt; {    \/\/ ...  });  test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438', async () =&gt; {    \/\/ ...  });  test.afterEach(async ({ request }) =&gt; {    for (const product of createdProducts) {      await deleteProductById(request, product.id);    }  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong><u>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u043f\u0446\u0438\u0438 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u2014 test.step:<\/u><\/strong><\/p>\n<p>\u0412 Playwright \u0435\u0441\u0442\u044c \u043e\u043f\u0446\u0438\u044f test.step, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u043e\u0434\u0438\u043d \u0448\u0430\u0433. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c, \u0430 \u0432 \u043e\u0442\u0447\u0451\u0442\u0435 HTML \u0438\u043b\u0438 Trace Viewer \u0448\u0430\u0433\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u0442\u0435\u0441\u0442 \u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435 (\u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435). \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430 \u0440\u0430\u0437\u043e\u0431\u044c\u0451\u043c \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0438 \u043e\u0431\u0435\u0440\u043d\u0451\u043c \u0438\u0445 \u0432 test.step, \u0447\u0442\u043e\u0431\u044b \u0448\u0430\u0433\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u043a\u0430\u043a \u0432 \u043a\u043e\u0434\u0435, \u0442\u0430\u043a \u0438 \u0432 \u043e\u0442\u0447\u0451\u0442\u0430\u0445.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435\u0442 \u0441\u0442\u0435\u043f\u043e\u0432, \u0430 \u043a\u043e\u043c\u0435\u043d\u0442\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0431\u0435\u0437 test.step<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435', async ({ page, request }) =&gt; {  const products = new ProductListPage(page);  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 (\u0442\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u0435\u043d\u0442\u044b \u043b\u0443\u0447\u0448\u0435 \u0443\u0431\u0440\u0430\u0442\u044c)  await sortProductsByPrice(request, 'desc');  await products.open('\/products');  await products.sortByPriceDesc();  \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430: \u0442\u043e\u0432\u0430\u0440\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0446\u0435\u043d\u044b   const prices = await page.locator('[data-testid=\"product-price\"]').allTextContents();  await products.toBeSortedInDescendingOrder();});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0411\u0435\u0437 test.step \u043e\u0442\u0447\u0451\u0442 \u043b\u0438\u0448\u0451\u043d \u0441\u043c\u044b\u0441\u043b\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432\u0438\u0434\u043d\u0430, \u043d\u043e \u044d\u0442\u0430\u043f\u044b (\u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430, \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438) \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u044b.<\/p>\n<pre><code>\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435- GET \/api\/products?sort=price_desc- page.goto('\/products')- click [data-testid=\"sort-by-price\"]- locator('[data-testid=\"product-price\"]').allTextContents()- expect([...]).toEqual([...])<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u0435\u0440\u043d\u0435\u043c, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0432 test.step:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 test.step<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435', async ({ page, request }) =&gt; {  const products = new ProductListPage(page);  await test.step('\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 API', async () =&gt; {    await sortProductsByPrice(request, 'desc');  });  await test.step('\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0432 UI', async () =&gt; {    await products.open('\/products');    await products.sortByPriceDesc();  });  await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0442\u043e\u0432\u0430\u0440\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0446\u0435\u043d\u044b', async () =&gt;  {    const prices = await page.getByTestId(PRODUCT_PRICE).allTextContents();        await products.toBeSortedInDescendingOrder();  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0442\u0447\u0435\u0442 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c test.step \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0435\u0435:<\/p>\n<pre><code>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 API\u00a0\u00a0\u00a0- GET \/api\/products?sort=price_desc\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443\u00a0\u00a0\u00a0- page.goto('\/products')\u00a0\u00a0\u00a0- click [data-testid=\"sort-by-price\"]\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0446\u0435\u043d\u00a0\u00a0\u00a0- allTextContents()\u00a0\u00a0\u00a0- expect(...)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0418\u0442\u043e\u0433<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>test.step<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430 \u0438 \u043e\u0442\u0447\u0451\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433 \u0432\u0438\u0434\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u0438\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443.<\/p>\n<\/li>\n<\/ul>\n<p><strong><em><u>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0433\u043e\u0432 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0435:<\/u><\/em><\/strong><\/p>\n<p>\u0422\u0435\u0433\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442:<\/p>\n<ul>\n<li>\n<p>\u043e\u0442\u043c\u0435\u0447\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b. <\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0435\u0433 @screenshot\u00a0\u2014 \u0442\u043e \u0435\u0441\u0442\u044c, \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0447\u0442\u043e\u00a0\u0432\u00a0\u0434\u0430\u043d\u043d\u043e\u043c \u0442\u0435\u0441\u0442\u0435 \u0435\u0441\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0438\u043b\u0438 @smoke\u00a0\u2014 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0442\u0435\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043c\u043e\u0443\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u043d\u0443 \u0438\u043b\u0438 @flaky\u00a0\u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0435\u0439\u0441 \u0442\u043e \u0443\u0441\u043f\u0435\u0448\u0435\u043d \u0442\u043e \u043d\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0442\u0435\u0433\u0430 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u00abnpx playwright test \u2011grep @screenshot\u00bb \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0442\u0435\u0433. \u0410\u00a0\u0435\u0449\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0443\u00a0\u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u00a0\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 &#8212; &#171;npx playwright test &#8212;grep <a class=\"mention\" href=\"\/users\/screenshot\">@screenshot<\/a> &#8212;update-snapshots&#187;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0438\u0434\u0435\u0442\u044c \u0442\u0435\u0433\u0438 \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u043a\u0435\u0439\u0441\u043e\u0432 \u0432\u043e \u0432\u0441\u0435\u0445 \u043e\u0442\u0447\u0451\u0442\u0430\u0445, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0432 \u043e\u0442\u0447\u0451\u0442\u0430\u0445 TMS (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, [@screenshot] \u0412\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f\u00a0\u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u00a0\u043e\u0442\u0447\u0435\u0442\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0442\u0435\u0433 \u0438 \u043f\u043e\u00a0\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0442\u0435\u0441\u0442\u0435 \u0435\u0441\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430)<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0433\u043e\u0432 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 (\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043e\u0444\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0435 <a href=\"https:\/\/playwright.dev\/docs\/test-annotations#tag-tests\" rel=\"noopener noreferrer nofollow\">Tag tests<\/a>)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u0433\u043e\u0432 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>test.describe('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432', {  tag: '@sortProducts', }, () =&gt; {  test('\u0421\u043e\u0440\u0442\u0438\u0440\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435 (\u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e)', async ({ page }) =&gt; {    \/\/ ...  });  test('\u0421\u043e\u0440\u0442\u0438\u0440\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443', {    tag: ['@screenshot', '@slow'],  }, async ({ page }) =&gt; {    \/\/ ...  });<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ul>\n<li>\n<p>tag: &#8216;@sortProducts&#8217; \u2014 \u044d\u0442\u043e \u0442\u0435\u0433 \u043d\u0430\u00a0\u0432\u0441\u044e \u0433\u0440\u0443\u043f\u043f\u0443 \u0442\u0435\u0441\u0442\u043e\u0432, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u00a0\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0432 \u0442\u0435\u0433 \u0432\u00a0\u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430: npx playwright test &#8212;grep @sortProducts<\/p>\n<\/li>\n<li>\n<p>tag: [&#8216;@screenshot&#8217;, &#8216;@slow&#8217;] \u2014 \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u0442 \u0447\u0442\u043e\u00a0\u0442\u0435\u0441\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u044b\u0439 <\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0432\u00a0\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<p><code>npx playwright test --grep \"@sortProducts.*@screenshots\" --update-snapshots<\/code><\/p>\n<\/div>\n<\/details>\n<p><strong><em><u>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0432 Playwright (\u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u0441 \u0434\u0430\u0442\u0430 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u043c):<\/u><\/em><\/strong><\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0435\u0441\u0442-\u043a\u0435\u0439\u0441\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430 \u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0445\u043e\u0434\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0442\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c (<a href=\"https:\/\/playwright.dev\/docs\/test-parameterize#parameterized-tests\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u043e\u0444\u0444 \u0434\u043e\u043a\u0438<\/a>). \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432, \u0430 \u0442\u0435\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043a\u0435\u0439\u0441\u044b \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433 \u0436\u0435 \u0442\u043e\u0432\u0430\u0440\u0430 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435:<\/p>\n<ul>\n<li>\n<p>1 \u043a\u0435\u0439\u0441\u00a0\u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e\u00a0\u0432\u00a0\u043a\u043e\u0440\u0437\u0438\u043d\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0445\u043e\u0442\u044f\u00a0\u0431\u044b 1\u00a0\u0442\u043e\u0432\u0430\u0440 \u0438 \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 1.<\/p>\n<\/li>\n<li>\n<p>2\u00a0\u043a\u0435\u0439\u0441\u00a0\u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 5 \u0448\u0442\u0443\u043a) \u043a\u043e\u0440\u0437\u0438\u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043b\u0438\u043c\u0438\u0442 \u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442\u044c \u0435\u0433\u043e.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/** * Data provider \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0430  * \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435 **\/const BASKET_SCENARIOS = [    { testName: '\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430',  count: 1,  expected: 1 },    { testName: '\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430',  count: 5,  expected: 5 },];for (const scenario of BASKET_SCENARIOS) {    test(`\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 ${scenario.testName} (${scenario.count}) \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443`, async ({ page, request }) =&gt;{        const productPage = new ProductPage(page);        const product = await test.step('\u0412\u044b\u0431\u043e\u0440 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u0442\u043e\u0432\u0430\u0440\u0430', async () =&gt; {            return await getRandomProduct(request);        });        const productId = product.id;        await test.step('\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0442\u043e\u0432\u0430\u0440\u0430', async () =&gt; {            await page.goto(`\/product\/${productId}`);        });        await test.step('\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0432\u0430\u0440\/\u044b \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443', async () =&gt; {            for (let i = 0; i &lt; scenario.count; i++) {                await productPage.addProductToBasket(i);            }        });        await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0437\u0438\u043d\u0443', async () =&gt; {            await page.goto('\/cart');            await expect(page.locator(PRODUCT_ID_COUNT)).toHaveCount(scenario.expected);        });    });}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<hr\/>\n<p><strong><em>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u0432\u0438\u0434\u0430\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432:<\/em><\/strong><\/p>\n<p>\u26a0\ufe0f \u0412 Playwright \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u2014 <code>.spec.ts,<\/code> \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p><strong>\u00a0\u041f\u0443\u0442\u044c \u043a \u0442\u0435\u0441\u0442\u0430\u043c:<\/strong><code> playwrightTests\/tests\/<\/code><\/p>\n<div class=\"floating-image\">\n<figure class=\"float full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/38f\/fec\/75f\/38ffec75fa7b48a61d30cd45b38c18da.png\" width=\"542\" height=\"502\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/38f\/fec\/75f\/38ffec75fa7b48a61d30cd45b38c18da.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/38f\/fec\/75f\/38ffec75fa7b48a61d30cd45b38c18da.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/div>\n<p>\u26a0\ufe0f \u0412 \u043f\u0430\u043f\u043a\u0435 tests \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0442\u0440\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438: <strong>smoke, e2e, api.<\/strong><\/p>\n<hr\/>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/86c\/3de\/fcb\/86c3defcbdbb00ecb7eccf87ee6e53ca.png\" alt=\"\u041a\u043e\u0442\u0438\u043a\u0438 \u043d\u0435 \u043a\u0443\u0440\u044f\u0442 \u0442\u0435\u0441\u0442\u044b!  \u041a\u043e\u0442\u0438\u043a\u0438 \u0438\u0445 \u043f\u0438\u0448\u0443\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442!\" title=\"\u041a\u043e\u0442\u0438\u043a\u0438 \u043d\u0435 \u043a\u0443\u0440\u044f\u0442 \u0442\u0435\u0441\u0442\u044b! \u041a\u043e\u0442\u0438\u043a\u0438 \u0438\u0445 \u043f\u0438\u0448\u0443\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442!\" width=\"1536\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/86c\/3de\/fcb\/86c3defcbdbb00ecb7eccf87ee6e53ca.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/86c\/3de\/fcb\/86c3defcbdbb00ecb7eccf87ee6e53ca.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u043e\u0442\u0438\u043a\u0438 \u043d\u0435 \u043a\u0443\u0440\u044f\u0442 \u0442\u0435\u0441\u0442\u044b! \u041a\u043e\u0442\u0438\u043a\u0438 \u0438\u0445 \u043f\u0438\u0448\u0443\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442!<\/figcaption><\/div>\n<\/figure>\n<p><strong>1) Smoke tests <\/strong>\u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e. \u041e\u043d\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0447\u0442\u043e \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<p>Smoke\u00a0\u2014 \u044d\u0442\u043e \u0444\u0430\u0439\u043b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u0447\u0442\u043e \u0432\u0435\u0442\u043a\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u0434 200, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442, \u043d\u0435 \u043f\u043e\u043b\u043e\u043c\u0430\u043d\u044b \u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0438 \u0442\u0438\u043f\u043e \u0442\u043e\u0433\u043e.<\/p>\n<p>\u0412 Smoke \u0442\u0435\u0441\u0442\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u043c\u0438\u043a\u0441\u043e\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u044b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u0430\u043a UI \u0442\u0430\u043a \u0438 API. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0447\u0442\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 200 \u043a\u043e\u0434 \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0431\u0434 \u0438 \u0442\u0438\u043f\u043e \u0442\u043e\u0433\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b Health Check<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/ Smoke tests .\/tests\/smoke\/HealthCheck\u00a0test('is host alive', async ({ page }) =&gt; {\u00a0\u00a0\u00a0const response = await page.goto('https:\/\/example.com\/');\u00a0\u00a0\u00a0expect(response?.status()).toBe(200);   await expect(page).toHaveTitle(\/Example Domain\/);});test('\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442', async ({ request }) =&gt; {\u00a0\u00a0const userCheck = await request.get('\/api\/users\/testUser\/email=testUser@email.com');\u00a0\u00a0\u00a0\u00a0expect(userCheck.status()).toBe(200);\u00a0\u00a0const body = await userCheck.json();\u00a0\u00a0expect(body).toHaveProperty('isAlive');\u00a0\u00a0expect(body.isAlive).toBe(true);});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><u>\u2b07\ufe0f <\/u><strong><u>\u0417\u0430\u043f\u0443\u0441\u043a smoke \u0442\u0435\u0441\u0442\u043e\u0432:<\/u><\/strong><\/p>\n<p>Smoke-\u0442\u0435\u0441\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u043d\u044c\u0448\u0435 setup, \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u0438\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u043d\u0430 \u0441\u0430\u043c\u044b\u0439 \u0432\u0435\u0440\u0445 \u043f\u043e \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432.<\/p>\n<p>\u0412 Smoke-\u0442\u0435\u0441\u0442\u0430\u0445 \u041d\u0415 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>storageState<\/code> \u0438 <code>retries<\/code><a href=\"https:\/\/playwright.dev\/docs\/test-projects#splitting-tests-into-projects\" rel=\"noopener noreferrer nofollow\"> <\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { defineConfig } from '@playwright\/test';export default defineConfig({\u00a0\u00a0projects: [\u00a0\u00a0\u00a0\u00a0\u00a0{\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ smoke tests\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: 'health_check',      testMatch: \/.*\\.HealthCheck.spec\\.ts\/,\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testDir: '.\/tests\/smoke',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fullyParallel: true,\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0retries: 0,\u00a0\u00a0\u00a0\u00a0},\u00a0\u00a0\u00a0\u00a0{\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ setup auth \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u043c \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0444\u0430\u0439\u043b\u044b \u0432 .auth\/\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: 'setup auth',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testIgnore: \/.*\\.HealthCheck.spec\\.ts\/, \/\/\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043c\u043e\u0443\u043a \u0442\u0435\u0441\u0442\u043e\u0432\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testMatch: \/.*\\.setup\\.ts\/, \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 setup\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testDir: '.\/tests',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fullyParallel: true,\u00a0\u00a0\u00a0\u00a0},    {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0name: 'chrome'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testIgnore: \/.*\\.HealthCheck.spec\\.ts\/, \/\/\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043c\u043e\u0443\u043a \u0442\u0435\u0441\u0442\u043e\u0432\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0testDir: '.\/tests',\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fullyParallel: true,\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dependencies: ['setup auth'], \/\/ \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 setup auth\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0retries: 1,\u00a0\u00a0\u00a0}\u00a0\u00a0]});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u2757\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c smoke\u2011\u0442\u0435\u0441\u0442\u044b, \u043d\u043e\u00a0\u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439\u00a0\u2014 \u044d\u0442\u043e \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0432\u00a0gitlab.yaml\u00a0\u2014 \u0442\u043e \u0435\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0441\u0442\u0430\u0434\u0438\u044f smoke \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0430, \u0442\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0432\u0435\u0442\u043a\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f, \u0434\u0436\u043e\u0431\u0430 \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043a\u0440\u0430\u0441\u043d\u0430\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442. \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c<a href=\"https:\/\/habr.com\/ru\/companies\/selectel\/articles\/819509\/\" rel=\"noopener noreferrer nofollow\"> \u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430\u0445<\/a><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043c\u043e\u0443\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 CI|CD<\/summary>\n<div class=\"spoiler__content\">\n<pre><code># \u0415\u0441\u043b\u0438 \u0434\u0436\u043e\u0431\u0430 \u0441 smoke \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0443\u043f\u0430\u0434\u0451\u0442 - \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f\u00a0# \u0414\u0436\u043e\u0431\u0430 \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430\u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0435\u0441\u043b\u0438 \u0441\u043c\u043e\u0443\u043a \u043d\u0435 \u0443\u0441\u043f\u0435\u0448\u0435\u043dstages:\u00a0\u00a0- smoke\u00a0\u00a0- test# 1) \u041f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043c\u043e\u0443\u043asmoke:\u00a0\u00a0stage: smoke\u00a0\u00a0image: mcr.microsoft.com\/playwright:v1.54.0-jammy\u00a0\u00a0before_script:\u00a0\u00a0\u00a0\u00a0- npm ci\u00a0\u00a0script:\u00a0\u00a0\u00a0\u00a0- npx playwright test --grep \"@smoke\"\u00a0\u00a0allow_failure: false\u00a0\u00a0\u00a0\u00a0\u00a0when: on_success\u00a0\u00a0# 2) \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u2014 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0422\u041e\u041b\u042c\u041a\u041e \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0448\u0451\u043b smokee2e_rest:\u00a0\u00a0stage: test\u00a0\u00a0image: mcr.microsoft.com\/playwright:v1.54.0-jammy\u00a0\u00a0before_script:\u00a0\u00a0\u00a0\u00a0- npm ci\u00a0\u00a0script:\u00a0\u00a0\u00a0\u00a0- npx playwright test --grep-invert \"@smoke\"\u00a0\u00a0needs: [\"smoke\"]\u00a0\u00a0\u00a0<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<pre><code># \u043b\u0438\u0431\u043e \u0441\u0442\u043e\u043f\u0430\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u00a0# \u043a\u043e\u0433\u0434\u0430 \u0441\u043c\u043e\u0443\u043a \u0442\u0435\u0441\u0442\u044b \u0443\u043f\u0430\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0435script:\u00a0\u00a0\u00a0\u00a0- |\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0npx playwright test tests\/smoke\/HealthCheck.spec.ts\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if [ $? -ne 0 ]; then\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0exit 1\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0npx playwright test --grep-invert \"@smoke\"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fi<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<hr\/>\n<p><strong>2) E2E (end-to-end) \u0442\u0435\u0441\u0442\u044b <\/strong>\u2014 \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u0438 \u0442\u0435\u0441\u0442\u044b \u0441\u0430\u043c\u044b\u0435 \u0442\u044f\u0436\u0435\u043b\u044b\u0435 \u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435, \u043d\u043e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435.<\/p>\n<p>\u0426\u0435\u043b\u044c E2E \u0442\u0435\u0441\u0442\u0430\u00a0\u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0447\u0442\u043e \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0431\u044d\u043a\u0435\u043d\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0438 \u0434\u0430\u044e\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p><strong><em>\u041f\u0443\u0442\u044c \u043a E2E \u0442\u0435\u0441\u0442\u0430\u043c<\/em><\/strong><em>:<\/em> <code>playwrightTests\/tests\/e2e<\/code><\/p>\n<blockquote>\n<p>\u26a0\ufe0f \u0412 E2E-\u0442\u0435\u0441\u0442\u0430\u0445, \u0433\u0434\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f, \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 <code>storageState<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 <code>storageState<\/code> \u0438 \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <strong><em><u>(<\/u><\/em><\/strong><a href=\"https:\/\/habr.com\/ru\/articles\/942656\/#:~:text=%F0%9F%93%8C\" rel=\"noopener noreferrer nofollow\">\u0410\u0443\u0435\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/a><u> &#8212; \u0413\u043b\u0430\u0432\u0430 3. \u0410\u0443\u0435\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445)<\/u><\/p>\n<\/blockquote>\n<p><u>\u2b07\ufe0f <\/u><strong><u>Codegen \u2014 \u043a\u0430\u043a \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430:<\/u><\/strong><\/p>\n<p>\u0427\u0430\u0441\u0442\u043e \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043a\u0430\u043a \u043d\u0430\u0439\u0442\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0438 \u0442\u0443\u0442 Playwright \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0444\u0438\u0447\u0435\u0439 \u043a\u0430\u043a \u043a\u043e\u0434\u0435\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f (<a href=\"https:\/\/playwright.dev\/docs\/codegen-intro#running-codegen\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0432\u00a0\u043e\u0444\u0444 \u0434\u043e\u043a\u0435 \u2192 Generating tests<\/a>). <\/p>\n<p>\u0427\u0430\u0441\u0442\u043e \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440. \u0412 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0432 Playwright \u0444\u0438\u0447\u0430\u00a0\u2014 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0432\u00a0\u043e\u0444\u0444 \u0434\u043e\u043a\u0435 \u2192 <a href=\"https:\/\/playwright.dev\/docs\/codegen-intro#running-codegen\" rel=\"noopener noreferrer nofollow\">Generating tests<\/a>). <\/p>\n<p>\u26a0\ufe0f \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u043b\u043e\u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0442\u044c \u044d\u0442\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e. \u041a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u043a\u0430\u043a \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430, \u043d\u043e \u043e\u043d\u0430 \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a: <\/p>\n<ul>\n<li>\n<p> \u043d\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b<\/p>\n<\/li>\n<li>\n<p> \u043d\u0435 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442 \u0438\u0445 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 <code>PageObject<\/code> \u0438\u043b\u0438 <code>ComponentObject<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418 \u0432\u043e\u0442 \u0441\u0443\u0442\u044c \u0442\u0430\u043a\u043e\u0432\u0430, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u043a\u0438\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a \u0438\u043b\u0438 \u0432\u0435\u0442\u0445\u0443\u044e \u043e\u0441\u043d\u043e\u0432\u0443 \u0442\u0435\u0441\u0442\u0430, \u00ab\u041d\u041e\u00bb \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u044c\u0442\u0430\u0431\u0438\u043b\u0435\u043d, \u043c\u043e\u0436\u043d\u043e\u00a0\u043b\u0438\u00a0\u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u044b\u043c, \u0447\u0442\u043e\u00a0\u0442\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u00a0\u0442\u0435\u0441\u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438?<\/p>\n<blockquote>\n<p>\u042f \u0432\u0441\u0451 \u044d\u0442\u043e \u043a\u00a0\u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u00a0\u0435\u0441\u043b\u0438 \u043f\u0438\u0448\u0435\u0442\u0435 \u04352\u0435 \u0442\u0435\u0441\u0442, \u041d\u041e\u00a0\u043d\u0435\u00a0\u0437\u043d\u0430\u0435\u0442\u0435 \u0441\u00a0\u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c\u00a0\u2014 \u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c <strong>codegen<\/strong> (\u0448\u0442\u0443\u043a\u0430 \u0445\u043e\u0440\u043e\u0448\u0430\u044f), \u043d\u043e\u00a0\u043f\u043e\u0442\u043e\u043c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e:<\/p>\n<ul>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 test-id \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a UI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u0434\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430 \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u044d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u0432 Page Object \u0438\u043b\u0438 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432 <strong>test.step <\/strong>(<a href=\"https:\/\/playwright.dev\/docs\/api\/class-test#test-step\" rel=\"noopener noreferrer nofollow\">test.step<\/a>) \u2192 \u0447\u0442\u043e\u0431\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u043b\u0435\u0433\u0447\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0437\u00a0\u0447\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0442\u0435\u0441\u0442 \u0432 \u043a\u043e\u0434\u0435 \u0438 \u0432 \u0440\u0435\u043f\u043e\u0440\u0442\u0435, \u0430 \u043d\u0435 \u043f\u043e\u043b\u043e\u0442\u043d\u043e. <\/p>\n<\/li>\n<li>\n<p>\u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 Page Object, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438\u043b\u0438 \u0432 Component Object, \u0435\u0441\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043e\u0431\u0449\u0438\u0435 \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446.<\/p>\n<\/li>\n<\/ul>\n<\/blockquote>\n<p><u>\u2b07\ufe0f <\/u><strong><em><u>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 e2e (test.info):<\/u><\/em><\/strong><\/p>\n<p>\u0417\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0438\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u0442\u0435\u0441\u0442\u0435 \u0435\u0441\u0442\u044c \u0448\u0430\u0433 \u043a\u0430\u043a \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043b\u0438\u0431\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u0430\u043b\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0435\u0441\u0442.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0438\u0445 \u0432 \u043e\u0442\u0447\u0451\u0442\u0435. <\/p>\n<p>\u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <strong><em><u>\u0435\u0441\u043b\u0438 \u0442\u0435\u0441\u0442 \u043f\u0430\u0434\u0430\u0435\u0442<\/u><\/em><\/strong> \u0438\u0437-\u0437\u0430 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u043e \u0432 \u043e\u0442\u0447\u0451\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e<strong> \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u044b\u043b\u0438 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b<\/strong> \u0438\u043b\u0438 <strong>\u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/strong> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p> \u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u043e\u0442\u0447\u0451\u0442\u0430 \u043f\u043e \u0442\u0435\u0441\u0442\u0443 \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0435\u0431\u0430\u0433\u0430).<\/p>\n<\/li>\n<li>\n<p>\u0438\u043b\u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0439\u0442\u0438 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u043c\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u043f\u0446\u0438\u044f<code> test.info<\/code>!<\/p>\n<p>\u00a0<a href=\"http:\/\/test.info\" rel=\"noopener noreferrer nofollow\"><code>test.info<\/code><\/a> \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p> \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f REST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f query-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438):<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code> const response = await request.get('url + query parameters');    \/\/ \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u043e\u0442\u0447\u0451\u0442    await test.info().attach('API request', {        body: JSON.stringify(response, null, 2),    });<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p> \u0430 \u0442\u0430\u043a\u0436\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f e2e \u0442\u0435\u0441\u0442\u0430 \u2192 \u0442\u043e \u0435\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u044b \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432:<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>   test.beforeEach(async ({ page, request }) =&gt; {    createdProducts = await createManyProductsByCategory(      request,      CATEGORIE_NAMES.animalCare,      LIMIT    );    \/\/ \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u043e\u0442\u0447\u0451\u0442    await test.info().attach('Created products', {        body: JSON.stringify(createdProducts, null, 2),        contentType: 'application\/json',    });  });<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432:<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>  \/\/ \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442  const screenshot = await page.screenshot();  \/\/ \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0432 \u043e\u0442\u0447\u0435\u0442    await test.info().attach(        'screenshots',       { body: screenshot, contentType: 'image\/png' }  );<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043e\u0442\u0447\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/024\/e24\/453\/024e2445393b359a0b0f115928d8f0f4.png\" width=\"1738\" height=\"1314\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/024\/e24\/453\/024e2445393b359a0b0f115928d8f0f4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/024\/e24\/453\/024e2445393b359a0b0f115928d8f0f4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<div class=\"floating-image\"><\/div>\n<\/div>\n<\/details>\n<p>\u0412 playwright html \u043e\u0442\u0447\u0435\u0442\u0435\u00a0\u2014 <a href=\"http:\/\/test.info\" rel=\"noopener noreferrer nofollow\">test.info<\/a> \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 Attachments: <\/p>\n<div class=\"floating-image\">\n<figure class=\"float \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c61\/a10\/562\/c61a10562deaa37fc6e9393406cb9886.png\" alt=\"test info \u0432 attachments \u0432 playwright html \u043e\u0442\u0447\u0435\u0442\u0435\" title=\"test info \u0432 attachments \u0432 playwright html \u043e\u0442\u0447\u0435\u0442\u0435\" width=\"502\" height=\"466\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c61\/a10\/562\/c61a10562deaa37fc6e9393406cb9886.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c61\/a10\/562\/c61a10562deaa37fc6e9393406cb9886.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>test info \u0432 attachments \u0432 playwright html \u043e\u0442\u0447\u0435\u0442\u0435<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435, &#8216;API request&#8217; \u0438 &#8216;API response&#8217; \u043b\u0435\u0436\u0430\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 Attachments. \u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/p>\n<\/div>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f test.info<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e Star Wars API.<\/p>\n<p>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u043e\u043c API request:<\/p>\n<figure class=\"bordered full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/72e\/d9a\/88d\/72ed9a88db11386e619736b0f5459006.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \" width=\"1942\" height=\"1364\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/72e\/d9a\/88d\/72ed9a88db11386e619736b0f5459006.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/72e\/d9a\/88d\/72ed9a88db11386e619736b0f5459006.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <\/figcaption><\/div>\n<\/figure>\n<div class=\"floating-image\">\n<p>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u043e\u043c API response:<\/p>\n<\/div>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/727\/308\/110\/727308110a61604945e095d96d1dd78d.png\" alt=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430\" title=\"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430\" width=\"1914\" height=\"1296\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/727\/308\/110\/727308110a61604945e095d96d1dd78d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/727\/308\/110\/727308110a61604945e095d96d1dd78d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><u>\u2b07\ufe0f <\/u><strong><u>\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442:<\/u><\/strong><\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0438 <code>test.describe, beforeEach, test with tag, test.step, afterEach<\/code> c \u0443\u0447\u0435\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <a href=\"https:\/\/habr.com\/ru\/articles\/942656\/\" rel=\"noopener noreferrer nofollow\">\u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c<\/a>. <\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440: <\/em><\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0435\u0441\u0442\u044c \u043a\u0435\u0439\u0441\u044b \u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0442\u043e\u0432\u0430\u0440\u043e\u0432: \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0446\u0435\u043d\u0435 (\u0443\u0431\u044b\u0432\u0430\u043d\u0438\u0435\/\u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u0435), \u0440\u0435\u0439\u0442\u0438\u043d\u0433, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0423 \u0432\u0441\u0435\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0432 beforeEach.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043b\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0441 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e <strong>\u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443<\/strong> \u0438 <strong>\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c<\/strong> \u0442\u043e\u0432\u0430\u0440\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440:<\/p>\n<ul>\n<li>\n<p>rating\u00a0\u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442 1\u00a0\u0434\u043e 10<\/p>\n<\/li>\n<li>\n<p>recommendedLevel\u00a0\u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0442 <strong>1\u00a0\u0434\u043e 10<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0442\u0441\u044e\u0434\u0430, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u0430\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 <strong>\u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c<\/strong> \u043d\u0443\u0436\u0435\u043d <strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 beforeEach<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u043e\u0432\u0430\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u043f\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u043b\u0438\u0447\u0438\u0435 <em>rating, recommendedLeve<\/em>l).<\/p>\n<p><em>\u0420\u0430\u0437\u0431\u043e\u0440 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0441\u0445\u043e\u0436\u0438\u0435 \u043f\u043e \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0435 \u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/em><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 <\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e \u0446\u0435\u043d\u0435 \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 5 <\/p>\n<pre><code>\/\/SortProductsList.spec.ts - \u0444\u0430\u0439\u043b \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443import {     CATEGORIE_NAMES,    AUTH_ROLE_STATES} from 'playwrightTests\/common\/constants\/..'import  { PRODUCT_PRICE } from '..test-ids.ts' import  {      createManyProductsByCategory,      deleteProductById } from 'playwrightTests\/common\/helpers\/..' import .. from 'playwrightTests\/common\/pages\/..'import ..from  'playwrightTests\/common\/steps\/..' let productPage\/\/ \u0432\u044b\u043d\u043e\u0448\u0443 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0438 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \/\/ \u043f\u043e \u0446\u0435\u043d\u0435 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443 \/\/ \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u0442\u0435\u0433 \u043a\u0430\u043a sortProductstest.describe({tag:'@sortProducts'}, async() =&gt; {   let createdProducts: {}\u00a0   const LIMIT = 5    \/\/ storageState \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 (\u043a\u0430\u0441\u0442\u043e\u043c\u0435\u0440 1)   test.use({ storageState: AUTH_ROLE_STATES.customer.first });   \/\/ \u0412 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u0441\u044f 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430   test.beforeEach(async ({ page, request }) =&gt; {        productsPage = new ProductListPage(page);        createdProducts = await createManyProductsByCategory(          request,          CATEGORIE_NAMES.electronics,          LIMIT       );       await test.step('\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0438', async () =&gt; {         await page.goto(`\/products?category=${CATEGORIE_NAMES.electronics}`);       });       ......  });  \/\/ \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0446\u0435\u043d \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0442\u043e\u0432\u0430\u0440\u0443 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435  async function getProductPrices(page) {     const priceTexts = await page.getByTestId(PRODUCT_PRICE).allTextContents();         return getClearPrices(priceTexts);  }  test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0446\u0435\u043d\u0435', async ({ page }) =&gt; {      await test.step('\u041e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0446\u0435\u043d\u044b', async () =&gt; {          await products.sortByPriceDesc();      });      await test.step('\u0422\u043e\u0432\u0430\u0440\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e \u0446\u0435\u043d', async () =&gt;  {         const prices = await getProductPrices(page)           await products.toBeSortedInDescendingOrder(prices);      });  })  test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0435\u0439 \u0446\u0435\u043d\u0435', async ({ page }) =&gt; {      const products = new ProductListPage(page);               await test.step('\u041e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0446\u0435\u043d\u0435 \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e', async () =&gt; {          await products.sortByPriceAsc();      });             await test.step('\u0422\u043e\u0432\u0430\u0440\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e \u0446\u0435\u043d', async () =&gt; {          const prices = await getProductPrices(page)            await products.toBeSortedInAscendigOrder(prices);      });  });  \/\/\u041f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0435  \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0442\u043e\u0432\u0430\u0440\u044b  test.afterEach(async ({ request }) =&gt; {\u00a0\u00a0   for (const product of createdProducts) {\u00a0\u00a0\u00a0    \u00a0await deleteProductById(request, product.id);\u00a0\u00a0    }   });})------------------------\/\/\u0437\u0434\u0435\u0441\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u0432\u0442\u043e\u0440\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c (<em>rating, recommendedLeve) <\/em>\u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0442\u043e\u0432\u0430\u0440\u044b \u0434\u043b\u044f \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445, \u0433\u0434\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u043e\u0432\u0430\u0440\u043e\u0432 20.<\/p>\n<pre><code>\/\/ \u0432\u044b\u043d\u043e\u0448\u0443 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0438 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \/\/ \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443 \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c \/\/ \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u0442\u0435\u0433 \u043a\u0430\u043a sortProductstest.describe('\u0432\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430', {tag:'@sortProducts'}, async() =&gt; {   let createdProducts: {}\u00a0   const LIMIT = 20    \/\/ storageState \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 (\u043a\u0430\u0441\u0442\u043e\u043c\u0435\u0440 2)   test.use({ storageState: AUTH_ROLE_STATES.customer.second });   \/\/ \u0412 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u0441\u044f 20 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0442\u043e\u0432\u0430\u0440\u044b \u0434\u043b\u044f \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445   test.beforeEach(async ({ page, request }) =&gt; {        productsPage = new ProductListPage(page);        createdProducts = await createManyProductsByCategory(          request,          CATEGORIE_NAMES.animalCare,          LIMIT,          getRandom(MIN_RATING, MAX_RATING), \/\/ \u0440\u0435\u0439\u0442\u0438\u043d\u0433          getRandom(MIN_LEVEL, MAX_LEVEL), \/\/ \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438       );       await test.step('\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0442\u043e\u0432\u0430\u0440\u044b \u0434\u043b\u044f \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445', async () =&gt; {           await page.goto(`\/products?category=${CATEGORIE_NAMES.animalCare}`);       });       ......   });   test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443', async ({ page }) =&gt; {       await test.step('\u041e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0446\u0435\u043d\u0435 \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443', async () =&gt; {          await products.sortByRating();       });         await test.step('\u0422\u043e\u0432\u0430\u0440\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0440\u0435\u0439\u0442\u0438\u043d\u0433\u0443', async () =&gt;  {           .....                await products.toBeSortedInRatingOrder(createdProducts);      });  })  test('\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e \u0446\u0435\u043d\u0435', async ({ page, request }) =&gt; {      const products = new ProductListPage(page);               await test.step('\u041e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c', async () =&gt; {         await products.sortByRecomended();      });        await test.step('\u0422\u043e\u0432\u0430\u0440\u044b \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u043c', async () =&gt;  {        ....              await products.toBeSortedInRecomendedOrder(createdProducts);    });   });  \/\/\u041f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u0435  \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0442\u043e\u0432\u0430\u0440\u044b  test.afterEach(async ({ request }) =&gt; {\u00a0\u00a0   for (const product of createdProducts) {\u00a0\u00a0\u00a0    \u00a0await deleteProductById(request, product.id);\u00a0\u00a0    }   });})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0418\u0442\u043e\u0433 \u043f\u0440\u0438\u043c\u0435\u0440\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0442\u0435\u0441\u0442\u044b \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u0423 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0441\u0432\u043e\u0439 beforeEach\/afterEach (\u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f\/\u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f)<\/p>\n<\/li>\n<li>\n<p>\u0442\u0435\u0441\u0442\u044b \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0448\u0430\u0433\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>test.step<\/code><\/p>\n<\/li>\n<li>\n<p> \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 <code>playwrightTest\/common\/constants\/{some-constant.ts}<\/code>. <\/p>\n<\/li>\n<li>\n<p>API-\u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u0451\u0440\u043d\u0443\u0442\u044b \u0432\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, deleteProductById, createManyProductsByCategory) \u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 <code>playwrightTest\/common\/helpers\/{some-helper.ts}<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <strong>test-id <\/strong>(data-test-id\/data-testId) \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>...\/test-ids<\/code> (\u0432\u043d\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b <code>playwrightTests<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u043c\u0435\u0442\u043e\u0434\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439\u00a0\u2014 \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a sortByPriceAsc, toBeSortedInDescendingOrder, sortByPriceDesc \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0432 PageObject <code>ProductListPage<\/code><\/p>\n<\/li>\n<\/ul>\n<p><u>\u2b07\ufe0f <\/u><strong><u>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432 e2e:<\/u><\/strong><\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442 \u0441 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u00ab\u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0441\u00a0\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c\u00bb. \u0422\u0430\u043a\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c (\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0439 \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445) \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 <code>playwrightTests\/snapshots<\/code>. <\/p>\n<blockquote>\n<p>\u041b\u0435\u0433\u043a\u043e \u0436\u0435! \u2014 \u0441\u043a\u0430\u0436\u0435\u0442\u0435 \u0432\u044b. \u0418 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0437\u0438.<\/p>\n<\/blockquote>\n<p>\ud83d\udccc <em>\u041e \u0442\u043e\u043c, \u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 <\/em><a href=\"https:\/\/habr.com\/ru\/articles\/942656\/#:~:text=%F0%9F%93%8C%20Screenshots%20(snapshots)\" rel=\"noopener noreferrer nofollow\">\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c: Screenshots (snapshots)<\/a> <\/p>\n<p>\u26a0\ufe0f \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>npx playwright test --update-snapshots<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p> \u0410 \u0435\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u0441 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c\u0438 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u044b \u0442\u0435\u0433\u0430\u043c\u0438, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u043e\u0440\u043e\u0447\u043d\u043e, \u0443\u043a\u0430\u0437\u0430\u0432 \u0442\u0435\u0433 (<a class=\"mention\" href=\"\/users\/screenshots\">@screenshots<\/a>\u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043c\u044f \u0442\u0435\u0433\u0430):<\/p>\n<pre><code>npx playwright test --update-snapshots --grep @screenshots <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u26a0\ufe0f \u0414\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f: <a href=\"https:\/\/playwright.dev\/docs\/api\/class-pageassertions#page-assertions-to-have-screenshot-1\" rel=\"noopener noreferrer nofollow\">toHaveScreenshot(name)<\/a><\/p>\n<p>\u0412 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438 <a href=\"https:\/\/playwright.dev\/docs\/test-snapshots#options\" rel=\"noopener noreferrer nofollow\">\u043e\u043f\u0446\u0438\u0438<\/a> <\/p>\n<p>\u0421\u0430\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u044d\u0442\u043e <code>maxDiffPixels<\/code> \u0438 <code>maxDiffPixelRatio<\/code> , \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430\u0434\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u043c.<\/p>\n<pre><code>maxDiffPixelRatio = (\u0447\u0438\u0441\u043b\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439) \/ (\u043e\u0431\u0449\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c <code>maxDiffPixelRatio: 0.02<\/code>, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0434\u043e 2% \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0439. \u0414\u043b\u044f \u0441\u043d\u0438\u043c\u043a\u0430 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1 000 000 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 2% \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 20 000 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u043c \u2264 20 000 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e<\/p>\n<p>\u26a0\ufe0f \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445 \u043f\u0440\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438:<\/p>\n<p>1) \u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 playwright.config.ts &#8212; \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a:<\/p>\n<pre><code> expect: {    toHaveScreenshot: {      maxDiffPixels: 50,       \/\/ \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439      maxDiffPixelRatio: 0.01, \/\/ \u0438\u043b\u0438 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435    }, }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>2) \u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043d\u0438\u043c\u043a\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 <code>playwrightTests\/common\/base\/Base.ts<\/code><\/p>\n<pre><code>\/** * \u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 * * @param target \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0438\u043b\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 (\u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0441\u043a\u0440\u0438\u043d\u0438\u0442\u044c) * @param name \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 (\u0435\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e, Playwright \u0441\u0430\u043c \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442) * @param increasedDiff  \u043c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0433\u043e \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e 1) * @param options \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438 Playwright expect (threshold, animations) *\/async areScreenshotsMatch(  target: Locator | Page,  name?: string,  increasedDiff = 1,  options: Record&lt;string, unknown&gt; = {}) {  const diffPixelsRatio = 0.1 * increasedDiff; \/\/\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445  const diffPixels = 100 * increasedDiff; \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0441\u043e\u0444\u0442 \u0430\u0441\u0441\u0435\u0440\u0442 - \u0447\u0442\u043e\u0431\u044b \u0442\u0435\u0441\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f\/\/\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u0448\u0430\u0433 \u0437\u0430\u0444\u0435\u0439\u043b\u0438\u0442\u0441\u044f  await expect.soft(target).toHaveScreenshot(name ?? '', {    maxDiffPixelRatio: diffPixelsRatio,    maxDiffPixels: diffPixels,    ...options,  });}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u2757\u041a\u0441\u0442\u0430\u0442\u0438 \u0435\u0441\u0442\u044c \u043d\u044c\u044e\u0430\u043d\u0441:<\/strong><\/p>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e <code>maxDiffPixels: 200<\/code> \u0438 <code>maxDiffPixelRatio: 0.2<\/code>, \u0442\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u043e \u0441\u0432\u044f\u0437\u043a\u0435 <strong>\u0418<\/strong>. <\/p>\n<p>\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 200 <strong><u>\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e<\/u><\/strong> \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 20% \u043e\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u043e \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442\u0441\u044f \u2192 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0443\u043f\u0430\u0434\u0451\u0442.<\/p>\n<\/blockquote>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 200 \u00d7 200 = 40 000 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, maxDiffPixelRatio: 0.2, maxDiffPixels: 100. <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u043e \u0441\u0432\u044f\u0437\u043a\u0435 <strong>\u0418<\/strong>, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u2264 maxDiffPixels (\u2264 100). \u0420\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0440\u043e\u0433 = 100 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439<\/p>\n<pre><code>await expect.soft(target).toHaveScreenshot(name ?? '', {  maxDiffPixelRatio: 0.2, \/\/ \u0434\u043e 20% \u043e\u0442\u043b\u0438\u0447\u0438\u0439  maxDiffPixels: 100,     \/\/ \u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043d\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 100 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439  ...options,});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u0441\u0442\u044b \u0441 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439:<\/p>\n<p><em>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0441\u0430\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f:<\/em><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440_1:<\/p>\n<p> \u041d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043a\u043e\u043d\u043e\u043a \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435, \u0433\u0434\u0435 \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0442\u043e\u0432\u0430\u0440\u0430\u0445 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u044b.<\/p>\n<p>\u041f\u0443\u0442\u044c \u043a \u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0443\u00a0<code>.\/tests\/e2e\/Basket.spec.ts<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0441\u0442\u0430 \u0441 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { test } from '@playwright\/test';import { areScreenshotsMatch } from '..\/common\/base\/Base';import { BASKET_CONTENT } from '..\/common\/test-ids';import { BasketPreviewComponent } from '..\/common\/components\/BasketPreviewComponent';import { getInfoProductsInBasket } from '..\/common\/helpers\/basket-helpers';test('View products details and icons in basket', { tag: '@screenshots' }, async ({ page }) =&gt; {  const basketPreview = new BasketPreviewComponent(page);  await test.step('\u041c\u043e\u043a\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \/getInfoProductsInBasket', async () =&gt; {    await getInfoProductsInBasket(page); \/\/ \u043c\u043e\u043a \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0432 helper  });  await test.step('\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u0440\u0437\u0438\u043d\u0443', async () =&gt; {    await basketPreview.openBasket();  });  await test.step('\u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435', async () =&gt; {    await areScreenshotsMatch(page.getByTestId(BASKET_CONTENT), '');  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p> \u0418\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0431\u0443\u0434\u0435\u0442: <code>View-products-details-and-icons-in-basket-1.png<\/code><\/p>\n<p>\u0421\u0430\u043c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 <code>\/screenshots\/desktop-chrome\/e2e\/Basket.spec.ts\/View-products-details-and-icons-in-basket-1.png<\/code><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440_2:<\/p>\n<p> \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u0435\u043d\u044e \u0441\u0430\u0439\u0442\u0430 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c, \u0433\u0434\u0435 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0438 \u043f\u043e\u0434\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>\u041f\u0443\u0442\u044c \u043a \u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0443\u00a0<code>.\/tests\/e2e\/Catalog.spec.ts<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0441\u0442\u0430 2 \u0441 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { test } from '@playwright\/test';import { areScreenshotsMatch } from '..\/common\/base\/Base';import { EXPANDED_CATALOG_CONTENT } from '..\/common\/test-ids';import { CatalogComponent } from '..\/common\/components\/CatalogComponent';test('Show catalog and expanded subcatalog', { tag: '@screenshots' }, async ({ page }) =&gt; {  const catalogContent = new CatalogComponent(page);  await test.step('\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433', async () =&gt; {    await catalogContent.openCatalog();  });  await test.step('\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u0440\u0430\u0437\u0434\u0435\u043b - \u0422\u043e\u0432\u0430\u0440\u044b \u0434\u043b\u044f \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445', async () =&gt; {    await catalogContent.openSubCatalog(CATEGORIES.animalCare);  });  await test.step('\u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430', async () =&gt; {    await areScreenshotsMatch(page.getByTestId(EXPANDED_CATALOG_CONTENT), '');  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0418\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0431\u0443\u0434\u0435\u0442: <code>Show-catalog-and-expanded-subcatalog-1.png<\/code><\/p>\n<p>\u0421\u0430\u043c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 <code>\/screenshots\/mobile-chrome\/e2e\/Catalog.spec.ts\/Show-catalog-and-expanded-subcatalog-1.png<\/code><\/p>\n<p><strong>\u2757\u0414\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c \u043f\u043e \u0442\u0435\u0433\u0443: <\/p>\n<\/li>\n<\/ul>\n<pre><code>npx playwright test Catalog.spec.ts --grep @screenshots<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0432 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c UI-\u0440\u0435\u0436\u0438\u043c\u0435 (\u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0441\u0440\u0430\u0437\u0443 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 <em>Attachments<\/em> , \u0435\u0441\u043b\u0438 \u0442\u0435\u0441\u0442 \u0443\u043f\u0430\u043b \u2014 <a href=\"https:\/\/playwright.dev\/docs\/trace-viewer-intro\" rel=\"noopener noreferrer nofollow\">Trace Viewer<\/a>):<\/p>\n<pre><code>npx playwright test --ui<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong><u>\u26a0\ufe0f \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435:<\/u><\/strong><\/p>\n<p><strong>E2E-\u0442\u0435\u0441\u0442\u044b<\/strong> \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445, \u0438\u043b\u0438 \u0432 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u0439 \u0438\u043b\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430.<\/p>\n<p>\u0412 <strong>Playwright<\/strong> \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0444\u0438\u0433 \u0432 <code>playwright.config.ts<\/code>.<\/p>\n<p>\u0411\u044b\u0432\u0430\u044e\u0442 \u0441\u043b\u0443\u0447\u0430\u0438 \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <strong>\u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b<\/strong> \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c Chrome, \u0438\u043b\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c\u0441\u044f <strong>\u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445<\/strong> (\u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445\/\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445).<\/p>\n<p><sub><u>\u041f\u0440\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u00a0\u2014 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b\u0430 \u0432\u00a0\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 (\u0438\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u00a0\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u00abConfig\u00bb).<\/u><\/sub><\/p>\n<blockquote>\n<p><strong>\u26a0\ufe0f \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435: <\/strong>\u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 (<code>.spec.ts<\/code>) \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0438\u0441\u044c <strong>\u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445<\/strong>, \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 <code>test-assets<\/code>.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p><code>Basket.spec.ts<\/code> \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043f\u043e \u043f\u0443\u0442\u0438:<br \/> <code>playwrightTests\/tests\/e2e\/Basket\/test-assets\/Basket.spec.ts<\/code><\/p>\n<\/li>\n<li>\n<p><code>ProductList.spec.ts<\/code> \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043f\u043e \u043f\u0443\u0442\u0438:<br \/> <code>playwrightTests\/tests\/e2e\/Basket\/test-assets\/ProductList.spec.ts<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044f\u0432\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0432 <code>playwright.config.ts<\/code>, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043d\u0443\u0436\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 \u0438\u043b\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043a\u0430\u043a <code>Basket.spec.ts <\/code>\u0438 <code>ProductList.spec.ts<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 ProductList.spec.ts<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>testIgnore: \/.*Smoke|api.spec.ts\/. \u2192 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043c\u043e\u0443\u043a \u0438 \u0430\u043f\u0438 \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>testMatch: \/.*ProductList.spec.ts\/ \u2192 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0432 3-\u0445 projects<\/p>\n<\/li>\n<li>\n<p> \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0438\u0442\u0440\u0430\u0435\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c project,<\/p>\n<\/li>\n<li>\n<p> devices \u0438 viewport \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e project \u2014 Desktop Chrome|Mobile Chrome(Pixel 7)| Mobile Safari (iPad Air)<\/p>\n<\/li>\n<\/ul>\n<pre><code>projects: {[  ...\/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 ProductList.spe.ts  {    name: 'desktop_chrome',    testIgnore: \/.*Smoke|api\\.spec\\.ts\/,    testMatch: \/.*ProductList\\.spec\\.ts\/,    use: {      ...devices['Desktop Chrome'],      viewport: { width: 1280, height: 720 },    },    testDir: '.\/tests',    fullyParallel: false,    dependencies: ['setup auth'], \/\/ \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 setup auth    retries: 1,  },---------  {    name: 'mobile_chrome',    testIgnore: \/.*Smoke|api\\.spec\\.ts\/,    testMatch: \/.*ProductList\\.spec\\.ts\/,    use: {      ...devices['Pixel 7'], \/\/ \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 mobile-\u043f\u0440\u043e\u0444\u0438\u043b\u044c      isMobile: true,      viewport: { width: 400, height: 700 }    },    testDir: '.\/tests',    fullyParallel: true,    retries: 2,  },--------  {    name: 'mobile_safari',    testIgnore: \/.*Smoke|api\\.spec\\.ts\/,     testMatch: \/.*ProductList\\.spec\\.ts\/,    use: {      ...devices['iPad Air'],      isMobile: true,      viewport: { width: 820, height: 1180  },    },    testDir: '.\/tests',    fullyParallel: true,    retries: 1,  },  ...\/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Basket.spe.ts]}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>Basket.spec.ts \u0433\u043e\u043d\u044f\u0435\u043c \u043d\u0430:<\/p>\n<ul>\n<li>\n<p><code>devices['Desktop Chrome']<\/code> c <code>viewport: { width: 1280, height: 720 }<\/code><\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p><code>devices['Pixel 7'] , viewport: { width: 412, height: 915 }<\/code><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Basket.spec.ts<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>testIgnore: \/.*Smoke|api.spec.ts\/. \u2192 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043c\u043e\u0443\u043a \u0438 \u0430\u043f\u0438 \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>testMatch: \/.*Basket.spec.ts\/ \u2192 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0432 3-\u0445 projects<\/p>\n<\/li>\n<li>\n<p> \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0438\u0442\u0440\u0430\u0435\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c \u0432 \u043a\u0430\u0436\u0434\u043e\u043c project,<\/p>\n<\/li>\n<li>\n<p> devices \u0438 viewport \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e project \u2014 Desktop Chrome|Mobile Chrome(Pixel 7)<\/p>\n<\/li>\n<\/ul>\n<pre><code>projects: {[  ...\/\/ \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 Basket.spe.ts  {    name: 'desktop_chrome',    testIgnore: \/.*Smoke|api\\.spec\\.ts\/,    testMatch: \/.*Basket\\.spec\\.ts\/,    use: {      ...devices['Desktop Chrome'],      viewport: { width: 1280, height: 720 },    },    testDir: '.\/tests',    fullyParallel: true,    dependencies: ['setup auth'], \/\/ \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 setup auth    retries: 1,  },---------  {    name: 'mobile_chrome',    testIgnore: \/.*Smoke|api\\.spec\\.ts\/,    testMatch: \/.*Basket\\.spec\\.ts\/,    use: {      ...devices['Pixel 7'], \/\/ \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 mobile-\u043f\u0440\u043e\u0444\u0438\u043b\u044c      isMobile: true,      viewport: { width: 400, height: 700 }    },    testDir: '.\/tests',    fullyParallel: false,    retries: 1,  },  ...]}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u0448\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 \u0438 \u0440\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b\u0445 viewport, \u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0435\u0449\u0435 \u043a\u0443\u0447\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043d\u0430 <\/p>\n<ul>\n<li>\n<p>Desktop Chrome| Desktop  Safari| Mobile Chrome| Mobile Safari <\/p>\n<\/li>\n<li>\n<p>\u0433\u0434\u0435 viewport: { width: 412, height: 915 } <\/p>\n<\/li>\n<li>\n<p>\u0438\u043b\u0438 viewport: { width: 1280, height: 720 }<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b, \u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0435 \u0447\u0442\u043e \u043b\u0435\u0436\u0430\u0442 \u0432 <strong>test-assets <\/strong>\u043f\u0430\u043f\u043a\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0438 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0431\u0430\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432:<\/p>\n<pre><code>{  name: 'mobile_chrome',  \/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0438\u0437 test-assets (\u043e\u043d\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445)  testIgnore: ['**\/test-assets\/**'],  testDir: '.\/tests',  fullyParallel: true,  use: {    ...devices['Mobile Chrome'],    isMobile: true,    viewport: { width: 360, height: 780 },  },},{  name: 'mobile_safari',  testIgnore: ['**\/test-assets\/**'],  testDir: '.\/tests',  fullyParallel: true,  use: {    ...devices['iPhone 13'],    isMobile: true,    viewport: { width: 393, height: 852 },  },},<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0431\u0430\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432:<\/p>\n<pre><code>{  name: 'desktop_chrome',  \/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0438\u0437 test-assets (\u043e\u043d\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445)  testIgnore: ['**\/test-assets\/**'],  testDir: '.\/tests',  fullyParallel: true,  use: {    ...devices['Desktop Chrome'],      viewport: { width: 1280, height: 720 },  },  retries: 1,},{  name: 'desktop_safari',  testIgnore: ['**\/test-assets\/**'],  testDir: '.\/tests',  fullyParallel: true,  use: {    ...devices['Desktop Safari'],      viewport: { width: 1280, height: 720 },  },   retries: 1,},<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong><u>\u26a0\ufe0f \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (\u0422\u0430\u0439\u043c\u0430\u0443\u0442\u044b) \u0432 e2e:<\/u><\/strong><\/p>\n<p>\u0412\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<blockquote>\n<p>\u0416\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e <strong><em>\u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <\/em><\/strong>\u0442\u0430\u0439\u043c\u0430\u0443\u0442\u044b \u043a\u0430\u043a <code>waitForTimeout()<\/code>. \u0414\u0430\u0436\u0435 \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043e \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0434\u0435\u0431\u0430\u0433\u0438\u043d\u0433\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u043d\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. <code>waitForTimeout(5000) <\/code>\u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u043d\u0430 5 \u0441\u0435\u043a.<\/p>\n<\/blockquote>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435:<\/p>\n<ul>\n<li>\n<p> \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f\/\u0438\u0441\u0447\u0435\u0437\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430<code> await expect(locator).toBeVisible({ timeout:  milliseconds });<\/code><\/p>\n<p><code>|| await expect(locator).toBeHidden({ timeout:  milliseconds })<\/code><\/p>\n<\/li>\n<li>\n<p> \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b) <code>await page.waitForLoadState('networkidle');<\/code><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<p>3) API-\u0442\u0435\u0441\u0442\u044b\u00a0\u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b <strong>\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432<\/strong> \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u041e\u043d\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b (\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d).<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 HTTP-\u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 (200, 201, 400, 401, 404 \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 (\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON\/XML, \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u043e\u043b\u044f).<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d, \u0442\u043e\u043a\u0435\u043d \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435).<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0430, \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0430\u043f\u0438 \u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p><strong>API-\u0445\u0435\u043b\u043f\u0435\u0440<\/strong>\u00a0\u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0445\u0435\u043b\u043f\u0435\u0440 \u0434\u043b\u044f\u00a0\u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0432\u0441\u0435\u0445 API\u2011\u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p><strong>Steps <\/strong>\u2014 \u0448\u0430\u0433\u0438 \u0434\u043b\u044f\u00a0\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f API\u2011\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043d\u0430\u00a0\u043e\u0441\u043d\u043e\u0432\u0435 \u0445\u0435\u043b\u043f\u0435\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p><strong>Schemas<\/strong>\u00a0\u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u043b\u044f\u00a0\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043e\u0442\u0432\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>apiRoutes<\/strong>\u00a0\u2014 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<\/blockquote>\n<p><strong><em><u>\u26a0\ufe0f \u0421\u0445\u0435\u043c\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 (Schemas) \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445:<\/u><\/em><\/strong><\/p>\n<p> <strong>C\u0445\u0435\u043c\u0430<\/strong>\u00a0\u2014 \u044d\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430\u00a0API \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<p>\u0421\u0445\u0435\u043c\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f <strong>\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u0432<\/strong>, \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e\u00a0API \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u00a0\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. <\/p>\n<p>\u0412\u0441\u0435 \u0441\u0445\u0435\u043c\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u043b\u0435\u0439 \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0421\u0445\u0435\u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 <code>schemas<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>common<\/code>. \u0422\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 \u0441\u0445\u0435\u043c\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 <code>\/common\/schemas\/{feature}-schemas.ts<\/code>.<\/p>\n<blockquote>\n<p>\u041b\u0443\u0447\u0448\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0445\u0435\u043c\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443  <code>\/common\/schemas\/<\/code>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0421\u0445\u0435\u043c\u044b \u0432\u043e \u043c\u043d\u043e\u0433\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b, \u043d\u043e \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 API-\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0447\u0438\u0441\u043b\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 API-\u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u0445\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0430\u00a0\u0441\u0445\u0435\u043c\u044b\u00a0\u2014 \u0434\u043b\u044f\u00a0\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432.<\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>\/common\/schemas<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0441\u0442\u0443\u044e \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0441\u0445\u0435\u043c\u0430\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<blockquote>\n<p> \u0421\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e\u0434 \u0442\u0430\u0439\u0442\u043b\u043e\u043c \u00bb<strong><u>\u0421\u0445\u0435\u043c\u044b API\u2011\u043e\u0442\u0432\u0435\u0442\u043e\u0432<\/u><\/strong><u>\u00bb<\/u><a href=\"https:\/\/habr.com\/ru\/articles\/942656\/\" rel=\"noopener noreferrer nofollow\"> \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<p><strong><em><u>\u26a0\ufe0f apiRoutes (\u0415\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b):<\/u><\/em><\/strong><\/p>\n<p>\u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 <code>\/common\/apiRoutes\/{feature}-routes.ts<\/code><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0432 <code>\/common\/apiRoutes\/authorization-routes.ts<\/code>:<\/p>\n<pre><code>\/\/ \u0412\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438export const AUTH_ROUTES = {  POST_LOGIN: '\/api\/v1\/auth\/login',  .....};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043b\u044e\u0441 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0443\u0442\u0438 API-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e, \u0438 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u043f\u0440\u0430\u0432\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<\/p>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432 API-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043d\u044b\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 <code>apiRoutes<\/code>.<\/p>\n<pre><code>import { doPostRequest } from '\/common\/helpers\/api-base-helper';import { POST_LOGIN } from '\/common\/apiRoutes\/authorization-routes.ts'test('\u041f\u0440\u0438\u043c\u0435\u0440', async ({ request }) =&gt; {  const response = await doPostRequest(     request,     POST_LOGIN,     .....   );<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u0445 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<blockquote>\n<p>\u0421\u043c\u043e\u0442\u0440\u0435\u0442\u044c  \u043f\u043e\u0434 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c \u00abApiRoutes\u00bb <a href=\"https:\/\/habr.com\/ru\/articles\/942656\/\" rel=\"noopener noreferrer nofollow\"> \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/blockquote>\n<p><strong><em><u>\u26a0\ufe0f API-\u0445\u0435\u043b\u043f\u0435\u0440<\/u><\/em><\/strong><em><u>:<\/u><\/em><\/p>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u0440\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 (\u0441\u043c. \u00ab\u26a0\ufe0f \u0425\u0435\u043b\u043f\u0435\u0440\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f API-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\u00bb), \u044f \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u0445\u0435\u043b\u043f\u0435\u0440\u0430, \u0433\u0434\u0435 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 JSON-\u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0438 \u0432 \u0442\u0435\u043a\u0441\u0442\u0432\u043e\u043c \u0432\u0438\u0434\u0435 \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 200.<\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u044d\u0442\u043e\u0433\u043e, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <strong>\u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0445\u0435\u043b\u043f\u0435\u0440<\/strong> <code>doRequest<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b<strong> \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/strong> (<code>doGetRequest<\/code>, <code>doPostRequest<\/code>, <code>doPutRequest<\/code>, <code>doPatchRequest<\/code>, <code>doDeleteRequest<\/code>), \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c HTTP-\u043c\u0435\u0442\u043e\u0434\u043e\u043c<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f HTTP-\u043c\u0435\u0442\u043e\u0434\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f doGETRequest(&#8230;)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { POST_LOGIN } from 'playwrightTests\/common\/apiRoutes\/..'import {    SUCCESS_LOGIN_SCHEMA } from 'playwrightTests\/common\/schemas\/auth-schemas.ts'test('\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 doPostRequest', async ({ request }) =&gt; {  const response = await doPostRequest(     request,     POST_LOGIN,     {       'email': 'emailTest@testUser.com',       'password': 'Password123!',     }   );      expect(response.status).toBe(200)    expect(response.body.settings).toBeTruthy()    expect(response.body).toMatchObject(SUCCESS_LOGIN_SCHEMA);})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043a\u0435\u0439\u0441, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 \u0440\u0430\u0432\u0435\u043d <code>200<\/code>, \u0430 JSON-\u043e\u0442\u0432\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0445\u0435\u043c\u0435 SUCCESS_LOGIN_SCHEMA.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u043d\u0451\u043c \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438 \u043d\u0435 \u043e\u0445\u0432\u0430\u0447\u0435\u043d\u044b \u0432\u0441\u0435 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 <code>doGetRequest<\/code> \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0432\u044b\u0437\u043e\u0432 <code>doGetRequest<\/code> \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a\u0430\u043a:<\/p>\n<pre><code>  expect(response.status).toBe(200)  expect(jsonBody.settings).toBeTruthy()  expect(jsonBody).toMatchObject(SUCCESS_LOGIN_SCHEMA);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong><u>\u26a0\ufe0f<\/u><em><u> Step pattern \u0434\u043b\u044f API-\u0442\u0435\u0441\u0442\u043e\u0432:<\/u><\/em><\/strong><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043e\u0434\u0430 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445, \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>step-\u043f\u0430\u0442\u0442\u0435\u0440\u043d<\/strong>.<\/p>\n<blockquote>\n<p>\u041f\u0440\u0438\u0447\u0438\u043d\u0430, \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0442\u0435\u043f\u044b \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 API-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445. <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b<strong> \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c <\/strong>\u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0442\u0435\u0441\u0442\u0435, \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <strong>\u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0435\u0437 \u0434\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 JSON \u0438 \u0431\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430. <\/strong><\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0431\u0443\u0434\u0443\u0442 \u043a\u0435\u0439\u0441\u044b \u043d\u0430 \u0430\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0447\u0435\u0440\u0435\u0437 API.<\/p>\n<p>\u041f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b:<\/p>\n<p>      1-\u043a\u0435\u0439\u0441: \u0443\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c\u0438 e-mail \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u043c<\/p>\n<p>\u041d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b:<\/p>\n<p>     2-\u043a\u0435\u0439\u0441: \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u043d\u0435\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c<\/p>\n<p>     3-\u043a\u0435\u0439\u0441: \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (e-mail \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c)<\/p>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u043d\u0443\u0436\u043d\u044b API-\u0442\u0435\u0441\u0442\u044b, \u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u0435\u0439\u0441 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443 \u0436\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443, \u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 1:<\/p>\n<p>\u0414\u043b\u044f \u043a\u0435\u0439\u0441\u043e\u0432 1 (\u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u043e\u0433\u043e), \u0430 \u0442\u0430\u043a\u0436\u0435 2 \u0438 3 (\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445) \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/login<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b <code>userLogin<\/code> \u0438 <code>password<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 query. <\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 <code>doPostRequest<\/code> \u043e\u0431\u0435\u0440\u043d\u0443 \u0432 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>sendLogin<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f e-mail \u0438 \u043f\u0430\u0440\u043e\u043b\u044f, \u0431\u0435\u0437 \u0441\u0442\u0440\u043e\u0433\u043e\u0439 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438, \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0435\u043f\u0430 sendLogin(..) \u0432 \/common\/steps\/api\/auth-step.ts<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/common\/steps\/api\/auth-step.tsimport { POST_LOGIN } from 'playwrightTests\/common\/apiRoutes\/...'\/*** \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e*\/export async function sendLogin(  request: APIRequestContext,  email: string,  password: string) {   return await doPostRequest(     request,     POST_LOGIN,     {       'email': email,       'password': password,     }   );}\/*** \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430*\/export function verifyResponseCode(  response: any,  statusCode: number) {   expect(response.status).toBe(statusCode);}\/*** \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043e\u0442\u0432\u0435\u0442\u0430*\/export function verifyResponseStructure(  response: any,  structure: object) {   expect(response.body).toMatchObject(structure);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p> \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0442\u0435\u0441\u0442 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432 \u043d\u0451\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u044b <code>sendLogin, verifyResponseCode, verifyResponseStructure<\/code> , \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0442\u0435\u0441\u0442\u0435 (\u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430)<\/summary>\n<div class=\"spoiler__content\">\n<p>1-\u043a\u0435\u0439\u0441: \u0443\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c\u0438 e-mail \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u043c:<\/p>\n<pre><code>import { POST_LOGIN } from 'playwrightTests\/common\/apiRoutes\/..'import {    SUCCESS_LOGIN_SCHEMA } from 'playwrightTests\/common\/schemas\/auth-schemas.ts'import {    sendLogin,    verifyResponseCode,   verifyResponseStructure} from 'playwrightTests\/common\/steps\/api\/auth-step.ts'test('\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c\u0438 e-mail \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u043c', async ({ request }) =&gt; {  let response;  await test.step('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430', async () =&gt; {      response = await sendLogin(          request,          'emailTest@testUser.com',          'Password123!'      );  });  \/\/ \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u043e\u0442\u0447\u0451\u0442  await test.info().attach('API response', {      body: JSON.stringify(response, null, 2),      contentType: 'application\/json',  });  await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0434\u0430 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u0432\u0435\u0442\u0430', async () =&gt; {       verifyResponseCode(response, 200);       verifyResponseStructure(response, SUCCESS_LOGIN_SCHEMA)  });  await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432 settings \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043d\u0435 null', async () =&gt; {      expect(response.body.settings).toBeTruthy();  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043f\u043e\u00a0\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c \u0430\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u0438 c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 <code>sendLogin, verifyResponseCode, verifyResponseStructure<\/code>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0442\u0435\u0441\u0442\u0435 (\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>test('\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u0430\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441 \u043d\u0435\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c', async ({ request }) =&gt; {  let response;  const notExistingEmail = 'johnDoe12345@testUser.com';  await test.step('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430', async () =&gt; {      response = await sendLogin(          request,          notExistingEmail,          'Password123!'      );  });   \/\/ \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u043e\u0442\u0447\u0451\u0442  await test.info().attach('API response', {      body: JSON.stringify(response, null, 2),      contentType: 'application\/json',  });  await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0434\u0430 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u0432\u0435\u0442\u0430', async () =&gt; {       verifyResponseCode(response, 404);       verifyResponseStructure(         response,          returnUnknownUserSchema(ERROR_CODE, notExistingEmail)       );  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0435\u0439\u0441 -3: \u0430\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (e-mail \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c):<\/p>\n<pre><code>test('\u0410\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438', async ({ request }) =&gt; {  let response;  await test.step('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430', async () =&gt; {      response = await sendLogin(          request,          'emailTest@testUser.com',          'wrongPassword'      );  });   \/\/ \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 \u043e\u0442\u0447\u0451\u0442  await test.info().attach('API response', {      body: JSON.stringify(response, null, 2),      contentType: 'application\/json',  });   await test.step('\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0434\u0430 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u0432\u0435\u0442\u0430', async () =&gt; {       verifyResponseCode(response, 401);       verifyResponseStructure(         response,          INVALID_AUTH_SCHEMA       );  });});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p><strong><u>\u26a0\ufe0f \u0418\u0442\u043e\u0433: \u0447\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 API-\u0442\u0435\u0441\u0442\u0430:<\/u><\/strong><\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0445\u0435\u043b\u043f\u0435\u0440 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e API-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u0441\u0442\u0435\u043f-\u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u044b \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 \u0432 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0442\u0435\u043f\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0428\u0430\u0433\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 (\u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0438 \u0442.\u043f.) \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0435\u043f\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 apiRoutes \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0435\u043f\u0430\u0445 \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0441\u0445\u0435\u043c\u044b (\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b) \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 schemas \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0441\u0445\u0435\u043c\u0430\u0445 \u043d\u0435\u0442 \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0430, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0442\u0435\u0441\u0442\u0430\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432 \u043a\u0430\u043a \u0434\u043b\u044f \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0442\u0435\u0441\u0442\u0430\u0445, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"http:\/\/test.info\" rel=\"noopener noreferrer nofollow\">test.info<\/a> \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 <\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 \u0442\u0435\u0441\u0442\u044b \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043f\u0440\u0438\u0451\u043c\u044b \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0443\u043f\u043e\u0440 \u0441\u0434\u0435\u043b\u0430\u043d \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u043d\u0435\u0435 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438: <a href=\"https:\/\/habr.com\/ru\/articles\/942656\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c:  \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c<\/a><\/p>\n<p>\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043a \u0442\u0435\u043c\u0430\u043c, \u0443\u0436\u0435 \u0437\u0430\u0442\u0440\u043e\u043d\u0443\u0442\u044b\u043c \u0440\u0430\u043d\u0435\u0435, \u0438 \u043f\u0440\u0438\u0432\u0435\u043b\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c<\/strong>, \u0447\u0442\u043e \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u044b, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0437\u0434\u0435\u0441\u044c, \u043d\u0435 \u043f\u0440\u0435\u0442\u0435\u043d\u0434\u0443\u044e\u0442 \u043d\u0430 \u0440\u043e\u043b\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430. \u042d\u0442\u043e \u0441\u043a\u043e\u0440\u0435\u0435 \u043f\u043e\u0434\u0431\u043e\u0440\u043a\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0438\u0434\u0435\u0439, \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u044f \u043f\u0440\u0438\u0448\u043b\u0430 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/946902\/\">https:\/\/habr.com\/ru\/articles\/946902\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u0439\u043d\u0443\u0440\u0430.\u0418 \u0442\u0430\u043a\u0441, \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u044f \u0434\u043e\u0431\u0440\u0430\u043b\u0430\u0441\u044c \u0434\u043e \u0447\u0430\u0441\u0442\u0438, \u0433\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \ud83d\ude05.\u041d\u0435 \u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u0447\u0442\u043e \u0445\u0430\u043e\u0441 \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u0435\u043d, \u043e\u043d \u043e\u043f\u0430\u0441\u0435\u043d \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 (\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432), \u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435, \u044f \u043e\u0442\u043c\u0435\u0442\u0438\u043b\u0430 \u0447\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430, \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0443\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438\u00a0\u2014 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0445\u0430\u043e\u0441\u0430 \u0432\u00a0\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0438\u043b\u0438\u00a0\u043f\u0440\u0438\u00a0\u0435\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438, \u0441\u043c\u043e\u0447\u044c \u0435\u0433\u043e \u0440\u0430\u0437\u0433\u0440\u0435\u0441\u0442\u0438.\u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c \u0435\u0449\u0435 \u0440\u0430\u0437 \u0447\u0442\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0432\u0430\u0436\u0435\u043d\u00a0\u2014 \u043f\u0440\u043e\u0449\u0435 \u0432\u043e\u0432\u0440\u0435\u043c\u044f \u00ab\u043f\u0440\u0438\u0431\u0440\u0430\u0442\u044c\u0441\u044f\u00bb, \u0447\u0435\u043c \u043f\u043e\u0442\u043e\u043c \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u043b\u044c\u043d\u0443\u044e \u0443\u0431\u043e\u0440\u043a\u0443. \u041e\u0442\u043c\u0430\u0437\u043a\u0438 \u0432\u0440\u043e\u0434\u0435 \u00ab\u0434\u043e\u0434\u0435\u043b\u0430\u044e \u043f\u043e\u0442\u043e\u043c\u00bb, \u00ab\u043f\u043e\u0436\u0438\u0432\u0451\u043c\u00a0\u2014 \u0443\u0432\u0438\u0434\u0438\u043c\u00bb, \u00ab\u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435\u00bb\u00a0\u2014 \u043d\u0435\u00a0\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442!!!! (\u041d\u043e \u044d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043b\u0438\u0448\u044c \u043c\u043e\u0451 \u043c\u043d\u0435\u043d\u0438\u0435 \ud83d\ude42)\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0435\u043c\u044b:\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 .spec\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 .spec\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0445\u0443\u043a\u043e\u0432 beforeEach \/ afterEach \/ describe\u041e\u043f\u0446\u0438\u044f test.step\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0433\u043e\u0432 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044bSmoke tests\u0417\u0430\u043f\u0443\u0441\u043a smoke \u0442\u0435\u0441\u0442\u043e\u0432E2E (end-to-end) \u0442\u0435\u0441\u0442\u044bCodegen\u00a0\u2014 \u043a\u0430\u043a\u00a0\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u0430\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 e2e (test.info)\u0420\u0430\u0437\u0431\u043e\u0440 e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 e2e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (\u0442\u0430\u0439\u043c\u0430\u0443\u0442\u044b) \u0432 e2eAPI-\u0442\u0435\u0441\u0442\u044b\u0421\u0445\u0435\u043c\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 (Schemas)apiRoutes (\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b)API-\u0445\u0435\u043b\u043f\u0435\u0440Step pattern \u0434\u043b\u044f API-\u0442\u0435\u0441\u0442\u043e\u0432\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044e \u043f\u0440\u0430\u0432\u0438\u043b \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.\u2b50 \u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430:\u0434\u043e\u043b\u0436\u0435\u043d: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043e\u0434\u0438\u043d \u043a\u0435\u0439\u0441.\u041e\u0434\u0438\u043d \u0442\u0435\u0441\u0442 = \u043e\u0434\u0438\u043d \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u041d\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442. \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 PageObject (locators, components, helpers), constants, helpers, step pattern, snapshots, components. \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 constants, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 1\u00a0\u0440\u0430\u0437\u0430. \u0425\u0440\u0430\u043d\u0438\u0442\u0435 \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0436\u0435\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u00a0\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u0445 \u0430\u00a0\u043d\u0435\u00a0\u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0442\u0435\u0441\u0442.\u0438\u043c\u0435\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c, \u0447\u0442\u043e\u00a0\u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f.\u0431\u044b\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437\u00a0\u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u0427\u0435\u043c \u043f\u0440\u043e\u0449\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0442\u0435\u0441\u0442, \u0442\u0435\u043c \u043e\u043d \u043d\u0430\u0434\u0451\u0436\u043d\u0435\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435. \u0422\u043e \u0435\u0441\u0442\u044c, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u044b \u0447\u0451\u0442\u043a\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0438\u0445 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0430\u00a0\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430 \u0438\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u00ab\u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u0435\u043c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0430\u00bb. \u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0431\u043b\u043e\u043a\u0438 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0439\u0442\u0435 \u0432 test.step. \u044f\u0432\u043d\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u043b\u043e\u0433\u0438 \u0438\u043b\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: userId, orderId, experimentBucket, priceBefore\/priceAfter. \u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 test.step(&#8216;\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f&#8217;, \u2026) \u0441 \u0430\u0441\u0441\u0435\u0440\u0442\u0430\u043c\u0438 \u0432\u0438\u0434\u0430 expect(keyValue, { message: keyValue }).toBeTruthy(), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0435 \/ \u043d\u0435 null \/ \u043d\u0435 0, \u043b\u0438\u0431\u043e \u0447\u0435\u0440\u0435\u0437 testInfo.attach\u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d:\u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.\u0422\u0435\u0441\u0442 \u21162 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0448\u0451\u043b \u0442\u0435\u0441\u0442 \u21161. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0431\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0440\u0435\u0441\u0443\u0440\u0441.\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434.\u0415\u0441\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u043a\u043e\u0434 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445\u00a0\u2014 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0435 \u0435\u0433\u043e \u0432 common(support). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 helpers \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435, \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438 \u0442. \u0434.), \u0432 steps \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0448\u0430\u0433\u043e\u0432 \u0438\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0437 PageObject.\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0433\u0438, \u0433\u0434\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0438\u043b\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0415\u0441\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b (parametrize tests) \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430. Parametirize tests\u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u043e\u0432 (sleep, waitForTimeout), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044f\u0432\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f.\u0441\u043b\u0435\u0434\u0443\u0435\u0442: \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443.\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0442\u0435\u0433\u0438, \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430.\u2b50 \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432:\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043e\u0440\u043e\u0436\u0435, \u0447\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d \u0438\u043b\u0438 \u0434\u0435\u0448\u0435\u0432\u043b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u2192 \u0442\u0430\u043a\u0438\u0435 \u043a\u0435\u0439\u0441\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438.\u041e\u043d\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438.\u0417\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u0435 \u043a\u00a0\u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c.\u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0433\u0434\u0430 \u0447\u0442\u043e\u00a0\u2014 \u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435\u00a0\u0442\u0430\u043a!\u0415\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0435\u0439\u0441 \u043d\u0430\u00a0\u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u043d\u043e\u00a0\u0431\u044d\u043a\u0435\u043d\u0434 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d \u0438 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b, \u0432\u043b\u0438\u044f\u044e\u0449\u0438\u0435 \u043d\u0430\u00a0\u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0434\u043b\u044f\u00a0\u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f.\u041f\u0440\u0438\u00a0\u044d\u0442\u043e\u043c, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 API\u2011\u0442\u0435\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u044d\u0442\u043e\u0442\u00a0\u0436\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 \u043d\u0430\u00a0\u043a\u043e\u0434 \u0438 \u043e\u0431\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 (\u0431\u0435\u0437 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438).\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c .spec:\u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 PascalCase, \u0433\u0434\u0435 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0443\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: ProfileSettings.spec.ts &#8212; \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, ForgotPassword.spec.ts &#8212; \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c .spec:\u0415\u0441\u043b\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u0438\u0445 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0438\u0447\u0443 \u0432 \u0446\u0435\u043b\u043e\u043c.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u0441\u0442\u044b ProfileView.spec.ts \u0438 ProfileEdit.spec.ts \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0431\u0449\u0435\u0439 \u043f\u0430\u043f\u043a\u0435 tests\/e2e\/profile, \u0430 \u0444\u0438\u0447\u0430 Authorization \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b ForgotPassword.spec.ts \u0438 SignUp.spec.ts, \u0433\u0434\u0435 \u043f\u0443\u0442\u044c tests\/e2e\/Authorization\/ \u0438\u043b\u0438 tests\/api\/AuthCheck\/\u2757\u0412\u0430\u0436\u043d\u043e: \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 beforeeEach \/ afterEach \/describe hooks \u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f (beforeEach), \u043f\u043e\u0441\u0442\u0443\u0441\u043b\u043e\u0432\u0438\u044f (afterEach) \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 (describe) &#8212; \u044d\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Playwright Test, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b\u0435 \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u0438\u0434\u0430\u043c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 (API, e2e, smoke)\u041f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u043e\u043c:BeforeEach \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f: \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043b\u043e\u0433\u0438\u043d, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0442\u0438\u043f\u043e \u0442\u043e\u0433\u043e.\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0448\u0430\u0433\u0438 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e spec.ts \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c beforeEach\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f beforeEachimport { test, expect } from &#8216;@playwright\/test&#8217;;let createdProducts = {}test.beforeEach(async ({ page, request }) =&gt; {\u00a0\u00a0\/\/ \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e API \u0432\u0435\u0440\u043d\u0451\u0442 \u0441\u043f\u0438\u0441\u043e\u043a\u00a0\u00a0\u00a0\/\/ \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0433\u0434\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f = \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430\u00a0\u00a0createdProducts = await request.post(&#8216;\/api\/products\/create&#8217;, {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: { count: 5, category: &#8216;electronics&#8217; },\u00a0\u00a0});\u00a0 const createdProducts = await resp.json();\u00a0  \/\/ 2. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 &#171;\u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0430&#187;\u00a0\u00a0await page.goto(&#8216;\/products\/electronics&#8217;);\u00a0\u00a0\/\/ 3. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c = 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432\u00a0\u00a0const items = page.locator(&#8216;[data-testid=&#187;product-item&#187;]&#8217;);\u00a0\u00a0const count = await items.count();\u00a0\u00a0expect(count).toBeGreaterThanOrEqual(5);\u00a0\u00a0\/\/ 4. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430 \u0438\u0437 API\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0 \u00a0const item = page.locator([data-testid=&#187;product-item&#187;][data-id=&#187;${product.id}&#187;]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}});\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0432\u00a0spec.ts \u0432\u00a0beforeEach \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u00a0API, \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u00a0\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438. \u0414\u043b\u044f\u00a0\u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u043d\u043e\u00a0\u043f\u043b\u043e\u0445\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432\u00a0\u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 (\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438\u00a0\u0442.\u00a0\u0434.), \u0442\u043e \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0441\u043a\u0438 \u043a\u043e\u0434\u0430.\u0427\u0442\u043e\u0431\u044b \u043d\u0435\u00a0\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u0438 \u0442\u043e\u0436\u0435\u00a0\u2014 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0441\u0435 \u0447\u0442\u043e\u00a0\u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u043f\u043e\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0432\u00a0\u0445\u0435\u043b\u043f\u0435\u0440\u044b \u0438\u043b\u0438\u00a0\u0432\u00a0pageObject (\u0441\u043c. \u043f\u0440\u0438\u043c\u0435\u0440)\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u0440\u0435\u0444\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e beforeEach\/\/common\/helpers\/products-helper.tsimport { APIRequestContext} from &#8216;@playwright\/test&#8217;;import { PRODUCT_CREATE} from &#8216;playwrightTests\/common\/apiRoutes&#8217;;\/**\u00a0* \u0421\u043e\u0437\u0434\u0430\u0451\u0442 n \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\u00a0\u00a0*\/export async function createManyProductsByCategory(\u00a0\u00a0request: APIRequestContext,\u00a0\u00a0categoryName: string,\u00a0\u00a0totalCount: number) {\u00a0\u00a0try {\u00a0\u00a0\u00a0\u00a0const resp = await request.post(PRODUCT_CREATE, {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data: { count: totalCount, category: categoryName },\u00a0\u00a0\u00a0\u00a0});\u00a0\u00a0\u00a0\u00a0if (!resp.ok()) {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error(\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&#8216;\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u0432\u0430\u0440\u043e\u0432. Status: &#8216; + resp.status()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0const data = await resp.json();\u00a0\u00a0\u00a0\u00a0if (!Array.isArray(data)) {\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error(&#8216;API \u0432\u0435\u0440\u043d\u0443\u043b\u043e \u041d\u0415 \u043c\u0430\u0441\u0441\u0438\u0432&#8217;);\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0return data;\u00a0\u00a0} catch (err) {\u00a0\u00a0\u00a0\u00a0throw err\u00a0\u00a0}}\u0414\u0430\u043b\u0435\u0435, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject \u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 test.step \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0411\u044b\u043b\u043e&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\/\/ 3. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c &gt; 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432\u00a0\u00a0const items = page.locator(&#8216;[data-testid=&#187;product-item&#187;]&#8217;);\u00a0\u00a0const count = await items.count();\u00a0\u00a0expect(count).toBeGreaterThan(limit);&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\u0421\u0442\u0430\u043b\u043e: \u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 steptest.step(&#8216;\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0438\u0441\u044c &gt; 5 \u0442\u043e\u0432\u0430\u0440\u043e\u0432&#8217;,\u00a0\u00a0\u00a0async () =&gt; {\u00a0\u00a0\u00a0const item = page.getByTestId(PRODUCT_ITEM);\u00a0\u00a0\u00a0const count = await item.count();\u00a0\u00a0\u00a0expect(count).toBeGreaterOrEqual(limit);})&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\u0421\u0442\u0430\u043b\u043e: \u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject (\u043b\u0443\u0447\u0448\u0435)\/\/ common\/pages\/ProductListPage.tsasync checkProductsCount(limit: number) {\u00a0\u00a0const count = await this.item.count();\u00a0\u00a0await expect(count).toBeGreaterThanOrEqual(limit);}\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0442\u043e \u044d\u0442\u043e \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 id \u0442\u043e\u0432\u0430\u0440\u0430 \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0442\u043e\u0432\u0430\u0440\u0430\u0411\u044b\u043b\u043e&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;\/\/ 4. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0\u00a0const item = page.locator([data-testid=&#187;product-item&#187;][data-id=&#187;${product.id}&#187;]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible(); \u00a0\u00a0}\u0421\u0442\u0430\u043b\u043e\u00a0&#8212;&#8212;&#8212;&#8212;&#8212;-\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0432 steptest.step(&#8216;\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441 id \u0442\u043e\u0432\u0430\u0440\u0430&#8217;, async () =&gt; {\u00a0\u00a0for (const product of createdProducts) {\u00a0\u00a0\u00a0\u00a0const item = page.getByTestId(PRODUCT_ITEM).locator([data-id=&#187;${product.id}&#187;]);\u00a0\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}});&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 PageObject (\u043b\u0443\u0447\u0448\u0435)\/\/ common\/locators\/product-locators.tsexport function getProductCardById(id: number): string {\u00a0\u00a0return [data-testid=&#187;${PRODUCT_ITEM}&#187;][data-id=&#187;${id}&#187;];}\/\/ common\/pages\/ProductListPage.tsasync verifyProductCardsVisible(products: { id: number }[]) {\u00a0\u00a0for (const product of products) {\u00a0\u00a0\u00a0const item = this.page.locator(getProductCardById(product.id));\u00a0\u00a0\u00a0await expect(item).toBeVisible();\u00a0\u00a0}}\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0438\u0434 \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:import { test, expect } from &#8216;@playwright\/test&#8217;;import {&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-475024","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/475024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=475024"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/475024\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=475024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=475024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=475024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}