{"id":472819,"date":"2025-09-01T09:00:21","date_gmt":"2025-09-01T09:00:21","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=472819"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=472819","title":{"rendered":"<span>\u0417\u0430\u043f\u0438\u0441\u043a\u0438 \u043e\u0434\u043d\u043e\u0433\u043e QA. \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: \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 (Playwright + Typescript)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0413\u043b\u0430\u0432\u0430 1. \u041a\u0430\u043a\u00a0\u0432\u0441\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u043e\u0441\u044c. \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0438 \u0432\u043e\u0434\u044b \u043e\u00a0\u043c\u043e\u0435\u043c\u00a0\u043b\u0438\u0447\u043d\u043e\u043c \u043e\u043f\u044b\u0442\u0435.<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442!<br \/>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u0439\u043d\u0443\u0440\u0430.<\/p>\n<div class=\"floating-image\">\n<p>\u041c\u043e\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0441 Playwright \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u043e\u043a\u043e\u043b\u043e \u0434\u0432\u0443\u0445 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434. \u0417\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u044f \u043d\u0435 \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0430\u0441\u044c \u0441 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438, \u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043d\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c.<\/p>\n<\/div>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/550\/389\/3c4\/5503893c4b94bf89152af1e5cc11931a.png\" alt=\"\u041c\u0443\u043b\u044c\u0442\u044f\u0448\u043d\u044b\u0439 \u0434\u0440\u0430\u043a\u0443\u043b\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442! \u041d\u0435 \u0441\u043a\u0432\u0435\u0440\u043d\u043e\u0441\u043b\u043e\u0432\u0438\u0442!\" title=\"\u041c\u0443\u043b\u044c\u0442\u044f\u0448\u043d\u044b\u0439 \u0434\u0440\u0430\u043a\u0443\u043b\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442! \u041d\u0435 \u0441\u043a\u0432\u0435\u0440\u043d\u043e\u0441\u043b\u043e\u0432\u0438\u0442!\" width=\"1536\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/550\/389\/3c4\/5503893c4b94bf89152af1e5cc11931a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/550\/389\/3c4\/5503893c4b94bf89152af1e5cc11931a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041c\u0443\u043b\u044c\u0442\u044f\u0448\u043d\u044b\u0439 \u0434\u0440\u0430\u043a\u0443\u043b\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442! \u041d\u0435 \u0441\u043a\u0432\u0435\u0440\u043d\u043e\u0441\u043b\u043e\u0432\u0438\u0442!<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b\u0441\u043b\u044c \u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 Playwright \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0432 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e Codeception \u043d\u0435 \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0440\u044f\u0434\u043e\u043c \u0437\u0430\u0434\u0430\u0447, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0447\u0430\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0441 WebView.<\/p>\n<p>\u0410 <strong>\u043c\u0438\u043d\u0443\u0441\u044b<\/strong> \u0431\u044b\u043b\u0438 \u0432\u0435\u0441\u043e\u043c\u044b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <strong>Codeception<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u274c \u0414\u043e PHP 8 \u0432\u0441\u0451 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 Codeception \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0443\u0447\u043d\u044b\u043c. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u044d\u0442\u043e\u0442 \u0433\u0435\u043c\u043e\u0440: \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e 8-\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 PHP, \u043b\u0438\u0431\u043e \u0432\u0441\u0451 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0427\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0438\u0434\u0435\u044f \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u043d\u044f \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u044f\u043b\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0430 \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 API-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 (\u041f\u0440\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u044f \u0437\u0430 \u044d\u0442\u043e \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438) .<\/p>\n<\/li>\n<li>\n<p>\u274c \u0421\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435! \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0430 \u043a\u0435\u0439\u0441\u043e\u0432 \u043d\u0430 WEBVIEW \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 (\u0430 \u044d\u0442\u043e \u0431\u044b\u043b \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043c\u0438\u043d\u0443\u0441). \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u043c\u0438 &#8212; \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e Chrome \u0447\u0435\u0440\u0435\u0437 WebDriver)<\/p>\n<\/li>\n<li>\n<p>\u274c \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 <\/p>\n<\/li>\n<li>\n<p>\u274c \u041d\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p>\u274c \u041c\u0435\u043d\u044c\u0448\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u274c \u0414\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433 \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0433 \u0431\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0433\u0447\u0435. \u0412 Codeception \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438: \u043d\u0435\u043b\u044c\u0437\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u0438\u0434\u0435\u0442\u044c, \u043a\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0443\u0445\u043e\u0434\u0438\u0442 \u0438 \u043a\u0430\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438. \u0412\u0441\u0451 \u044d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>\u274c \u041d\u0435 \u0431\u044b\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u274c \u0412 Codeception \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0438\u0434\u043e\u0432 \u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0440\u043e\u0434\u0435 <strong>see, dontSee<\/strong> \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0442\u0435\u043a\u0441\u0442\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 <strong>soft-\u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432<\/strong><\/p>\n<\/li>\n<li>\n<p>\u274c \u041f\u043e\u0438\u0441\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f <strong>\u0422\u041e\u041b\u042c\u041a\u041e  <\/strong>\u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b: <code>data-test-id<\/code>, <code>id, class \u0438 \u0442 \u0434<\/code>. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430 (<code>class<\/code>) \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043b\u043e\u0445\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0438\u043b\u0438 \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u044b( class=&#187;yellow__1a2b3&#8243; \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0430  class=&#187;yellow__97dhfgg&#187;)<\/p>\n<\/li>\n<li>\n<p>\u274c \u041c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u0441 best practices<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0412\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043b\u044e\u0441\u043e\u0432 <\/strong>Playwright<strong> \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0448\u0430\u044e\u0442 \u043c\u0438\u043d\u0443\u0441\u044b Codeception :<\/strong><\/p>\n<ul>\n<li>\n<p>\u2705 <strong><em>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432<\/em><\/strong>. \u0422\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u0440\u043e\u0441\u0441\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0441\u0442\u0438.<\/em><\/strong> Playwright \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 Chromium, Firefox, WebKit \u0438 \u0434\u0430\u0436\u0435 \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432.<\/em> <\/strong>\u0412\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Playwright \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0447\u0435\u043c \u043d\u0430 Codeception \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u0432 CI\/CD  (\u0441\u043c. \u0422\u0430\u0431\u043b\u0438\u0446\u0430 1)<\/p>\n<\/li>\n<li>\n<p>\u2705<em> <\/em><strong><em>\u041b\u0451\u0433\u043a\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f UI-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Codegen<\/em><\/strong><em> <\/em>\u2014 \u043c\u043e\u0436\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 <\/em><\/strong>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441 <strong>\u043f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c<\/strong> \u0442\u0435\u0441\u0442\u0430 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430. \u0412 Playwright \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0433\u0438\u0431\u043a\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430: \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442, \u0433\u0440\u0443\u043f\u043f\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043f\u0430\u0432\u0448\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044e Trace Viewer \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0438 DOM-\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435 \u0442\u0435\u0441\u0442\u0430, \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043e\u0442\u0432\u0435\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043e\u0448\u0438\u0431\u043a\u0438, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0431\u044b\u0441\u0442\u0440\u044b\u043c \u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435<\/em><\/strong><em>.<\/em> \u0412 Playwright \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 expect().toHaveScreenshot(), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043f\u0440\u044f\u043c\u043e \u0432 \u0442\u0435\u0441\u0442\u0435 (\u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435).<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041c\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u043e\u0432 \u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432 \u0438 soft-\u0430\u0441\u0441\u0435\u0440\u0442\u044b<\/em><\/strong>, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0442\u0435\u043a\u0441\u0442\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 (await elementHandle.isChecked(), await elementHandle.isEditable(), await elementHandle.isEnabled()).  \u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <strong>soft-\u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432 <\/strong>(\u043c\u044f\u0433\u043a\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u0434\u0435\u043b\u0430\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0413\u0438\u0431\u043a\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/em><\/strong>. \u0412 Playwright \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043d\u0438\u043c \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 (heading, label, text, paragraph \u0438 \u0442. \u043f.), \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b (data-test-id, id \u0438 \u0442 \u0434), \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 (\u0446\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430), \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 (locator.getByRole(), locator.getByText(), locator.getByTestId()), \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041e\u0431\u0448\u0438\u0440\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0441\u0442\u0430\u0442\u044c\u0438.<\/em><\/strong><em> <\/em>\u041a\u0440\u043e\u043c\u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0435\u0439, \u0433\u0430\u0439\u0434\u043e\u0432 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0441 \u0432\u044b\u0445\u043e\u0434\u043e\u043c \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0442\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432, \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f API-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0434\u0435\u0431\u0430\u0433\u0430.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/71d\/458\/2f5\/71d4582f5a81459582854f93f08aa266.png\" alt=\"\u0422\u0430\u0431\u043b\u0438\u0446\u0430 1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 Playwright vs Codeception\" title=\"\u0422\u0430\u0431\u043b\u0438\u0446\u0430 1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 Playwright vs Codeception\" width=\"1428\" height=\"348\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/71d\/458\/2f5\/71d4582f5a81459582854f93f08aa266.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/71d\/458\/2f5\/71d4582f5a81459582854f93f08aa266.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 Playwright vs Codeception<\/figcaption><\/div>\n<\/figure>\n<p>\u2757 <strong>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435!  <\/strong>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u044b, <strong>\u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a WebView<\/strong> \u2014 \u044d\u0442\u043e <strong>\u043e\u0431\u0449\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0441 best practices<\/strong>, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u0430 \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u2757<strong>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435! <\/strong>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f  \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442  \u0432 \u0441\u043a\u0440\u044b\u0442\u043e\u043c \u0442\u0435\u043a\u0441\u0435.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 2. \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \ud83d\ude80 \u041c\u043e\u0438 best practices <\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u043b\u0430\u0432\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0441\u043b\u0443\u0436\u0430\u0449\u0430\u044f \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u043e\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u0445 \u0438 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.  \u0410 \u0438\u043c\u0435\u043d\u043d\u043e:<em> PageObject-\u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, helpers, step pattern, config, snapshots.<\/em><\/p>\n<p><strong>\u041f\u0440\u0438\u0447\u0438\u043d\u0430<\/strong>, \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0441\u044c \u043d\u0430 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <strong>\u0441\u0430\u043c\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u044d\u0442\u0438\u0445 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/strong>. \u0412\u0441\u0451, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 <code>common<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 <code>snapshots<\/code> \u0438 <code>config<\/code>.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0432\u0441\u0451 \u043f\u043e\u0434\u0440\u044f\u0434, \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u043b\u0438 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u0435\u0434\u0451\u0442 \u043a \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u044e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u044e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434-\u0440\u0435\u0432\u044c\u044e \u0438 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 -&gt; \u043a \u0445\u0430\u043e\u0441\u0443.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0442 \u0445\u0430\u043e\u0441 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b \u0438\u043b\u0438 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a  \u0440\u0430\u0437\u0433\u0440\u0435\u0431\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0445\u0430\u043e\u0441, \u044f \u0443\u0434\u0435\u043b\u044f\u044e \u043e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p><strong><em>\u0418 \u0442\u0430\u043a\u0441, \u043d\u0430\u0447\u043d\u0435\u043c \ud83d\ude80\ud83d\udc47<\/em><\/strong><\/p>\n<h4>\ud83d\uddc2 \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430<\/h4>\n<p>C \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u043d\u0435\u043c? \u041a\u043e\u043d\u0435\u0448\u043d\u043e \u0436\u0435, \u0441 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. <\/p>\n<p>\u0418 \u0442\u0430\u043a  \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0443\u0436\u043d\u0430 \u0442\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u044f \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e  QA  \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0430\u044f ( \u0431\u0435\u0437 \u043a\u0440\u0430\u0441\u043e\u0442\u044b \u0436\u0438\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f!)<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0432\u0438\u0434\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f). \u0412\u0430\u0436\u043d\u043e \u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u043d\u0443\u0436\u043d\u044b \u043b\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043b\u0438 e2e-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f UI-\u043f\u0440\u043e\u0435\u043a\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438 API, \u0438 UI \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 (\u043f\u0440\u0438 \u044d\u0442\u043e\u043c API-\u0442\u0435\u0441\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 UI)<\/p>\n<\/li>\n<li>\n<p>\u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b devDependencies  \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c  package.json ,  \u0438\u043b\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. <\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u043e\u0439 package.json \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0415\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 <code>package.json<\/code>:<\/p>\n<ul>\n<li>\n<p> \u0442\u043e \u044d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 <code>node_modules<\/code><\/p>\n<\/li>\n<li>\n<p> \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 <\/p>\n<\/li>\n<li>\n<p>\u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 CI\/CD<\/p>\n<\/li>\n<li>\n<p> \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p> \u043c\u043e\u0436\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043e\u0431\u0440\u0430\u0437\u0430 (\u0435\u0441\u043b\u0438 \u043d\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b <code>dependencies<\/code> \u0438 <code>devDependencies<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c <code>package.json)<\/code><\/p>\n<\/li>\n<\/ul>\n<p>&#171;\u042f \u0431\u044b \u043d\u0435 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u043b\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (devDependencies) \u0441 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c package.json \u0438 \u0432\u044b\u043d\u0435\u0441\u043b\u0430 \u0431\u044b \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c package.json, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0447\u0438\u0441\u0442\u043e\u0442\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430&#187;<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0442\u0440\u0451\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432: <strong>common<\/strong>, <strong>snapshots<\/strong> \u0438 <strong>tests<\/strong> \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.<\/p>\n<div class=\"floating-image\">\n<figure class=\"float\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26a\/3a8\/c02\/26a3a8c02836680f5d6e645a8bcfff89.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430  \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439  \u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430  \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439  \u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \" width=\"478\" height=\"916\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/26a\/3a8\/c02\/26a3a8c02836680f5d6e645a8bcfff89.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26a\/3a8\/c02\/26a3a8c02836680f5d6e645a8bcfff89.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430  \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439  \u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 <\/figcaption><\/div>\n<\/figure>\n<p><strong>&#8212; common<\/strong> \u2013 \u043e\u0431\u0449\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 (\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0448\u0430\u0433\u0438).<\/p>\n<p><strong>&#8212; snapshots<\/strong> \u2013 \u0441\u043d\u0438\u043c\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432).<\/p>\n<p>&#8212; <strong>tests<\/strong> \u2013 \u0441\u0430\u043c\u0438 \u0442\u0435\u0441\u0442\u044b, \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0442\u0438\u043f\u0430\u043c (smoke, e2e, api)<\/p>\n<p>&#8212; <strong>playwright.config.ts <\/strong>&#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043e\u0431\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Playwright<\/p>\n<p>\ud83d\udcc1 <strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong> \ud83d\udccc <strong>(\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c!)<\/strong><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u043b\u044f \u044f\u0441\u043d\u043e\u0441\u0442\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439.<\/p>\n<\/div>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0444\u0430\u0439\u043b\u043e\u0432, <strong>\u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u0443 <em>\u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435<\/em><\/strong>, \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0449\u0435\u0435 \u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<ul>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b, c\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>kebab-case<\/code> + \u043e\u043a\u0430\u043d\u0447\u0430\u043d\u0438\u0435 <code>locators<\/code>.  \u041f\u0440\u0438\u043c\u0435\u0440: <code>filter-locators.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b,  c\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435  \u0445\u0435\u043b\u043f\u0435\u0440\u044b (services)<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>kebab-case<\/code>   + \u043e\u043a\u0430\u043d\u0447\u0430\u043d\u0438\u0435  \u043d\u0430 <code>helper<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: <code>date-format-helper.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b  c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>kebab-case<\/code> \u0438 \u043e\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 <code>constants<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440:  <code>profile-constants.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>PascalCase<\/code> \u0438 \u043e\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 <code>Component<\/code> \u0438\u043b\u0438 <code>Page<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: UserProfilePage.ts, <code>FilterComponent.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b  c  \u0441\u0430\u043c\u0438\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>PascalCase<\/code> \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c <code>.spec.ts <\/code>. \u041f\u0440\u0438\u043c\u0435\u0440:  ProfileSettings.spec.ts\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>kebab-case<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: <code>api-routes.ts<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u0430 <strong>\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0444\u0438\u0447\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u0434\u0435\u043b\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0439.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0445 <strong>common(support)<\/strong> \u0438\u043b\u0438 <strong>tests<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438\u0445 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0432 \u043e\u0434\u043d\u0443 \u043f\u0430\u043f\u043a\u0443. \u042d\u0442\u043e \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e.<\/p>\n<ol>\n<li>\n<p> \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong>Authorization<\/strong>) \u2192 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443.   \u041f\u0440\u0438\u043c\u0435\u0440: <code>pages\/auth\/LoginPage.ts<\/code>, <code>pages\/auth\/RegisterPage.ts<\/code><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong> ProfilePage.ts,  EditProfileTest.spec.ts<\/strong>) \u2192 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043b\u044f \u043d\u0435\u0451 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p>\ud83d\udc49 <strong>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0447\u0442\u043e \u043a \u0447\u0435\u043c\u0443 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <em>common (support) <\/em><\/strong>\u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Playwright.<\/p>\n<p>\u042d\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <strong>\u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434<\/strong>, \u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0439\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0438\u043b\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c.<\/p>\n<div class=\"floating-image\">\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <strong>common(<\/strong>\u0438\u043b\u0438 \u0436\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u0435 \u0441\u0440\u0435\u0434\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435  -&gt; <strong>support)<\/strong> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432, \u0434\u0435\u043b\u0430\u044f \u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0435\u043d\u043d\u043e\u0439. \u0417\u0434\u0435\u0441\u044c \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p> \u041f\u0430\u043f\u043a\u0430 <strong>common(support)<\/strong> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 8 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0438  \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 Playwright:<\/p>\n<\/div>\n<ol>\n<li>\n<p><strong>base<\/strong> &#8212;  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0438\u0445 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 (Common, BasePage, BaseComponent \u0438 \u0434\u0440\u0443\u0433\u0438\u0445), \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>constants<\/strong> \u2013 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432\u043e \u0432\u0441\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 <\/p>\n<\/li>\n<li>\n<p><strong>helpers<\/strong> \u2013 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b (\u043e\u0431\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432: \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u0442, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0440.)<\/p>\n<\/li>\n<li>\n<p><strong>locators<\/strong> \u2013 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>apiRoutes<\/strong>\u2013 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0434\u043b\u044f API.<\/p>\n<\/li>\n<li>\n<p><strong>components<\/strong> \u2013 \u043e\u0431\u0449\u0438\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>pages<\/strong> \u2013 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446 (Page Object Model).<\/p>\n<\/li>\n<li>\n<p><strong>steps<\/strong> \u2013 \u0448\u0430\u0433\u0438 \u0434\u043b\u044f e2e \u0438 API \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>config<\/strong> \u2013 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b Playwright.<\/p>\n<\/li>\n<\/ol>\n<h4>\ud83d\udccc Base (\u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b)<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 PageObject \u0438\u043b\u0438 ComponentObject \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b (\u0438\u043b\u0438 \u043e\u0434\u0438\u043d \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441), \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0441 playwright.Page, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u0434\u0430\u043d\u044b \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<\/p>\n<p>\u042d\u0442\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>\/common\/base\/<\/code><\/p>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438: BasePage  \u0438\u043b\u0438  BaseComponent \u0438\u043b\u0438  Base.<\/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\/d7b\/626\/b87\/d7b626b875ec3ff6d30b7875a0769593.png\" alt=\"\" title=\"\" width=\"650\" height=\"356\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d7b\/626\/b87\/d7b626b875ec3ff6d30b7875a0769593.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d7b\/626\/b87\/d7b626b875ec3ff6d30b7875a0769593.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u26a0\ufe0f <strong>\u0412\u0430\u0436\u043d\u043e<\/strong>!  \u0432 \u043c\u043e\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u0438\u043d \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <strong>Base<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 this.page \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435  \u0438 \u0432\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b ComponentObject \/ PageObjects  \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u044b \u043e\u0442 Base.<\/p>\n<\/div>\n<p>\u041a\u043b\u0430\u0441\u0441 Base<strong>  &#8212; <\/strong>\u0445\u0440\u0430\u043d\u0438\u0442 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c\u0438(<code>\u0435lementVisibility<\/code> \u0438\u043b\u0438 <code>compareScrenshots)<\/code> , \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f\u043c\u0438, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>data-testid<\/code> \/ \u0440\u0430\u043d\u0435\u0435 <code>data-test-id<\/code>)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 Base \u043a\u043b\u0430\u0441\u0441\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\u041f\u0443\u0442\u044c common\/base\/Base.ts  import { expect, Locator, Page, selectors } from '@playwright\/test';  export class Base {   readonly page: Page;    selectors.setTestIdAttribute('data-test-id');    constructor(page: Page) {     this.page = page;;   }    \/**    * \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u0438\u0434\u0435\u043d    *\/   async elementVisibility(target: Locator) {     await expect(target).toBeVisible();   }    \/**    * \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430    *\/   async areScreenshotsMatch(     target: Locator | Page,     name?: string,     increasedDiff = 1,     options: Record&lt;string, unknown&gt; = {}   ) {     const diffPixels = 100 * increasedDiff;     await expect.soft(target).toHaveScreenshot(name ?? '', {       maxDiffPixels: diffPixels,       ...options,     });   } } <\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc Constants<\/h4>\n<p>\u0417\u0430\u0447\u0435\u043c \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b? &#8212; \u0412\u044b\u043d\u043e\u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p><em>\u0418\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0437\u0430\u0445\u043b\u0430\u043c\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/em><\/p>\n<\/li>\n<li>\n<p><em>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u0447\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/em><\/p>\n<\/li>\n<li>\n<p><em>\u0423\u043f\u0440\u043e\u0449\u0430\u0442\u044c \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/em><\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p><strong><em>profile-constants.ts<\/em><\/strong><em> \u2013 <\/em>\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c<em>. <\/em><\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f33\/ab5\/35d\/f33ab535d58141add4e2d9d86191ddb3.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b\" width=\"1170\" height=\"468\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f33\/ab5\/35d\/f33ab535d58141add4e2d9d86191ddb3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f33\/ab5\/35d\/f33ab535d58141add4e2d9d86191ddb3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b<\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p><strong><em>common-constants.ts<\/em><\/strong><em> \u2013 <\/em>\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0449\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443. <\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3da\/ab1\/83a\/3daab183a31cb9bf1a078ebfc55731af.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\" width=\"1242\" height=\"752\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/3da\/ab1\/83a\/3daab183a31cb9bf1a078ebfc55731af.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3da\/ab1\/83a\/3daab183a31cb9bf1a078ebfc55731af.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0412\u0441\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438: <code>\/common\/constants. <\/code><\/p>\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <strong>constants<\/strong> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0447\u0451\u0442\u043a\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u0449\u0443\u044e \u0438\u0434\u0435\u044e \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0432 \u0444\u0430\u0439\u043b\u0435. \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>kebab-case<\/strong> \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0443\u0444\u0444\u0438\u043a\u0441 <code>-constants.  <\/code><\/p>\n<p>\u2b50 \u041f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438: <code>\/common\/constants\/{NAME}-constants.ts <\/code><\/p>\n<p>\u2b50 \u041a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430: \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e <code><strong>export, <\/strong><\/code>\u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435(\u0441\u043c. \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442) <\/p>\n<p>\u0412\u044b\u0437\u043e\u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <strong>\u0438\u043c\u043f\u043e\u0440\u0442<\/strong><code>import { LOGIN_ERROR_MESSAGE } from '..\/common\/constants\/auth-constants';<\/code><\/p>\n<p> \u2b50 \u041a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 (\u0442\u0435\u043a\u0441\u0442\u044b, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f, \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u044b, \u0447\u0438\u0441\u043b\u0430 \u0438 \u0442. \u0434.), \u0432\u044b\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <code>common\/constants\/{feature-name}-constants.ts<\/code><\/p>\n<p>\u0412 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u0445 \u0442\u0430\u043a\u0436\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u043e\u043a-\u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430 API-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0432\u0438\u0434\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0433\u0434\u0435 \u0447\u0435\u0440\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u0432\u0435\u0442\u0435. \u041f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0433\u043e\u0441\u044f \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <code>\/constants\/mocks\/user-profile-constants.ts \u0438\u043b\u0438 \/constants\/profile-constants.ts. <\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<div class=\"floating-image\">\n<figure class=\"float full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/091\/2d6\/7eb\/0912d67eba25b572c0d4700b0148da45.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430\" width=\"1024\" height=\"1536\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/091\/2d6\/7eb\/0912d67eba25b572c0d4700b0148da45.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/091\/2d6\/7eb\/0912d67eba25b572c0d4700b0148da45.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430  \u0444\u0443\u043d\u043a\u0446\u0438\u0438  \u0444\u0443\u043d\u043a\u0446\u0438\u0438<code>getUserProfileSettingsMock<\/code>\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u043f\u043e\u043d\u0437<\/p>\n<\/div>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1c\/182\/f26\/c1c182f2609f85a448811100e2064a4c.png\" alt=\"\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438getUserProfileSettingsMock\" title=\"\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438getUserProfileSettingsMock\" width=\"1122\" height=\"512\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c1c\/182\/f26\/c1c182f2609f85a448811100e2064a4c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1c\/182\/f26\/c1c182f2609f85a448811100e2064a4c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><strong>\u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/strong><code>getUserProfileSettingsMock<\/code><\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u26a0\ufe0f \u041a\u0441\u0442\u0430\u0442\u0438, \u0435\u0441\u043b\u0438 \u0432 api \u0442\u0435\u0441\u0442\u0430\u0445 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u0441\u0445\u0435\u043c\u0443 \u0442\u043e \u0441\u0445\u0435\u043c\u044b  -&gt; \u0422\u041e \u043b\u0443\u0447\u0448\u0435  \u0432\u0441\u0435 \u0441\u0445\u0435\u043c\u044b (\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432) \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 <code>.\/common\/constants\/shemas\/{FEATURE}<\/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\/fed\/27a\/f2a\/fed27af2a42aa4aea486ff2235dd109e.png\" alt=\"\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u0441\u0445\u0435\u043c \" title=\"\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u0441\u0445\u0435\u043c \" width=\"614\" height=\"346\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fed\/27a\/f2a\/fed27af2a42aa4aea486ff2235dd109e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fed\/27a\/f2a\/fed27af2a42aa4aea486ff2235dd109e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u0441\u0445\u0435\u043c <\/figcaption><\/div>\n<\/figure>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 order-shemas.ts \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0437\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u0437\u0430\u043a\u0430\u0437\u0443 <\/p>\n<\/div>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/ common\/constants\/shemas\/order-shemas\/orderResponse.schema.ts  export const LAST_ORDER_BY_USER_ID = [   {     id: expect.any(Number),     payedAt: expect.any(String),      \/\/ ISO date string     createdAt: expect.any(String),    \/\/ ISO date string     isDelivered: expect.any(Boolean),     address: expect.any(String),     status: expect.any(String),   }, ];<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443 \u0436\u0435 \u0441\u0445\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u044f\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 <code>orderNumber<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0437\u0430\u043a\u0430\u0437 \u0441 \u043b\u044e\u0431\u044b\u043c \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443 \u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<pre><code>\/\/ common\/constants\/shemas\/order-shemas.ts  export const getOrderSchema = (orderNumber: string) =&gt; ({   [orderNumber]: [     {       id: expect.any(Number),       payedAt: expect.any(String),      \/\/ ISO date string       createdAt: expect.any(String),    \/\/ ISO date string       isDelivered: expect.any(Boolean),       address: expect.any(String),       status: expect.any(String),       userId: expect.any(Number),     },   ], });   \/\/ \u0430\u0441\u0441\u0435\u0440\u0442 \u0432 \u0442\u0435\u0441\u0442\u0435 expect(json).toMatchObject(getOrderSchemaB(\"KZ-12345-ONLINE\")); <\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc Helpers.  \u26a0\ufe0f \u041d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c \u0441 playwright-helpers.<\/h4>\n<p><strong>Helpers<\/strong> \u2014 \u044d\u0442\u043e \u0444\u0430\u0439\u043b\u044b \u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0445\u0435\u043b\u043f\u0435\u0440\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 common(support). \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u0440\u0435\u0432\u0430 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/275\/fd9\/8bc\/275fd98bc9a3e009fa84636ab5de38b8.png\" alt=\"\u0414\u0435\u0440\u0435\u0432\u043e \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432\" title=\"\u0414\u0435\u0440\u0435\u0432\u043e \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432\" width=\"1812\" height=\"474\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/275\/fd9\/8bc\/275fd98bc9a3e009fa84636ab5de38b8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/275\/fd9\/8bc\/275fd98bc9a3e009fa84636ab5de38b8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0435\u0440\u0435\u0432\u043e \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><strong><em>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/em><\/strong><\/p>\n<ul>\n<li>\n<p>Helpers \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>\u042d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0433\u0434\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438\/\u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0442\u0435\u043c \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 <strong>components<\/strong>, <strong>pages<\/strong>, <strong>steps<\/strong> \u0438\u043b\u0438 <strong>tests<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p><strong><em>\u0425\u0435\u043b\u043f\u0435\u0440\u044b \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f:<\/em><\/strong><\/p>\n<ol>\n<li>\n<p><strong>\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430<\/strong> \u2013 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u0442) \u0432 \u043e\u0434\u043d\u043e \u043c\u0435\u0441\u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/strong> \u2013 \u0442\u0435\u0441\u0442\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0447\u0438\u0449\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u0432 \u043d\u0438\u0445 \u043d\u0435\u0442 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438<\/strong> \u2013 \u0445\u0435\u043b\u043f\u0435\u0440\u044b \u043e\u0442\u0434\u0435\u043b\u044f\u044e\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u043e\u0442 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0441\u0442\u0438<\/strong> \u2013 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u0445\u0435\u043b\u043f\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0432\u043e \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u0430\u0445, \u0433\u0434\u0435 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439<\/strong> \u2013 \u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u0435\u0451 \u0432\u044b\u0437\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/strong> \u2013 \u0443\u0441\u043a\u043e\u0440\u044f\u044e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0443\u0442\u0438\u043b\u0438\u0442.<\/p>\n<\/li>\n<\/ol>\n<p><strong> <em>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432:<\/em><\/strong><\/p>\n<ol>\n<li>\n<p><em>\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430<\/em>:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>kebab\u2011case<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043b\u0436\u043d\u043e \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u00a0\u0441\u0443\u0444\u0444\u0438\u043a\u0441 <code><strong>-helper<\/strong><\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0431\u0443\u043a\u0432\u044b\u00a0\u2014 \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435, \u0441\u043b\u043e\u0432\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0435\u0444\u0438\u0441\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0443\u0442\u044c \u043a\u00a0\u0444\u0430\u0439\u043b\u0443 \u0441\u00a0\u0445\u0435\u043b\u043f\u0435\u0440\u0430\u043c\u0438 \u0432\u00a0\u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435: <code>\/common\/helpers\/{NAME}-helper.ts<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: <code>date-transform-helper.ts<\/code>, <code>user-profile-helper.ts<\/code><\/p>\n<\/li>\n<li>\n<p><em>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0445\u0435\u043b\u043f\u0435\u0440\u0430:<\/em><\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <strong>\u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e<\/strong> <code>export<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f <strong>\u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/strong> \u0432\u00a0\u0432\u0438\u0434\u0435 <strong>JSDoc\u2011\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3> \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/h3>\n<ul>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 <\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u0434\u0430\u0442 \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438).<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0443<code>common-helper.ts<\/code><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/910\/48f\/a4b\/91048fa4b531067d928de78016a2631a.png\" alt=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\" title=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\" width=\"1532\" height=\"626\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/910\/48f\/a4b\/91048fa4b531067d928de78016a2631a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/910\/48f\/a4b\/91048fa4b531067d928de78016a2631a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 2 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f  \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e ID. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 <code>user-profile-helper.ts<\/code><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/879\/d62\/460\/879d62460d3d10f4194958223d2a2a43.png\" alt=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e ID \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\" title=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e ID \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\" width=\"1002\" height=\"658\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/879\/d62\/460\/879d62460d3d10f4194958223d2a2a43.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/879\/d62\/460\/879d62460d3d10f4194958223d2a2a43.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u043f\u043e ID \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 3 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u0442\u0430\u043c\u0438. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 <code>date-format-helper.ts<\/code><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8ea\/d12\/473\/8ead12473ddd08e3a1e6edcc351e465e.png\" alt=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u0442\u0430\u043c\u0438\" title=\"\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u0442\u0430\u043c\u0438\" width=\"1370\" height=\"532\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/8ea\/d12\/473\/8ead12473ddd08e3a1e6edcc351e465e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8ea\/d12\/473\/8ead12473ddd08e3a1e6edcc351e465e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u0442\u0430\u043c\u0438<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p> \u26a0\ufe0f <strong>\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.<\/strong><\/p>\n<p> \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d  HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 , <code>data<\/code> , <code>queryParams<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u043b\u0441\u044f \u043d\u0435 \u0441 \u043a\u043e\u0434\u043e\u043c <strong>200<\/strong>.  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e,  \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u043f\u0430\u043f\u043a\u0435 helpers \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b request-helper.ts. <\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0438\u0442\u0430\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 (\u041a\u043e\u0434 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 doRequest(&#8230;))<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432 \u043d\u0435\u043c  \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>doRequest<\/code>,  \u043a\u043e\u0442\u043e\u0440\u0430\u044f  \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434, \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442,  contentType, \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 queryBody (\u0438\u043b\u0438 params\/ form), \u0442\u043e\u043a\u0435\u043d \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u0435\u0434\u0435\u0440\u044b<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438  \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>doRequest<\/code>:  <\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438:  \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0447\u0442\u043e \u0432 \u043e\u043f\u0446\u0438\u044f\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>fetch<\/code> \u0434\u043e\u043b\u0436\u043d\u044b  \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0445\u0435\u0434\u0435\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <strong> <\/strong>(<code>options.headers<\/code>)  \u043a\u0430\u043a Authorization || ContentType \u0438 \u0442\u0430\u043a\u0436\u0435  \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c  \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u0435\u0434\u0435\u0440\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u044b: \u0412 \u043e\u043f\u0446\u0438\u044f\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0443\u0436\u043d\u043e \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a <code>POST<\/code>, <code>PUT<\/code>, <code>PATCH<\/code>, \u0442\u043e <strong>\u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0435 \u043f\u0443\u0441\u0442\u044b\u043c<\/strong> \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u0430\u043a <code>data<\/code> \/ <code>form<\/code> \/ <code>multipart<\/code> \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a <code>GET<\/code> \u0438\u043b\u0438 <code>DELETE<\/code>, \u0442\u043e <strong>\u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f<\/strong>, \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c <strong>\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/strong> (<code>params<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u044b \u0432 query-\u0441\u0442\u0440\u043e\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0439 url \u0437\u0430\u043f\u0440\u043e\u0441\u0430  \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>doRequest<\/code><\/p>\n<\/li>\n<li>\n<p>\u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 fetch, \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0433\u043e \u0432 try\/catch \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 (status) \u0438 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON<\/p>\n<\/li>\n<li>\n<p>\u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0447\u0442\u043e\u0431\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u043b\u0430 \u043a\u043e\u0434  \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0441\u0430\u043c \u043e\u0442\u0432\u0435\u0442 \u0432 json \u0432\u0438\u0434\u0435<\/p>\n<\/li>\n<li>\n<p>\u0434\u0430\u043b\u0435\u0435 \u043a\u043e\u0433\u0434\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0433\u043e\u0442\u043e\u0432\u0430   -&gt; \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0435 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438  \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c  GET \u0437\u0430\u043f\u0440\u043e\u0441 <\/p>\n<\/li>\n<\/ul>\n<pre><code>\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 import {APIRequestContext} from \"playwright\";  const HOST = 'https:\/\/example.com\/'  const queryOptions = ['params', 'form-data', 'x-www-form-urlencoded']   export async function doRequest(     request: APIRequestContext,     method: string,  \/\/ HTTP \u043c\u0435\u0442\u043e\u0434     endpoint: string, \/\/ \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430     payload: string, \/\/ \u0432\u0438\u0434 payload     lang?: string,     platform?: string,     token?: string, \/\/ \u0442\u043e\u043a\u0435\u043d     queryContent?: any, \/\/ \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b     headers?: any \/\/ \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 ) {     \/\/ \u043d\u0435 \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0438 \u043d\u0435 null\/undefined     let userToken = token &amp;&amp; token !== '' ? token : null;      const authType = 'Bearer' \/\/ \u0438\u043b\u0438 Basic \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0438 \u0442.\u043f      const options = {         method,         headers: {             'app-platform': platform,             'app-language': lang,             'accept': 'application\/json',             'Authorization': authType + ' ' + userToken,             ...headers, \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0445\u0435\u0434\u0435\u0440\u043e\u0432         },         [payload]: queryContent, \/\/ \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b     }      if (         payload === \"body\" &amp;&amp;         queryContent &amp;&amp;         [\"POST\", \"PUT\", \"PATCH\"].includes(method.toUpperCase())     ) {         options.body = JSON.stringify(queryContent);     }      if (         queryOptions.includes(payload) &amp;&amp;         [\"GET\", \"DELETE\"].includes(method.toUpperCase())     ) {         options.payload = JSON.stringify(queryContent);     }      let url = HOST + endpoint      try {         const res = await request.fetch(url, options);          return {             status: res.status(),             jsonResponse: await res.json()         };     } catch (error) {         return {             data: {                 error: \"Request failed\",                 options: options             }         };     } }   export async function doGETRequest(     request: APIRequestContext,     endpoint: string, \/\/ \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430     queryContent?: any, \/\/ \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b     lang?: string,     platform?: string,     token?: string, \/\/ \u0442\u043e\u043a\u0435\u043d     headers?: any, \/\/ \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438  ) {      return await doRequest(         request,         'GET',         endpoint,         'params',         lang,         platform,         token,         queryContent,         headers     ) }<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432  doGETRequest \u0432 \u0442\u0435\u0441\u0442\u0435:<\/p>\n<pre><code>\/\/\u0432\u044b\u0437\u043e\u0432 doGETRequest \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435  test('\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 doGETRequest', async ({ request }) =&gt; {    const response = await doGETRequest(           request,           'api\/getText',           {             'isbn': '1234',             'page': 23,           },           'ru',           'frontend',       )          \/\/console.log(await response.jsonResponse)        expect(response.status).toBe(200)     expect(await response.jsonResponse.items.length).toBeGreaterThan(0) })<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u26a0\ufe0f \u0412 \u0445\u0435\u043b\u043f\u0435\u0440\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0435<strong> \u0437\u0430\u043c\u043e\u043a\u0430\u043d\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442<\/strong> \u0438\u043b\u0438 \u0436\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043c\u043e\u043a\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \/common\/helpers\/mocks\/book-helper.ts<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b:  <a href=\"https:\/\/playwright.dev\/docs\/mock#modify-api-responses\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043e\u0444\u0444. \u0441\u0430\u0439\u0442\u0430<\/a><\/p>\n<h4>\ud83d\udccc Locators<\/h4>\n<p><strong>Locators<\/strong> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445. \u041e\u043d\u0438 \u0438\u0433\u0440\u0430\u044e\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u0443\u044e \u0440\u043e\u043b\u044c \u0432 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f UI, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u041e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 DOM (Document Object Model).<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043d\u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u043c\u0435\u043b\u043a\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0434\u0438\u0437\u0430\u0439\u043d\u0435 \u0438\u043b\u0438 \u0432\u0435\u0440\u0441\u0442\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0435\u043b\u0430\u044e\u0442 \u0442\u0435\u0441\u0442\u044b \u0431\u043e\u043b\u0435\u0435 <strong>\u043d\u0430\u0434\u0451\u0436\u043d\u044b\u043c\u0438 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c\u044b\u043c\u0438<\/strong>, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f:<\/h4>\n<ul>\n<li>\n<p>\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>kebab-case<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0443\u0444\u0444\u0438\u043a\u0441 <code><strong>-locators<\/strong><\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0431\u0443\u043a\u0432\u044b\u00a0\u2014 \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435, \u0441\u043b\u043e\u0432\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0435\u0444\u0438\u0441\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u2b50 \u041f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u0441 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435: <code>\/common\/locators\/{NAME}-locators.ts . <\/code>\u0414\u0440\u0435\u0432\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u043a\u043e\u0432 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043d\u0438\u0436\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u0440\u0435\u0432\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dfb\/c9b\/f44\/dfbc9bf446c5653c4b4c09640caa3c52.png\" alt=\"\u0414\u0440\u0435\u0432\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \" title=\"\u0414\u0440\u0435\u0432\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \" width=\"840\" height=\"378\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/dfb\/c9b\/f44\/dfbc9bf446c5653c4b4c09640caa3c52.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dfb\/c9b\/f44\/dfbc9bf446c5653c4b4c09640caa3c52.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0440\u0435\u0432\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 <\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b (\u0441\u043c.  \u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442):<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>data-test-id<\/code> \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441\u043f\u0438\u0441\u043a\u0430\u00a0<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d3d\/99c\/672\/d3d99c67295e6b2277672c85fb451396.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c data-test-id \u0438 ul \" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c data-test-id \u0438 ul \" width=\"1084\" height=\"300\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d3d\/99c\/672\/d3d99c67295e6b2277672c85fb451396.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d3d\/99c\/672\/d3d99c67295e6b2277672c85fb451396.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>data-test-id<\/code> \u0438 <code>ul<\/code> <\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 XPath  \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c  HTML \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 id<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8ee\/7de\/e19\/8ee7dee1979637e7cbb61c5594ab3f91.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c  \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430  id\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c  \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430  id\" width=\"1312\" height=\"116\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/8ee\/7de\/e19\/8ee7dee1979637e7cbb61c5594ab3f91.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8ee\/7de\/e19\/8ee7dee1979637e7cbb61c5594ab3f91.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 XPath \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c  \u0430\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u0430  id<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435  \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430 \u0442\u0435\u043c\u044b \u043f\u043e \u0435\u0435 \u0438\u043c\u0435\u043d\u0438<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f6a\/d0e\/980\/f6ad0e980d9708e569282aa2f2be8e69.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 XPath\u2011\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0442\u0435\u043c\u044b \u043f\u043e \u0435\u0451 \u0438\u043c\u0435\u043d\u0438\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 XPath\u2011\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0442\u0435\u043c\u044b \u043f\u043e \u0435\u0451 \u0438\u043c\u0435\u043d\u0438\" width=\"1300\" height=\"442\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f6a\/d0e\/980\/f6ad0e980d9708e569282aa2f2be8e69.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f6a\/d0e\/980\/f6ad0e980d9708e569282aa2f2be8e69.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 XPath\u2011\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0442\u0435\u043c\u044b \u043f\u043e \u0435\u0451 \u0438\u043c\u0435\u043d\u0438<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u2b50 \u0414\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 UI\u2011\u0442\u0435\u0441\u0442\u043e\u0432 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 <code>data-test-id<\/code> \u0438\u043b\u0438 <code>data-test<\/code>.  ( \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \ud83d\ude09, \u043d\u043e \u043b\u0443\u0447\u0448\u0435  \u0442\u0430\u043a \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c)<\/p>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e <strong>test id<\/strong> &#8212; \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u0438\u043b\u0438 \u0440\u043e\u043b\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u0441\u044f, \u0442\u0435\u0441\u0442 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c.  \u0412\u044b\u0437\u043e\u0432 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 <code>page.getByTestId()<\/code><\/p>\n<p><strong>Test-id<\/strong> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <strong>class<\/strong>, <strong>id<\/strong>, <strong>name<\/strong> \u0438\u043b\u0438 <strong>text<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438, \u043b\u0438\u0431\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0445\u0435\u0448\u0438\u0440\u0443\u0435\u043c\u044b\u0435,  <strong><em>\u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u0442\u0435\u0441\u0442\u043e\u0432<\/em><\/strong>.  (\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f <a href=\"https:\/\/bugbug.io\/blog\/software-testing\/data-testid-attributes\/\" rel=\"noopener noreferrer nofollow\">\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e ++ test-id<\/a>)<\/p>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u274c \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 <code>class, id, placeholder<\/code>\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u0442\u0435\u0441\u0442\u0430 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u0438\u043b\u0438 \u0445\u0435\u0448\u0438\u0440\u0443\u0435\u043c\u043e<code>class=\"email-123-6gdhfge77<\/code> \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0430  <code>class=\"email-123-hdvbcv<\/code><\/p>\n<\/li>\n<li>\n<p>\u274c \u041f\u043e\u0438\u0441\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043f\u043e \u0442\u0435\u043a\u0441\u0442\u0443 &#8212; \u043d\u0430\u0438\u0445\u0443\u0434\u0448\u0438\u0439 \u0432\u044b\u0431\u043e\u0440, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043a\u043e\u0434\u0435 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0435\u043a\u0441\u0442, \u043b\u0438\u0431\u043e \u0442\u0435\u0441\u0442 \u0443\u043f\u0430\u0434\u0451\u0442 \u0438\u0437\u2011\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d. \u041f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442 \u0442\u0430\u043a\u0436\u0435 \u0443\u043f\u0430\u0434\u0451\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0442\u0435\u043a\u0441\u0442\u0443 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043b\u0443\u0447\u0448\u0435 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p> \u0410 \u0432\u043e\u0442 <strong>test-id<\/strong> \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u0435\u043a\u0441\u0442\u0430, \u0441\u0442\u0438\u043b\u0435\u0439 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b DOM \u0438\u043b\u0438 \u0441\u043c\u0435\u043d\u044b \u0442\u0435\u043a\u0441\u0442\u0430. ( <strong>CSS-\u043a\u043b\u0430\u0441\u0441\u044b<\/strong> \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u044b \u0438\u043b\u0438 \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u044b , a <strong>XPath<\/strong> \u0447\u0430\u0441\u0442\u043e \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 DOM.)<\/p>\n<p>\u041f\u043e\u0438\u0441\u043a \u0447\u0435\u0440\u0435\u0437 <code>page.getByTestId()<\/code> \u043a\u043e\u0440\u043e\u0447\u0435, \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435 \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u0435\u0435, \u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 XPath \u0438\u043b\u0438 \u0446\u0435\u043f\u043e\u0447\u0435\u043a CSS, \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u0430\u0432\u043e\u043a \u043f\u0440\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0435 UI \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438.<\/p>\n<p>\u26a0\ufe0f <strong>\u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u041d\u0415 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c test-id:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043f\u043e <strong>\u043a\u043b\u0430\u0441\u0441\u0443<\/strong> \u0438\u043c\u0435\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0435\u0433\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u041f\u0440\u0438\u043c\u0435\u0440: <code>class=\"email\", id=\"email\"<\/code> \u2014  \u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445. <em>(\u041d\u043e \u043c\u0438\u043d\u0443\u0441 \u0442\u0430\u043a\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0451\u043d, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u0442\u0435\u0441\u0442\u0430.)<\/em><\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Playwright <em>&#171;the recommended built-in locators&#187;   <\/em><a href=\"https:\/\/playwright.dev\/docs\/locators#locating-elements\" rel=\"noopener noreferrer nofollow\">\u0427\u0438\u0442\u0430\u0435\u043c \u0432 \u043e\u0444\u0444 \u0434\u043e\u043a\u0435<\/a> <\/p>\n<\/li>\n<\/ul>\n<p><strong><em>\u0413\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 test-ids?<\/em><\/strong><\/p>\n<p>\u041b\u0443\u0447\u0448\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 <strong>test-id<\/strong> \u0432 \u043e\u0434\u043d\u043e\u043c \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <code> \/src\/constants\/test-ids.ts<\/code><\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 test-id : data-test-id={PROFILE.EDIT_BUTTON}, data-testid={PROFILE.EDIT_BUTTON}<\/p>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 test-id \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c <strong><em>\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c<\/em><\/strong>, \u0442\u043e \u0435\u0441\u0442\u044c <abbr class=\"habraabbr\" data-abbr=\"&quot;\u043e\u0434\u0438\u043d data-test-id   \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 &quot;\">&#171;\u043e\u0434\u0438\u043d data-test-id  \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443&#187;<\/abbr><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f test-ids \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 <\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/312\/72d\/21f\/31272d21fcff6f4b7b5534f4466d3b51.png\" alt=\" \u041f\u0440\u0438\u043c\u0435\u0440 test-ids \u0432 \/src\/constants\/test-ids.ts\" title=\" \u041f\u0440\u0438\u043c\u0435\u0440 test-ids \u0432 \/src\/constants\/test-ids.ts\" width=\"906\" height=\"298\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/312\/72d\/21f\/31272d21fcff6f4b7b5534f4466d3b51.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/312\/72d\/21f\/31272d21fcff6f4b7b5534f4466d3b51.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption> \u041f\u0440\u0438\u043c\u0435\u0440 test-ids \u0432 <code>\/src\/constants\/test-ids.ts<\/code><\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f test-id \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443<\/p>\n<pre><code>&lt;button data-test-id={PROFILE.EDIT_BUTTON}&gt;Edit Profile&lt;\/button&gt; &lt;div data-test-id={PROFILE.THEME_LIST}&gt; &lt;a data-test-id={PROFILE.SECURITY_LINK} href=\"\/profile\/security\"&gt;   ..... &lt;\/a&gt;<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f  test-id \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432 getByTestId  \u0432 PageObject || Components: <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c5\/783\/a9d\/9c5783a9dd729ab4d00421c3a185b4f7.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f test-id \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 editProfile\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f test-id \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 editProfile\" width=\"1330\" height=\"370\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/9c5\/783\/a9d\/9c5783a9dd729ab4d00421c3a185b4f7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c5\/783\/a9d\/9c5783a9dd729ab4d00421c3a185b4f7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f test-id \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 editProfile<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc ApiRoutes<\/h4>\n<h3>ApiRoutes  \u044d\u0442\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u044d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043b\u0435\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u043b\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 API \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432,  \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445.<\/h3>\n<h3>\u0424\u0430\u0439\u043b(\u044b) \u0432\u043d\u0443\u0442\u0440\u0438  \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438  \u0430piRoutes \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442(-\u0430\u0442) \u043f\u0443\u0442\u0438 \u043a API. \u041f\u0440\u0438\u0447\u0438\u043d\u044b \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0432\u0441\u0435 \u043f\u0443\u0442\u0438 API \u0445\u0440\u044f\u043d\u044f\u0442\u0441\u044f \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043e\u0442\u0432\u0435\u0434\u0435\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0441\u043b\u0435\u0434\u0443\u0449\u0438\u0435:<\/h3>\n<ul>\n<li>\n<p><em>\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438  \u043f\u0443\u0442\u0435\u0439 API \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/em> ( \u0445\u0440\u0430\u043d\u0438\u043c, \u0447\u0438\u0442\u0430\u0435\u043c \u043c\u0435\u043d\u044f\u0435\u043c \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435  \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u043f\u0443\u0442\u0438 API \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435). <\/p>\n<\/li>\n<li>\n<p><em>\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u043e\u0434 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c \u0438 \u043c\u0435\u043d\u0435\u0435 \u0441\u043a\u043b\u043e\u043d\u043d\u044b\u043c \u043a \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430\u043c <\/em>( \u043b\u0435\u0433\u0447\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 API (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>v1<\/code> \u2192 <code>v2<\/code>) \u043f\u0440\u0430\u0432\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435)<\/p>\n<\/li>\n<\/ul>\n<p> \u2757API-\u043f\u0443\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f: \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445. <\/p>\n<p> \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440  \u0433\u0434\u0435 \u0432\u0441\u0435 API \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043b\u0435\u0436\u0430\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 api-routes.ts<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 api-routes<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/**  * \u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438  *\/ export const AUTH = {   login: '\/api\/auth\/login',   restorePassword: '\/api\/auth\/restore-password', };  \/**  * \u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f  *\/ export const USER_PROFILE_SETTINGS = {   updateProfile: '\/api\/user\/profile\/update',   updateAvatar: '\/api\/user\/profile\/avatar\/update', };<\/code><\/pre>\n<\/div>\n<\/details>\n<p> \u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438\u043c\u0435\u0440  \u0433\u0434\u0435 \u0432\u0441\u0435 API \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b  \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u043e \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445. <\/p>\n<pre><code>apiRoutes\/   \u251c\u2500\u2500 authorization-routes.ts   \u251c\u2500\u2500 user-profile-routes.ts   \u2514\u2500\u2500 ...<\/code><\/pre>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u043e \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044e:<\/strong><\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0439\u0442\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0443\u0442\u044c API \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u044d\u0442\u0443 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0447\u0435\u0440\u0435\u0437 <code>export<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0438\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0438\u0437 <code>USER_PROFILE_SETTINGS<\/code><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 api \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 helpers<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { APIRequestContext, expect } from '@playwright\/test'; import {  USER_PROFILE_SETTINGS  } from '.\/common\/apiRoutes\/api-routes.ts';   export async function updateProfile(request: APIRequestContext) {   try {     const response = await request.post(       HOST + USER_PROFILE_SETTINGS.updateProfile,       {         headers: {           'Authorization': '...',           'Content-Type': '...'         },         data: {           name: '...',           \/\/ \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f         }       }     );      expect(response.status()).toBe(200);      const jsonData = await response.json();      expect(jsonData).toBeTruthy();     return jsonData;    } catch (error) {     console.error('API request failed:', error);     throw error;   } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc Components (Component Object \/ Page Component)<\/h4>\n<p>\u0427\u0430\u0441\u0442\u043e \u0431\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u2014 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0448\u0430\u043f\u043a\u0430 \u0441\u0430\u0439\u0442\u0430, \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435, \u043c\u043e\u0434\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0442. \u043f. \u042d\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438\u043b\u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e URL, \u043d\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p> \ud83d\udc49 \u0418 \u0442\u0430\u043a \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f  \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Component Object?<\/p>\n<p><strong>Component Object \/ Page Component<\/strong> &#8212; \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f Page Object.<\/p>\n<p> \u042d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u043d\u0443\u0442\u0440\u0438 PageObject.<\/p>\n<p>\u0426\u0435\u043b\u044c \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 &#8212; <strong>\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u0446\u0435\u043b\u0438\u043a\u043e\u043c (<\/strong> \u043d\u0435 \u0432 <strong>page object<\/strong>-\u0430\u0445), \u0430 \u0441 \u0435\u0451 <strong>\u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e (component object<\/strong>-\u0430\u0445), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 (\u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 URL). \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u0449\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u043b\u044e\u0431\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<p>\u2b50 <strong><em>\u041f\u0443\u0442\u044c<\/em><\/strong> \u043a \u0444\u0430\u0439\u043b\u0443 \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435: <code>\/common\/components\/{NAME}Component.ts. <\/code>\u0438\u043b\u0438<code> \/common\/components\/{componentFolder}\/{NAME}Component.ts<\/code><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0440\u0435\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441  Playwright-\u0442\u0435\u0441\u0442\u0430\u043c\u0438. <\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/13d\/903\/b19\/13d903b19b223101ec6d73d0860d6a29.png\" alt=\"\u0414\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\" title=\"\u0414\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\" width=\"1556\" height=\"530\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/13d\/903\/b19\/13d903b19b223101ec6d73d0860d6a29.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/13d\/903\/b19\/13d903b19b223101ec6d73d0860d6a29.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0434\u0440\u0435\u0432\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043b\u0451\u0433\u043a\u043e\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 <strong>page object<\/strong>-\u0430\u0445 \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u0430\u0445. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 &#8212; \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u043f\u0440\u0430\u0432\u043a\u0438 \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0430 \u043d\u0435 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445.<\/p>\n<\/div>\n<\/details>\n<p>\u2b50 <strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435  \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <\/strong>( \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b).<\/p>\n<p>\u0415\u0441\u0442\u044c 3 \u043f\u0443\u0442\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430:<\/p>\n<p> <strong>1. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0431\u0435\u0437 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>.  \u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u0430\u043a \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0439 \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e <code>Base<\/code>. <\/p>\n<p><strong><em>\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435? <\/em><\/strong><em> ( \u0440\u0430\u0441\u043a\u0440\u043e\u0439\u0442\u0435 \u0432 \u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u0433\u0434\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u043e\u0442\u043a\u0430\u0437\u0430 \u043e\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0435\u0437 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430)<\/em><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043b\u044e\u0441\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0435\u0437 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c<\/summary>\n<div class=\"spoiler__content\">\n<ol>\n<li>\n<p>\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f &#8212; \u043a\u043b\u0430\u0441\u0441-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 <code>Base<\/code>-\u043a\u043b\u0430\u0441\u0441\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0435 \u0441\u043b\u043e\u043c\u0430\u044e\u0442 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443. \u041e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0433\u0438\u0431\u043a\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0438 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c &#8212; \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0442\u0435\u043c\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043a \u043d\u0435\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u041b\u0451\u0433\u043a\u0430\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u044c &#8212; \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u043c \u0442\u0435\u0441\u0442\u0435, Page Object \u0438\u043b\u0438 Step Object \u0431\u0435\u0437 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0439 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u043d\u044c\u0448\u0435 \u0441\u043a\u0440\u044b\u0442\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u2013 \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043d\u0435\u0442 \u00ab\u043c\u0430\u0433\u0438\u0438\u00bb \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f, \u043a\u043e\u0433\u0434\u0430 \u0447\u0430\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0441\u043f\u0440\u044f\u0442\u0430\u043d\u0430 \u0432 Base.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0435\u0441\u0442\u044c \u0441\u0430\u0439\u0442 \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u043c\u0435\u043d\u044e.  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<pre><code>import {Locator, Page} from \"playwright\"; import {BASE_URL} from \"..\/config\/endpoints\";  \/**  * \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u043c\u0435\u043d\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0441\u0430\u0439\u0442\u0430  *\/ export class MenuComponent {     readonly page: Page;     readonly docs: Locator;     readonly menuButton: Locator     readonly guide: Locator      \/**      * \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440      * \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u0432(\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432) \u0443\u043a\u0430\u0437\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0443\u0442\u044c :)      *\/     constructor(page: Page) {         this.page = page;         this.menuButton = page.getByTestId('menuBurger')         this.docs = page.getByRole('link', { name: 'Docs' })         this.guide = page.getByRole('button', { name: 'Guides'})     }      \/**      * \u0420\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u043d\u044e      *\/     async expandMenu() {         await expect(this.menuButton).toBeVisible()         await expect(this.menuButton).toHaveAttribute('aria-expanded', 'false')         await this.menuButton.hover()         await this.menuButton.click()         await expect(this.menuButton).toHaveAttribute('aria-expanded', 'true')     }      \/**      * \u0412\u044b\u0431\u0435\u0440\u0430\u0435\u0442 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0441\u0435\u043a\u0446\u0438\u044e Docs      *\/     async goToDocs() {         await expect(this.docs).toBeVisible()         await this.docs.hover()         await this.docs.click()         await expect(this.page).toHaveURL(BASE_URL + '\/docs\/intro')     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p> 2) <strong>\u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440<\/strong> \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435  \u0441 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 Base. <\/p>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 <code>page<\/code> \u0438\u0437 <code>Base<\/code> (\u0433\u0434\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440) \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 -&gt; \u0438\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/p>\n<p><strong><em> \u041f\u043e\u0447\u0435\u043c\u0443  \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e  \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441? <\/em><\/strong><em> <\/em>( \u0440\u0430\u0441\u043a\u0440\u043e\u0439\u0442\u0435  \u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u0433\u0434\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u0447\u0438\u043d\u044b  \u0432\u044b\u0431\u043e\u0440\u0430 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043b\u044e\u0441\u044b \u043d\u0430\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u043b\u044e\u0441\u044b \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u0440\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 page \u0438\u0437 Base:<\/p>\n<ol>\n<li>\n<p>\u041c\u0435\u043d\u044c\u0448\u0435 \u043a\u043e\u0434\u0430 -&gt; \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 -&gt; \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0432\u0438\u0434\u043d\u044b \u043f\u0440\u044f\u043c\u043e \u0442\u0430\u043c, \u0433\u0434\u0435 \u0441 \u043d\u0438\u043c\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0440\u0430\u0431\u043e\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 -&gt; \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u00ab\u0436\u0438\u0432\u0451\u0442\u00bb \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0438 \u043d\u0435 \u0437\u0430\u0441\u043e\u0440\u044f\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u043d\u044c\u0448\u0435 \u0440\u0438\u0441\u043a\u0430 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 -&gt; \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0413\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0437\u043e\u0432\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 -&gt; \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0448\u0430\u0433, \u043d\u0435 \u0432\u043b\u0438\u044f\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0435\u0441\u0442\u044c \u0441\u0430\u0439\u0442 \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u043c\u0435\u043d\u044e.  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d  \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435,   \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430<\/p>\n<pre><code>import {Base} from \"..\/Base\"; import {expect} from \"@playwright\/test\"; import {BASE_URL} from \"..\/config\/endpoints\";  \/**  * \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u043c\u0435\u043d\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0441\u0430\u0439\u0442\u0430  *\/ export class MenuComponent extends Base {     \/**      * \u0420\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u043d\u044e      *\/     async expandMenu() {         const menuButton = this.page.getByTestId('menuBurger')          await expect(menuButton).toBeVisible()         await expect(menuButton).toHaveAttribute('aria-expanded', 'false')         await menuButton.hover()         await menuButton.click()         await expect(menuButton).toHaveAttribute('aria-expanded', 'true')     }      \/**      * \u0412\u044b\u0431\u0435\u0440\u0430\u0435\u0442 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0441\u0435\u043a\u0446\u0438\u044e Docs      *\/     async goToDocs() {         const docs = this.page.getByRole('link', { name: 'Docs' })          await expect(docs).toBeVisible()         await docs.hover()         await docs.click()         await expect(this.page).toHaveURL(BASE_URL + '\/docs\/intro')     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>3) \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 <strong>\u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441<\/strong> (\u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <code>page<\/code> \u0438 \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b) \u041d\u041e <strong>\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440<\/strong> \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.  (\u0441\u043c.\u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043b\u044e\u0441\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430: \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430  \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/summary>\n<div class=\"spoiler__content\">\n<p><strong> \u041a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? <\/strong><\/p>\n<ol>\n<li>\n<p><code>\u041a\u043b\u0430\u0441\u0441-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 <\/code>\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 Base (\u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043d\u0451\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432\u0441\u0451, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0432 Base &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e page.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u041a\u043b\u0430\u0441\u0441\u0430-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c page, \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c super(page), \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 super(page) \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 (menuButton, docs).<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u041f\u043b\u044e\u0441\u044b \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430<\/strong> (\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439) :<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043e\u0431\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b Base ( \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f,  \u0438 \u0442. \u043f.) \u0438 \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b .<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0423 \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430  \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u043e\u0438 \u043f\u043e\u043b\u044f \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f  \u0438\u0445 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435.<br \/> \u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0435\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435. \u041a\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0447\u0438\u0449\u0435, \u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443, \u0431\u0435\u0437 \u0437\u0430\u0441\u043e\u0440\u0435\u043d\u0438\u044f Base.<\/p>\n<\/li>\n<li>\n<p> C\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437.<br \/> \u041b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0430 \u043d\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 &#8212; \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<pre><code>import {Base} from \"..\/Base\"; import {expect, Page} from \"@playwright\/test\"; import {BASE_URL} from \"..\/config\/endpoints\"; import {Locator} from \"playwright\";  export class MenuComponent extends Base {     private readonly menuButton: Locator     private readonly docs: Locator      constructor(page:Page) {         super(page)         this.menuButton = this.page.getByTestId('menuBurger')         this.docs = this.page.getByRole('link', { name: 'Docs' })     }      \/**      * \u0420\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u043d\u044e      *\/     async expandMenu() {         \/\/const menuButton = this.page.getByTestId('menuBurger')          await expect(this.menuButton).toBeVisible()         await expect(this.menuButton).toHaveAttribute('aria-expanded', 'false')         await this.menuButton.hover()         await this.menuButton.click()         await expect(this.menuButton).toHaveAttribute('aria-expanded', 'true')     }      \/**      * \u0412\u044b\u0431\u0435\u0440\u0430\u0435\u0442 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0441\u0435\u043a\u0446\u0438\u044e Docs      *\/     async goToDocs() {         \/\/const docs = this.page.getByRole('link', { name: 'Docs' })          await expect(this.docs).toBeVisible()         await this.docs.hover()         await this.docs.click()         await expect(this.page).toHaveURL('https:\/\/playwright.dev\/docs\/intro');      } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432:<\/strong><\/p>\n<p>1)<strong><em> \u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435<\/em><\/strong>:  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0444\u043e\u0440\u043c\u0430\u0442 <strong>PascalCase<\/strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 <code>Component<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: HeaderComponent.ts <\/p>\n<p><abbr class=\"habraabbr\" data-abbr=\"\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 page objects \u0438 E2E-\u0442\u0435\u0441\u0442\u0430\u0445.\">\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 <\/abbr><strong><abbr class=\"habraabbr\" data-abbr=\"\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 page objects \u0438 E2E-\u0442\u0435\u0441\u0442\u0430\u0445.\">page objects<\/abbr><\/strong><abbr class=\"habraabbr\" data-abbr=\"\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 page objects \u0438 E2E-\u0442\u0435\u0441\u0442\u0430\u0445.\"> \u0438 <\/abbr><strong><abbr class=\"habraabbr\" data-abbr=\"\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 page objects \u0438 E2E-\u0442\u0435\u0441\u0442\u0430\u0445.\">E2E-\u0442\u0435\u0441\u0442\u0430\u0445<\/abbr><\/strong><abbr class=\"habraabbr\" data-abbr=\"\u041b\u0443\u0447\u0448\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445, \u0447\u0451\u0442\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0440\u0430\u0436\u0430\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u042d\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 page objects \u0438 E2E-\u0442\u0435\u0441\u0442\u0430\u0445.\">.<\/abbr><\/p>\n<p>2)<strong><em> \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/em><\/strong>: \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u0441\u0445\u043e\u0436\u0438\u0435 \u043f\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432 \u043e\u0431\u0449\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e. \u041f\u0440\u0438\u043c\u0435\u0440:  \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \/common\/components\/alerts\/ \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u0432\u0430  \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u043a <code>WarningComponent<\/code> \u0438<code> ErrorAlertComponent <\/code><\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0432 \u043a\u043e\u0442 Alert \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 Coockies<strong> <\/strong>(\u0441\u043c. \u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442) \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 page \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e Base \u043a\u043b\u0430\u0441\u0441\u0430<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0432 \u043a\u043b\u0430\u0441\u0441\u0430\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>Alert (WarningComponent) \u2014 \u043d\u0430\u0431\u043e\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f\u043c\u0438\/\u0430\u043b\u0435\u0440\u0442\u0430\u043c\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435, \u043e\u0448\u0438\u0431\u043a\u0430).<\/p>\n<\/li>\n<\/ul>\n<pre><code>\/\/ common\/components\/alerts\/WarningComponent.ts import { Page, Locator, expect } from '@playwright\/test'; import { Base } from 'common\/base\/Base'; import { CLOSE_ALERT, WARNING_ICON } from '..\/test-ids';  export class WarningComponent extends Base {   private readonly icon: Locator   private readonly closeBtn: Locator    constructor(page:Page) {       super(page)       this.icon = this.page.getByTestId(WARNING_ICON)       this.closeBtn = this.page.getByTestId(CLOSE_ALERT)   }    \/** \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u043a\u043e\u043d\u043a\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f *\/   async assertIconVisible() {     await expect(this.icon).toBeVisible();   }    \/** \u0417\u0430\u043a\u0440\u044b\u0442\u044c \u0430\u043b\u0435\u0440\u0442 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d \u0438\u0441\u0447\u0435\u0437 *\/   async dismissAlert() {     if (await this.closeBtn.isVisible()) {       await this.closeBtn.click();     }   } } <\/code><\/pre>\n<ul>\n<li>\n<p>SiteCookies \u2014 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 cookie-\u0431\u0430\u043d\u043d\u0435\u0440\u043e\u043c.<\/p>\n<\/li>\n<\/ul>\n<pre><code>\/\/ common\/components\/SiteCookiesComponent.ts import { Locator, Page, expect } from '@playwright\/test'; import { Base } from 'common\/base\/Base'; import {    ACCEPT_COOKIES_BTN,   REJECT_COOKIES_BTN,   COOKIES_BANNER  } from '..\/test-ids';  export class SiteCookiesComponent extends Base {   private readonly banner: Locator;   private readonly acceptButton: Locator;   private readonly rejectButton: Locator;    constructor(page: Page) {     super(page);     this.banner = this.page.getByTestId(COOKIES_BANNER);     this.acceptButton = this.page.getByTestId(ACCEPT_COOKIES_BTN);     this.rejectButton = this.page.getByTestId(REJECT_COOKIES_BTN);   }    \/** \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0431\u0430\u043d\u043d\u0435\u0440 \u0432\u0438\u0434\u0435\u043d *\/   async assertBannerVisible() {     await expect(this.banner).toBeVisible();   }    \/** \u041f\u0440\u0438\u043d\u044f\u0442\u044c cookies (\u0435\u0441\u043b\u0438 \u0431\u0430\u043d\u043d\u0435\u0440 \u0435\u0441\u0442\u044c) *\/   async acceptCookies() {     await expect(this.acceptButton).toBeVisible();     await this.acceptButton.click();     await this.assertBannerNotVisible();   }    \/** \u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c cookies (\u0435\u0441\u043b\u0438 \u0431\u0430\u043d\u043d\u0435\u0440 \u0435\u0441\u0442\u044c) *\/   async rejectCookies() {     await expect(this.rejectButton).toBeVisible();     await this.rejectButton.click();     await this.assertBannerNotVisible();   }    \/** \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0431\u0430\u043d\u043d\u0435\u0440 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f *\/   async assertBannerNotVisible() {     await expect(this.banner).toBeHidden();   } } <\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc Pages (Page Object Model)<\/h4>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d?<\/p>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e \u0438 \u0433\u0438\u0431\u043a\u043e\u0435 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Page Object Model (\u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b). \u042d\u0442\u043e\u0442 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044f \u0432\u0441\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<p>\u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f,  \u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0434\u0435\u043b\u0438\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043e\u0444\u043e\u0440\u043c\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. <\/p>\n<p>\u26a0\ufe0f <strong>\u0412\u0430\u0436\u043d\u043e<\/strong>!  \u041a\u0430\u043a \u043d\u0435 \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u0442\u044c \u0447\u0442\u043e \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0430 \u0447\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432  \u043f\u0435\u0439\u0434\u0436\u0435 \u0438 \u0447\u0442\u043e \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e?<\/p>\n<p>PageObject &#8212; \u044d\u0442\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<ul>\n<li>\n<p>\u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0440\u043e\u0443\u0442 (\u0447\u0430\u0441\u0442\u044c url) \u0438 \u043e\u0431\u0449\u0443\u044e \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/p>\n<\/li>\n<li>\n<p>\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: LoginPage.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421omponent &#8212; \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 UI:<\/p>\n<ul>\n<li>\n<p>\u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u043e\u0443\u0442\u0430 (url)<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0430 \u043d\u0435 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442).<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u043c\u043e\u0434\u0430\u043b\u043a\u0438, \u043f\u0430\u043d\u0435\u043b\u0438, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0445\u0435\u0434\u0435\u0440, \u0444\u043e\u0440\u043c\u0430 \u043f\u043e\u0438\u0441\u043a\u0430, \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u2757\u0412  \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0435\u0441\u0442\u044c \u043f\u0430\u043f\u043a\u0430 <strong>pages, <\/strong>\u043b\u0435\u0436\u0430\u0449\u0430\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <strong>common<\/strong>(support). <\/p>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 PageObject \u0432 \u043f\u0430\u043f\u043a\u0435 \/pages\/{PageName}Page.ts \u0438\u043b\u0438 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435 <code>.\/pages\/{feature}\/{PageName}Page.ts<\/code><\/p>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/strong><\/p>\n<p><strong>1) \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 <\/strong>PageObject \u0434\u043e\u043b\u0436\u043d\u043e <strong>\u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c<\/strong>, \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u043d \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d.<\/p>\n<p>\u0424\u043e\u0440\u043c\u0430\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 PageObject:  PageName + \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 Page<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043e \u0442\u043e\u043c \u043f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u0438\u043c\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u0432 PageObject<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u043f\u043e\u0447\u0435\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 <code>Page<\/code> \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f: \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u0438\u043c\u0435\u043d.<\/p>\n<p> \u041f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 <strong>PageObject<\/strong> \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0442\u043e \u0435\u0441\u0442\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e <code>Page<\/code> \u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 PageObject  \u041d\u0415 \u0412\u041e\u0417\u041d\u0418\u041a\u041d\u0415\u0422 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u0438\u043c\u0451\u043d.<\/p>\n<pre><code>\/\/ Pages\/LoginPage.ts export default class LoginPage { ... }  \/\/ Steps\/Login.ts export default class Login { ... }  \/\/ \u0418\u043c\u043f\u043e\u0440\u0442 import LoginPage from '..\/pages\/LoginPage'; import Login from '..\/steps\/Login'; \/\/(\u041d\u043e \u044d\u0442\u043e \u0432\u044b\u0434\u0443\u043c\u0430\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435  \/\/\u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \/\/\u0432 \u043f\u0430\u043f\u043a\u0435 common(support))  describe('Login page tests', () =&gt; {   const pageObject = new LoginPage();   const stepObject = new Login(); });<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435, \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0435\u0441\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u0438\u043c\u0435\u043d\u0435\u043c, \u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 <code>steps<\/code> \u0438\u043b\u0438 services(<code>helpers)<\/code>). <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441  PageObject  \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0447\u0442\u043e\u0431 \u043e\u043d \u043e\u0442\u0440\u0430\u0436\u0430\u043b \u043e\u0431\u0449\u0438\u0439 \u0441\u043c\u044b\u043b \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<\/div>\n<\/details>\n<p>2) <strong>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/strong> (\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430) pageObject \u0432 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>\/common\/pages.<\/code>  <\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043e\u0441\u043e\u0431\u043b\u0435\u043d\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u043c, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c  \u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0445\u043e\u0436\u0438\u0435 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u044d\u0442\u0438 \u0447\u0430\u0441\u0442\u0438 \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435 <code>\/common\/pages\/{feature}\/{PageName}Page.ts<\/code><\/p>\n<p> \u0422\u0430\u043a\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0431\u0449\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 pages.  \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435 \u043d\u0438\u0436\u0435:<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440, \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0445\u043e\u0436\u0438\u0445 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443  \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \u0432 ..\/pages<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d6b\/987\/068\/d6b9870688d4bcfa5b1bbb76208be4b7.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u0440\u0435\u0432\u0430 pageObject-\u043e\u0432 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u0440\u0435\u0432\u0430 pageObject-\u043e\u0432 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \" width=\"2034\" height=\"476\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d6b\/987\/068\/d6b9870688d4bcfa5b1bbb76208be4b7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d6b\/987\/068\/d6b9870688d4bcfa5b1bbb76208be4b7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u0440\u0435\u0432\u0430 pageObject-\u043e\u0432 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f <\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 \u043d\u0430 \u043d\u0435\u0439 \u043c\u0430\u043b\u043e \u043b\u043e\u0433\u0438\u043a\u0438  \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e  \u043c\u0435\u0442\u043e\u0434\u043e\u0432  \u043d\u0435 \u0442\u044c\u043c\u0430 \ud83d\ude42 &#8212; \u0442\u043e \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 PageObject \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \u0432 <code>\/common\/pages<\/code>  \u041f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0432 <code>\/common\/pages\/{PageName}Page.ts <\/code><\/p>\n<\/li>\n<\/ul>\n<p><strong> 3) \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u0438\u043b\u0438 \u043d\u0430\u0431\u043e\u0440\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442<\/strong>, \u0434\u043b\u044f \u043a\u0430\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 PageObjects, \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 PascalCase. <\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u043f\u043a\u0438<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: <\/p>\n<p>Authorization &#8212; \u043f\u0430\u043f\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<p>UserProfile &#8212; \u043f\u0430\u043f\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f,  \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f.<\/p>\n<\/div>\n<\/details>\n<p>\u2b50 <strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 PageObject \u0438 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <\/strong>(\u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b).<\/p>\n<p>\u0418 \u0442\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0439 \u044d\u0442\u043e \u0431\u043b\u0430-\u0431\u043b\u0430-\u0431\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 PageObject.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0440\u043d\u0438\u0446\u0430 \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439.  \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c <code><strong>ts<\/strong><\/code> \u0432 <code>\/common\/pages\/{PageName}Page.ts<\/code><\/p>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430:<\/p>\n<p> 1) \u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 PageObject \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043b\u043e\u0433\u0438\u043d\u0430 :  <code>export class LoginPage \u0432 \u043f\u0430\u043f\u043a\u0435 <\/code><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a \u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u043d\u0430 \u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u043e \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u0443 \u043d\u0430 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 Common \u0432  \/common\/base\/Base.ts \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440. <\/p>\n<p>\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c  <code>export class LoginPage extends Base<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>UserProfilePage<\/code>. <\/p>\n<p>\u041d\u043e \u0432\u043e\u0442 \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0432 \u043a\u043b\u0430\u0441\u0441 <code>PageObject<\/code>, \u0435\u0441\u043b\u0438 \u0432 <code>Base<\/code> \u043e\u043d \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d? \ud83e\udd14 <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441:<\/p>\n<p>1-\u0432\u0430\u0440\u0438\u0430\u043d\u0442) \u0415\u0441\u043b\u0438 \u0432 <code>PageObject<\/code>  \u041d\u0415 \u041d\u0423\u0416\u041d\u041e \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c -&gt; \u0442\u0430\u043a \u043a\u0430\u043a,  \u043e\u043d \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u0431\u0430\u0437\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 <code>Base<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 <code>page<\/code> \u0438\u0437 \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p>2-\u0432\u0430\u0440\u0438\u0430\u043d\u0442) \u0415\u0441\u043b\u0438 \u0432 <code>PageObject<\/code> \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <strong>\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e<\/strong> \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c. \u041f\u0440\u0438\u043c\u0435\u0440: <a href=\"https:\/\/playwright.dev\/docs\/pom\" rel=\"noopener noreferrer nofollow\"> \u043e\u0444\u0444. \u043f\u0440\u0438\u043c\u0435\u0440<\/a><\/p>\n<p>3-\u0432\u0430\u0440\u0438\u0430\u043d\u0442) \u041c\u043e\u0436\u043d\u043e  \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0432 \u043a\u043b\u0430\u0441\u0441  \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 (\u0442\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c 1 \u0438 2 \u043f\u043e\u0434\u0445\u043e\u0434)<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 pageObject, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430  \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 ( 3 &#8212; \u0432\u0430\u0440\u0438\u0430\u043d\u0442)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/common\/pages\/LoginPage.ts import { Page, expect, Locator } from '@playwright\/test'; import {Base} from \"..\/Base\"; import {BASE_URL} from \"..\/config\/endpoints\";  export class LoginPage extends Base {     readonly usernameInput: Locator     readonly passwordInput: Locator     readonly submitButton: Locator      constructor(page: Page) {         super(page);         this.usernameInput = this.page.getByTestId('login-username');         this.passwordInput = this.page.getByTestId('login-password');         this.submitButton = this.page.getByTestId('login-submit');     }      async open() {         const loginUrl = BASE_URL + '\/login'          await this.page.goto(BASE_URL + '\/login');         await expect(this.page).toHaveURL(loginUrl)     }      async fillUsername(username: string) {         await expect(this.usernameInput).toHaveValue('')         await this.usernameInput.fill(username);     }      async fillPassword(password: string) {         await expect(this.passwordInput).toHaveValue('')         await this.passwordInput.fill(password);     }      async submit() {         await expect(this.submitButton).toBeEnabled()         await this.submitButton.click();     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u26a0\ufe0f <strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438  \u043a\u043b\u0430\u0441\u0441\u0430 PageObject:<\/strong><\/p>\n<p>1)<em> <\/em><strong><em>\u041b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b<\/em><\/strong><em>.<\/em> \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 PageObject \u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u043d\u044b\u043c\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438. \u0422\u043e \u0435\u0441\u0442\u044c, \u0441\u0430\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0435 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u043f\u0430\u043f\u043a\u0435 <code>\/constants<\/code> \u0434\u043b\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 , <code>\/locators<\/code> \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 <\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<code>const loginButton = page.getByRole(ROLES.button, { name: buttonName })<\/code><\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u0432 PageObject  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0435 \u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 &#8212; \u0442\u043e \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0435 \u0432  \u0444\u0430\u0439\u043b \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438  \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0432 \u043c\u0435\u0442\u043e\u0434 PageObject  \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u0445.<\/p>\n<pre><code>\/\/ \u043c\u0435\u0442\u043e\u0434 \u0432 LoginPage.ts async clickLoginButton(buttonName: string) {    const loginButton = page.getByRole(ROLES.button,       { name: buttonName })    ..... }  \/\/ \u0441\u0430\u043c \u0442\u0435\u0441\u0442 import { BUTTONS }from '\/common\/constants\/element-constants.ts'  test('\u041b\u043e\u0433\u0438\u043d...', async ({ page }) =&gt; {   const loginPage = new LoginPage(page);    .....    await loginPage.clickLoginButton(BUTTONS.submit);    await expect(page).toHaveURL(EXPECTED_URL); });<\/code><\/pre>\n<\/div>\n<\/details>\n<p>2) <strong><em>\u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0438 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.<\/em><\/strong> \u041d\u0435 \u043f\u0438\u0448\u0438\u0442\u0435 \u00ab\u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u0435\u00bb \u043c\u0435\u0442\u043e\u0434\u044b, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u0414\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043d\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. \u042d\u0442\u043e \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>async fillPassword(password: string)<\/code> &#8212; \u2705, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0434\u043d\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u0410 \u0432\u043e\u0442 <code>async fillCredsAndSubmit(password: string, email: string, buttonName: string)<\/code> &#8212; \u274c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u0432 \u0444\u043e\u0440\u043c\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. <\/p>\n<p>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u0437 PageObject \u043c\u043e\u0436\u043d\u043e \u0432 StepObject, \u0435\u0441\u043b\u0438 \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0430.<\/p>\n<\/div>\n<\/details>\n<p>3)<strong><em> \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438. <\/em><\/strong>\u041f\u0435\u0440\u0435\u0434 \u043b\u044e\u0431\u044b\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u043c (\u043a\u043b\u0438\u043a, \u0432\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0442.\u043f.) \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <strong>\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0438 \u0432\u0438\u0434\u0438\u043c, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0439 <\/strong>(toBeVisible, toBeEditable, toBeEnabled). \u042d\u0442\u043e \u0441\u043d\u0438\u0437\u0438\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. <\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f, \u0437\u0430\u0442\u0435\u043c \u043a\u043b\u0438\u043a\u0430\u0435\u043c<br \/> const submitButton = page.locator(&#8216;button.submit&#8217;);<br \/> await expect(submitButton).toBeVisible();<br \/> await <a href=\"http:\/\/submitButton.click\" rel=\"noopener noreferrer nofollow\">submitButton.click<\/a>();<\/p>\n<p>\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c<br \/> const textField = page.getByRole(&#8216;textbox&#8217;);<br \/> await expect(textField).toBeEditable();<br \/> await textField.fill(&#8216;\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435&#8217;);<\/p>\n<p>\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0430, \u0437\u0430\u0442\u0435\u043c \u043a\u043b\u0438\u043a\u0430\u0435\u043c<br \/> const enabledButton = page.locator(&#8216;button.submit&#8217;);<br \/> await expect(enabledButton).toBeEnabled();<br \/> await <a href=\"http:\/\/enabledButton.click\" rel=\"noopener noreferrer nofollow\">enabledButton.click<\/a>();<\/p>\n<\/div>\n<\/details>\n<p>4) <strong>\u041f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/strong> \u041c\u0435\u0442\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u0443\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0442\u043e \u0435\u0441\u0442\u044c \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043e\u043d \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d. \u041f\u0440\u0438\u043c\u0435\u0440: <code>clickLoginButton()<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>clickButton()<\/code>.<\/p>\n<p>5) <strong>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/strong>. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 <strong>docstring <\/strong> \u043a  \u043c\u0435\u0442\u043e\u0434\u0430\u043c , \u043f\u043e\u044f\u0441\u043d\u044f\u044e\u0449\u0438\u0439  <strong><em>&#171;\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434&#187;<\/em><\/strong><\/p>\n<p>6) <strong>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438. <\/strong>\u0418\u0437\u0431\u0435\u0433\u0430\u0439\u0442\u0435 \u043f\u043e\u0438\u0441\u043a\u0430 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043f\u043e \u0442\u0435\u043a\u0441\u0442\u0443. \u0415\u0441\u043b\u0438 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f,  \u0442\u043e -&gt; <strong>\u041d\u0415 \u0425\u0410\u0420\u0414\u041a\u041e\u0414\u042c\u0422\u0415 \u0442\u0435\u043a\u0441\u0442<\/strong> \u043f\u0440\u044f\u043c\u043e \u0432 PageObject &#8212; \u274c, \u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434 <strong>\u0447\u0435\u0440\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 &#8212; <\/strong>\u2705<strong>.<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/ \u0441\u0430\u043c \u0442\u0435\u0441\u0442 import { BUTTONS }from '\/common\/constants\/element-constants.ts'  test('\u041b\u043e\u0433\u0438\u043d...', async ({ page }) =&gt; {   const loginPage = new LoginPage(page);    .....    await loginPage.clickLoginButton(eBUTTONS.submit);    await expect(page).toHaveURL(EXPECTED_URL); });<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0441\u0445\u043e\u0436\u0438\u0445 PageObject<\/p>\n<\/div>\n<\/details>\n<p>7)<strong> \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0441\u0445\u043e\u0436\u0438\u0445 PageObjects<\/strong>. \u041d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 (\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0438\u043b\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439). \u041b\u0443\u0447\u0448\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 PageObject \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>\/\/ LoginPage.ts export class LoginPage {  ......   async fillPassword(password: string) {     await expect(this.passwordField).toBeVisible();     await this.passwordField.fill(password);   }    async restorePassword() {     await expect(this.restoreButton).toBeEnabled();     await this.restoreButton.click();     return new RestorePasswordPage(this.page); \/\/ -&gt; \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c       \/\/ \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u0430\u0440\u043e\u043b\u044f     \/\/ \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 PageObject \u0432 RestorePasswordPage   } }  ...... \/\/ RestorePasswordPage.ts export class RestorePasswordPage {  ....   async enterRestoreCode(code: string) {     await expect(this.codeField).toBeVisible();     await this.codeField.fill(code);   } .... } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>8) \u041d\u0435 \u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>PageObject. <\/strong><\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <code>static<\/code> \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 PageObject. \u041a\u0430\u0436\u0434\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 <strong>\u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c<\/strong>, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0449\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c. <\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e:<\/p>\n<pre><code>\/\/ LoginPage.ts export class LoginPage {    ....    static async fillEmail(page: Page, email: string) {     await page.fill(this.emailField, email);   }    static async fillPassword(page: Page, password: string) {     await page.fill(this.passwordField, password);   } }  \/\/ \u0441\u0430\u043c \u0442\u0435\u0441\u0442, \/\/\u0433\u0434\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c page. \/\/ PageObject \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b test('\u041b\u043e\u0433\u0438\u043d \u0447\u0435\u0440\u0435\u0437 static \u043c\u0435\u0442\u043e\u0434\u044b', async ({ page }) =&gt; {   await LoginPage.fillEmail(page, 'test@example.com');   await LoginPage.fillPassword(page, '123456'); }); <\/code><\/pre>\n<p> \u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e:<\/p>\n<pre><code>\/\/ LoginPage.ts export class LoginPage {   ....    async fillEmail(email: string) {     await this.emailField.fill(email);   }    async fillPassword(password: string) {     await this.passwordField.fill(password);   } }  \/\/ \u0441\u0430\u043c \u0442\u0435\u0441\u0442 \/\/ \u0433\u0434\u0435 page \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435,  \/\/ \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 test('\u041b\u043e\u0433\u0438\u043d', async ({ page }) =&gt; {   const loginPage = new LoginPage(page);    await loginPage.fillEmail('test@example.com');   await loginPage.fillPassword('123456'); }); <\/code><\/pre>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u0438\u043b\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440), \u0437\u043d\u0430\u0447\u0438\u0442 \u043e\u043d \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442  \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043f\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0443:<\/p>\n<pre><code>\/\/ \u274c \u041f\u043b\u043e\u0445\u043e - \u0432 PageObject static getButtonByName(name: string) {   return 'button[name=\"${name}\"]''; }<\/code><\/pre>\n<pre><code>\/\/ \u2705 \u0425\u043e\u0440\u043e\u0448\u043e \u2014 \u0432 locators\/commonLocators.ts export function getButtonByName(name: string) {   return 'button[name=\"${name}\"]''; }<\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\ud83d\udccc Step pattern<\/h4>\n<p>(\u043d\u0435 \u043f\u0443\u0442\u0430\u0442\u044c \u0441 <code>test.step<\/code> \u0432 Playwright)<\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0448\u0430\u0433\u043e\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,  \u0434\u043b\u044f  e2e  \u0438\u043b\u0438 API \u0442\u0435\u0441\u0442\u0430  &#8212; \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f  \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432 <\/p>\n<ul>\n<li>\n<p><strong>API: <\/strong>\u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430: \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u0432\u0430\u0440\u0430 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443  -&gt; \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u043f\u043b\u0430\u0442\u044b -&gt; \u0434\u0430\u043b\u0435\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043e\u043f\u043b\u0430\u0442\u044b -&gt; \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0437\u0430\u043a\u0430\u0437\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>E2E: <\/strong>\u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430 &#8212; \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u043e\u0432\u0430\u0440 \u0438 \u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0443, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u043f\u043b\u0430\u0442\u044b, \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0435\u043c \u043e\u043f\u043b\u0430\u0442\u0443 \u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0430\u0437\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432  \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0430, \u0435\u0451 \u0441\u0442\u043e\u0438\u0442 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 step pattern (\u0448\u0430\u0433\u0438), \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0438 \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c.<\/p>\n<p>\u2757Step pattern<strong>  <\/strong>\u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442<strong>:<\/strong><\/p>\n<ul>\n<li>\n<p>\u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \/ \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: &#8216;\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f&#8217;, &#8216;\u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430&#8217;) \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 1 \u0440\u0430\u0437\u0430<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0441\u043b\u0435\u0434\u0443\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 DRY.<\/p>\n<\/li>\n<\/ul>\n<p>\u2757<em>\u041a\u043e\u0433\u0434\u0430  \u043d\u0443\u0436\u0435\u043d \u0441\u0442\u0435\u043f?<\/em><strong> <\/strong>&#8212; \u0442\u043e\u0433\u0434\u0430 \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 1 \u0440\u0430\u0437\u0430 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/p>\n<p>\u0426\u0435\u043b\u044c \u2014 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e\u0439 \u0436\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0430.<\/p>\n<p><strong>\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u043e \u0441\u0442\u0435\u043f\u0430\u043c\u0438<\/strong><\/p>\n<ul>\n<li>\n<p>\u0424\u0430\u0439\u043b \u0441\u043e \u0441\u0442\u0435\u043f\u0430\u043c\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <strong>kebab-case<\/strong>: \u0432\u0441\u0435 \u0431\u0443\u043a\u0432\u044b \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435, \u0441\u043b\u043e\u0432\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0435\u0444\u0438\u0441\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 <code><strong>step<\/strong><\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c\/\u0444\u0438\u0447\u0443, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0448\u0430\u0433\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<p><code>order-step.ts<\/code> &#8212; \u044d\u0442\u043e  \u0444\u0430\u0439\u043b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439  \u0441\u0442\u0435\u043f\u044b \u0434\u043b\u044f \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430<\/p>\n<\/div>\n<\/details>\n<p><strong>\u0413\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0442\u0435\u043f\u044b?<\/strong> &#8212;  \u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b  \u0441\u0442\u0435\u043f\u0430\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 common\/steps\/ <\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043b\u043a\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 -&gt; \u0422\u041e \u0440\u0430\u0437\u0431\u0435\u0439\u0442\u0435 \u0435\u0451 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u043e \u0441\u0442\u0435\u043f\u0430\u043c\u0438.<\/p>\n<p>\u041f\u0443\u0442\u044c:<code> \/common\/steps\/e2e(api)\/{feautureFolder}\/{feautureName}-step.ts<\/code>-&gt; \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u043e \u0441\u0442\u0435\u043f\u0430\u043c\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0438\u0447\u0435. <\/p>\n<p>\u0412\u0441\u0435 \u0442\u0430\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 <strong>\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435<\/strong>, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 (<strong>{featureFolder}<\/strong>) \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 <strong>steps\/e2e<\/strong> \u0438\u043b\u0438 <strong>steps\/api<\/strong> (\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0442\u0435\u0441\u0442\u043e\u0432).<\/p>\n<\/li>\n<\/ul>\n<div class=\"floating-image\">\n<figure class=\"float full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cfe\/4a5\/492\/cfe4a5492d2f8433450adb242a10be2b.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u0442\u0435\u043f\u044b \u0438 \u0434\u043b\u044f UI \u0438 \u0434\u043b\u044f   API \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0435\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u0442\u0435\u043f\u044b \u0438 \u0434\u043b\u044f UI \u0438 \u0434\u043b\u044f   API \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0435\" width=\"766\" height=\"558\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cfe\/4a5\/492\/cfe4a5492d2f8433450adb242a10be2b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cfe\/4a5\/492\/cfe4a5492d2f8433450adb242a10be2b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u0442\u0435\u043f\u044b \u0438 \u0434\u043b\u044f UI \u0438 \u0434\u043b\u044f API \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0435<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,  \u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 (\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f)  \u0435\u0441\u0442\u044c \u0448\u0430\u0433\u0438 \u043a\u0430\u043a \u0434\u043b\u044f UI, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f API, \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435 \u0438\u0445 \u043f\u043e \u0442\u0438\u043f\u0430\u043c \u0442\u0435\u0441\u0442\u043e\u0432: \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0444\u0430\u0439\u043b\u044b \u0441\u043e \u0441\u0442\u0435\u043f\u0430\u043c\u0438 \u0438 \u0432 steps\/e2e, \u0438 \u0432 steps\/api, \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<\/div>\n<div class=\"floating-image\">\n<figure class=\"float bordered full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/af7\/ec8\/2ba\/af7ec82ba62c7213dfb216b83761cb58.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430  \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e UI \u0438\u043b\u0438 \u0436\u0435 \u0442\u043e\u043b\u044c\u043a\u043e API \u0441\u0442\u0435\u043f\u044b\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430  \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e UI \u0438\u043b\u0438 \u0436\u0435 \u0442\u043e\u043b\u044c\u043a\u043e API \u0441\u0442\u0435\u043f\u044b\" width=\"870\" height=\"468\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/af7\/ec8\/2ba\/af7ec82ba62c7213dfb216b83761cb58.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/af7\/ec8\/2ba\/af7ec82ba62c7213dfb216b83761cb58.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430  \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e UI \u0438\u043b\u0438 \u0436\u0435 \u0442\u043e\u043b\u044c\u043a\u043e API \u0441\u0442\u0435\u043f\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u0410 \u0435\u0441\u043b\u0438  \u0441\u0442\u0435\u043f\u044b \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u0439 \u0444\u0438\u0447\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043d\u0435\u0441\u0442\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043a UI \u0438\u043b\u0438 API \u0442\u043e \u0438  \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0438\u0445 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0430\u043c, \u0433\u0434\u0435 \u0438\u043c \u043c\u0435\u0441\u0442<\/p>\n<\/div>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0441\u0442\u0435\u043f\u044b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0438\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b, \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443. \u041a\u043b\u0430\u0434\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u043f\u0440\u044f\u043c\u043e \u0432 steps\/api \u0438\u043b\u0438 steps\/e2e \u0438 \u043d\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u0432 kebab-case \u0441 \u0441\u0443\u0444\u0444\u0438\u043a\u0441\u043e\u043c <code>-step.ts.<\/code><\/p>\n<p>\u041f\u0443\u0442\u044c:<code>\/common\/steps\/e2e (api) \/{feautureName}-step.ts<\/code><\/p>\n<\/li>\n<\/ul>\n<div class=\"floating-image\">\n<figure class=\"float full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/37b\/691\/011\/37b691011f79ed7b414c734557ac4b42.png\" alt=\" \u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043f\u043e\u0432 \u043f\u043e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0430\u043c (\u0444\u0438\u0447\u0430\u043c)\" title=\" \u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043f\u043e\u0432 \u043f\u043e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0430\u043c (\u0444\u0438\u0447\u0430\u043c)\" width=\"654\" height=\"348\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/37b\/691\/011\/37b691011f79ed7b414c734557ac4b42.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/37b\/691\/011\/37b691011f79ed7b414c734557ac4b42.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption> \u041f\u0440\u0438\u043c\u0435\u0440  \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043f\u043e\u0432 \u043f\u043e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0430\u043c (\u0444\u0438\u0447\u0430\u043c)<\/figcaption><\/div>\n<\/figure>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,   \u0441\u0442\u0435\u043f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\u0438   \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b  auth-step   \u0432 \/common\/steps\/e2e (api)\/feature-step.ts<\/p>\n<\/div>\n<\/div>\n<\/details>\n<p>\u26a0\ufe0f \u0412 \u043c\u043e\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445  &#8212; \u0441\u0442\u0435\u043f\u044b \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430, \u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0447\u0442\u043e \u043b\u0438\u0431\u043e)  <\/p>\n<p>\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0441\u0442\u0435\u043f\u044b \u0434\u043b\u044f e2e (UI) \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432? \ud83d\udc47<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0442\u0435\u043f\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u0440\u0435\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u043a\u0435\u0439\u0441\u0430 \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0443 &#8212; \u043a\u0430\u043a \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043a\u0430\u0437:<\/p>\n<p>\u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442 1: \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430<\/p>\n<p>\u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442 -2: \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0436\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043a\u0430\u0437\u0430<\/p>\n<p>\u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442-3:  \u043e\u0442\u043c\u0435\u043d\u0430 \u0437\u0430\u043a\u0430\u0437\u0430<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c &#8216;\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u043a\u0430\u0437&#8217; \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0448\u0430\u0433\u0430\u043c\u0438, \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\/\u043e\u0442\u043c\u0435\u043d\u0443  -&gt;  \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0435\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432 \u0432 \u0441\u0442\u0435\u043f\u044b \u0438 \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c  \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0442\u0435\u043f \u0432 3 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e order.step.ts<\/p>\n<pre><code>\/ \/\/common\/steps\/e2e\/order-step.ts  import { ProductPage } from \"common\/pages\/ProductPage\"; import { BasketPage } from \"common\/pages\/BasketPage\"; import { OrderPage } from \"common\/pages\/OrderPage\";   export async function createOrderViaUI(     page: Page,     productId: number,     deliveryType: string,     address: string,     expectedOrderStatus: string,     paymentType: string,     card?: CardData ) {     const productPage = new ProductPage(page);     const basketPage  = new BasketPage(page);     const orderPage   = new OrderPage(page);      \/\/ 1) \u0422\u043e\u0432\u0430\u0440 \u2192 \u043a\u043e\u0440\u0437\u0438\u043d\u0430     await page.goto(`\/product\/${productId}`);     await productPage.addProductToBasket();      await basketPage.goToBasket();     await basketPage.ensureProductIsInBasket(productId);     await basketPage.buyProductByClick(productId);      \/\/ 2) \u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435     await orderPage.ensureOrderDetailsAreShownFor(productId);      const orderId = await orderPage.getOrderId();     expect(orderId, 'orderId \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f').toBeTruthy();      await orderPage.selectDelivery(deliveryType);     await orderPage.fillAddressToDeliver(address);     await orderPage.selectPaymentType(paymentType);      \/\/ 3) \u041e\u043f\u043b\u0430\u0442\u0430     if (paymentType === 'card') {         if (!card || !card.cardNumber || !card.cardHolder || !card.cardExpire || !card.cardCvv) {             throw new Error(                 '\u0414\u043b\u044f \u043e\u043f\u043b\u0430\u0442\u044b \u043a\u0430\u0440\u0442\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c card: { cardNumber, cardHolder, cardExpire, cardCvv }'             );         }         const cardComp = new CardComponent(page);         await cardComp.fillCardNumber(card.cardNumber);         await cardComp.fillCardHolder(card.cardHolder);         await cardComp.fillCardExpireDate(card.cardExpire);         await cardComp.fillCardCvv(card.cardCvv);         await cardComp.acceptPayment();     } else {         await orderPage.payWithAlternative(paymentType);     }      \/\/ 4) \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430     await orderPage.ensureOrderIsPaid(orderId);      const status = await orderPage.getOrderStatus(orderId);         await expect(status).toMatch(expectedOrderStatus);      return { orderId, status }; }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a  \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u0441\u0442\u0435\u043f \u0432  3 -\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u043f\u0430 \u0438\u0437 order-step.ts \u0432 \u0442\u0440\u0435\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0414\u0430\u043b\u0435\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a  \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u0441\u0442\u0435\u043f \u0432  3 -\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code>\/\/ \/tests\/e2e\/EditOrder.spec.ts import { test } from '@playwright\/test'; import { createOrderViaUI } from '..\/..\/common\/steps\/e2e\/order-step';  test('\u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430', async ({ page }) =&gt; {  const orderPage = new OrderPage(page)    \/\/ 1) \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0437\u0430\u043a\u0430\u0437 (\u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0448\u0430\u0433)   const { orderId } = await createOrderViaUI(     page,     123,                       \/\/ productId     'courier',                 \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438     'Almaty, Main 1, 050000',  \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441     'card',                    \/\/ \u043e\u043f\u043b\u0430\u0442\u0430 \u043a\u0430\u0440\u0442\u043e\u0439 (\u0434\u043b\u044f \"\u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e\"   \u0441\u0442\u0430\u0442\u0443\u0441\u0430)     {       cardNumber: CARD_NUMBER.visa,       cardHolder: CARD_NUMBER.holder,       cardExpire: CARD_NUMBER.expireDate,       cardCvv: CARD_NUMBER.cvv,     }   ); }); <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code>\/\/ \/tests\/e2e\/EditOrder.spec.ts import { test } from '@playwright\/test'; import { createOrderViaUI } from '..\/..\/common\/steps\/e2e\/order-step'; import {    editOrderDelivery,   editDeliveryAddress,   assertOrderDeliveryChanged,   assertDeliveryAddressChanged } from '..\/..\/common\/pages\/OrderPage.ts';  test('\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043a\u0430\u0437\u0430.      \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438', async ({ page }) =&gt; {  const orderPage = new OrderPage(page)    \/\/ 1) \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0437\u0430\u043a\u0430\u0437 (\u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0448\u0430\u0433)   const { orderId } = await createOrderViaUI(     page,     123,                       \/\/ productId     'courier',                 \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438     'Almaty, Main 1, 050000',  \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441     'card',                    \/\/ \u043e\u043f\u043b\u0430\u0442\u0430 \u043a\u0430\u0440\u0442\u043e\u0439 (\u0434\u043b\u044f \"\u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e\" \u0441\u0442\u0430\u0442\u0443\u0441\u0430)     {       cardNumber: CARD_NUMBER.visa,       cardHolder: CARD_NUMBER.holder,       cardExpire: CARD_NUMBER.expireDate,       cardCvv: CARD_NUMBER.cvv,     }   );    \/\/ 2) \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u043e\u0441\u043e\u0431 \u0438 \u0430\u0434\u0440\u0435\u0441 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438   const newDeliveryType = DELIVERY_TYPES.pickup   const newAddress = 'Almaty, Pickup Point #3'      await orderPage.editOrderDelivery(orderId, newDeliveryType);   await orderPage.editDeliveryAddress(orderId, newAddress);    \/\/ 3) \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0438 \u0430\u0434\u0440\u0435\u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d    await orderPage.assertOrderDeliveryChanged(newDeliveryType)   await orderPage.assertDeliveryAddressChanged(newAddress) }); <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u043d\u0430 \u043e\u0442\u043c\u0435\u043d\u0443 \u0437\u0430\u043a\u0430\u0437\u0430:<\/p>\n<pre><code>\/\/ \/tests\/e2e\/EditOrder.spec.ts import { test } from '@playwright\/test'; import { createOrderViaUI } from '..\/..\/common\/steps\/e2e\/order-step';  test('\u041e\u0442\u043c\u0435\u043d\u0430 \u0437\u0430\u043a\u0430\u0437\u0430', async ({ page }) =&gt; {  const orderPage = new OrderPage(page)    \/\/ 1) \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0437\u0430\u043a\u0430\u0437 (\u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0448\u0430\u0433)   const { orderId } = await createOrderViaUI(     page,     123,                       \/\/ productId     'courier',                 \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438     'Almaty, Main 1, 050000',  \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441     'card',                    \/\/ \u043e\u043f\u043b\u0430\u0442\u0430 \u043a\u0430\u0440\u0442\u043e\u0439 (\u0434\u043b\u044f \"\u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e\"   \u0441\u0442\u0430\u0442\u0443\u0441\u0430)     {       cardNumber: CARD_NUMBER.visa,       cardHolder: CARD_NUMBER.holder,       cardExpire: CARD_NUMBER.expireDate,       cardCvv: CARD_NUMBER.cvv,     }   );  \/\/ 2) \u041e\u0442\u043c\u0435\u043d\u044f\u0435\u043c \u0437\u0430\u043a\u0430\u0437    orderPage.cancelOrder(orderId)    \/\/ 3) \u0423\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f \u0447\u0442\u043e \u0437\u0430\u043a\u0430\u0437 \u043e\u0442\u043c\u0435\u043d\u0435\u043d    .....     }); <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0441\u0442\u0435\u043f\u044b \u0434\u043b\u044f API \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432? \ud83d\udc47<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u0435\u0439\u0441\u0430 <\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u0438\u043c\u0435\u0440:  \u041a\u0435\u0439\u0441 1:  \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441 \u043f\u0430\u0440\u043e\u043b\u0435\u043c \u0438 \u0438\u043c\u0435\u0439\u043b\u043e\u043c  &amp;&amp;  \u041a\u0435\u0439\u0441 -2: \u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 API-\u0442\u0435\u0441\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0448\u0430\u0433\u0438,  \u0433\u0434\u0435 1-2 \u0448\u0430\u0433  \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0442\u0441\u044f  \u0434\u043b\u044f  1 \u0438 2 \u043a\u0435\u0439\u0441\u0430:<\/p>\n<p> 1) \u0432\u0432\u043e\u0434 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f  \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0430 \u043a\u0440\u0435\u0434\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0435\u0440\u043d\u044b \u043b\u0438 \u043e\u043d\u0438<\/p>\n<p> 2) \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u043d\u044b \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u043e\u0442\u0432\u0435\u0442 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0442\u043e  \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0442 \u0447\u0442\u043e  \u043a\u0440\u0435\u0434\u044b (\u0438\u043c\u0435\u0439\u043b \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435\u0432\u0435\u0440\u043d\u044b)<\/p>\n<p>3) \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433: \u044d\u0442\u043e \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043c\u0435\u0439\u043b\u0430 \u0438\u043b\u0438 \u043d\u043e\u043c\u0435\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430<\/p>\n<p>4) \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f  \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430  \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0430 \u0438\u043c\u0435\u0439\u043b \u0438\u043b\u0438  \u0432 \u0441\u043c\u0441,   \u0433\u0434\u0435 \u0432  queryParametrers \u0431\u0443\u0434\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u0438\u0431\u043e  \u043d\u043e\u043c\u0435\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u043b\u0438\u0431\u043e \u0438\u043c\u0435\u0439\u043b\u0430<\/p>\n<p>5) \u0434\u0430\u043b\u0435\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0440\u0435\u0442\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441,  \u0433\u0434\u0435 \u0432  queryParametrers \u0431\u0443\u0434\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     \u043a\u043e\u0434\u0430 \u0432\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f<\/p>\n<p>6) \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d  &#8212; \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u043e\u043b\u044f, \u0433\u0434\u0435 \u0432  queryParametrers \u0431\u0443\u0434\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435  \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<p>7) \u0435\u0441\u043b\u0438 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u0435\u0440\u043d\u0443\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 -&gt;  \u0442\u043e \u0437\u0430\u043d\u043e\u0432\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043d\u043e \u0443\u0436\u0435 \u0441 \u043d\u043e\u0432\u044b\u043c \u043f\u0430\u0440\u043e\u043b\u0435\u043c<\/p>\n<p> \u0422\u0430\u043a \u0432\u043e\u0442,  \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0448\u0430\u0433\u043e\u0432  1-2  \u0438  7  \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443,  \u0432 \u043e\u0431\u043e\u0438\u0445 \u043a\u0435\u0439\u0441\u0430\u0445  -&gt;  \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 1, 2 ,7 \u0448\u0430\u0433\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0435\u043f \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f API ,   \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438  \u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u043e\u0442\u0432\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0442\u044c  \u043a\u043e\u0434 \u0438 \u0442\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0440\u0438\u0441\u043f\u043e\u043d\u0437, \u0430 \u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u043b\u043e\u0433\u0438\u043d\u0435  \u043e\u0442\u0432\u0435\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439  \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0435\u0441\u043b\u0438 \u0438 \u0438\u043c\u0435\u0439\u043b \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u0435\u0440\u043d\u044b \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d<\/p>\n<\/div>\n<\/details>\n<p>\ud83d\udccc <strong>Config <\/strong><\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u0430 \u043e \u0432\u0438\u0434\u0430\u0445 \u043e\u0442\u0447\u0435\u0442\u043e\u0432 \u0438  \u0438\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0432 \u043c\u0435\u0441\u0435\u043d\u0434\u0436\u0435\u0440, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0447\u0442\u043e \u0437\u0430 \u043f\u0430\u043f\u043a\u0430 \u0432 \u0432 \u0442\u0435\u0441\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 <strong>screenshots<\/strong><\/p>\n<p><strong>1) playwright.config &#8212; \u044d\u0442\u043e <\/strong>\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0433\u0434\u0435 \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p><strong> <\/strong>\u0427\u0442\u043e \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b?<\/p>\n<p><em>\u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0435\u0440\u0435\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0443\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u0430 \u043e\u0442\u043c\u0435\u0447\u0443 \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043e\u043f\u0446\u0438\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0430 \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0438\u0441\u044c \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435)))<\/em><\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438\u0437 \u043e\u0444\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0435:  <a href=\"https:\/\/playwright.dev\/docs\/test-configuration\" rel=\"noopener noreferrer nofollow\">\u041e\u0431\u0449\u0430\u044f \u0438\u043d\u0444\u0430 \u043f\u043e playwright.config<\/a>,  <a href=\"https:\/\/playwright.dev\/docs\/test-use-options\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438<\/a>,  <a href=\"https:\/\/playwright.dev\/docs\/api\/class-testproject#\" rel=\"noopener noreferrer nofollow\">TestProject &#8212; \u043f\u0440\u043e\u0433\u043e\u043d \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0445<\/a>,  <a href=\"https:\/\/playwright.dev\/docs\/test-retries\" rel=\"noopener noreferrer nofollow\">\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a  \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432<\/a>, <a href=\"https:\/\/playwright.dev\/docs\/test-reporters\" rel=\"noopener noreferrer nofollow\">\u041e\u0442\u0447\u0435\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/a><\/p>\n<p><strong><em>\u0422\u043e \u0447\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435<\/em><\/strong>\ud83d\udc47:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/docs\/test-projects#dependencies\" rel=\"noopener noreferrer nofollow\">Dependencies<\/a> \u0434\u043b\u044f  &#171;\u0442\u0438\u043f\u043e&#187; \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 &#8216;auth setup&#8217;  \ud83d\ude42  <\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0446\u0438\u044f  <strong>testIgnore<\/strong>  \u0434\u043b\u044f  \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e project  \u0432\u043d\u043a\u0442\u0440\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 projects \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e  <a href=\"https:\/\/playwright.dev\/docs\/api\/class-testproject#test-project-test-ignore\" rel=\"noopener noreferrer nofollow\">testignore<\/a>.  <\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <\/summary>\n<div class=\"spoiler__content\">\n<pre><code> projects: [     {       name: 'chromium',       testDir: '.\/tests',       testMatch: \/.*\\.spec\\.ts\/,       testIgnore: '**\/test-assets\/**', \/\/\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 test-assets       fullyParallel: true,       use: { browserName: 'chromium' },     },     {       name: 'firefox',       testDir: '.\/tests',       testMatch: \/ExampleTestFour.*\\.spec\\.ts\/,       testIgnore: \/.*(ExampleTestOne|ExampleTestTWO)\\.spec\\.ts\/, \/\/\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f        fullyParallel: false,       use: { browserName: 'firefox' },     },   ],  \/\/\u043b\u0438\u0431\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435  \/\/\u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e\u043c project\/s \/\/ \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432  const ignored = [   \/ExampleTestFour.*\\.spec\\.ts\/,   \/ExampleTest.*\\.spec\\.ts\/, ];  \/\/\u041f\u0440\u0438\u043c\u0435\u0440  {       name: 'firefox',       testDir: '.\/tests',       testMatch: \/ExampleTestFour.*\\.spec\\.ts\/,       testIgnore: ignored, \/\/\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f        fullyParallel: false,       use: { browserName: 'firefox' },     },<\/code><\/pre>\n<\/div>\n<\/details>\n<ul>\n<li>\n<p>\u041e\u043f\u0446\u0438\u044f <a href=\"https:\/\/playwright.dev\/docs\/api\/class-testproject#test-project-snapshot-path-template\" rel=\"noopener noreferrer nofollow\">snapshotPathTemplate<\/a> \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043f\u0443\u0442\u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0441\u043d\u0430\u043f\u0448\u043e\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a (\u0432\u044b\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u043e\u0439,  \u0441\u0434\u0435\u043b\u0430\u043d\u043e\u0439 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u0430  \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0439),  \u041f\u0440\u0438\u043c\u0435\u0440,  <code>\/__screenshots__{\/projectName}\/{testFilePath}\/{arg}{ext}<\/code><\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0446\u0438\u044f <a href=\"https:\/\/playwright.dev\/docs\/api\/class-testoptions#test-options-ignore-https-errors\" rel=\"noopener noreferrer nofollow\">ignoreHTTPSErrors<\/a> &#8212; \u0434\u043b\u044f \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f  \u043e\u0448\u0438\u0431\u043e\u043a SSL\/TLS. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440,  <code>use: {ignoreHTTPSErrors: true},<\/code><\/p>\n<\/li>\n<li>\n<p>reporter  &#8212; \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c\u0438 \u0432\u0438\u0434\u0430\u043c\u0438 \u043e\u0442\u0447\u0435\u0442\u043e\u0432:<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0412\u0438\u0434\u044b \u0438 \u043f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>1) html &#8212; \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 HTML-\u043e\u0442\u0447\u0451\u0442 Playwright,  \u0441 \u0448\u0430\u0433\u0430\u043c\u0438 \u0433\u0434\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u0438 \u0437\u0430 \u0447\u0435\u043c \u0431\u044b\u043b\u043e, \u043d\u043e \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0447\u0442\u043e \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c test.step<\/p>\n<p>2) json &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 Telegram \u0438\u043b\u0438 Slack-\u0431\u043e\u0442. \u0418\u0437 JSON-\u043e\u0442\u0447\u0451\u0442\u0430 \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u044c: \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445, \u0441\u043a\u0438\u043f\u043d\u0443\u0442\u044b\u0445, \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0438 flaky-\u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u0430  (\u043f\u043e\u043f\u043e\u0437\u0436\u0435 \u043d\u0430\u043f\u0438\u0448\u0443 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 :))<\/p>\n<p>3) allure-playwright &#8212; \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043e\u0442\u0447\u0451\u0442: \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0448\u0430\u0433\u0438, \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<pre><code>reporter: [   ['list'],    ['json', { outputFile: 'reports\/test-results.json' }],   ['html', { open: 'never' }] ],<\/code><\/pre>\n<\/div>\n<\/details>\n<hr\/>\n<h4>\ud83d\udccc Screenshots (snapshots)<\/h4>\n<p>\u042d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043b\u0435\u0436\u0430\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a.<\/p>\n<p>\u0412\u0441\u0435 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u043b\u0435\u0436\u0430\u0442 \u0432:  <code>.\/screenshots(snapshots)\/<\/code><\/p>\n<p>\u041f\u0443\u0442\u044c \u043a \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430\u043c  \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432  playwright  \u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u043a\u0430\u043a: <code>\/__screenshots__{\/projectName}\/{testFilePath}\/testFileName\/{arg}{ext}<\/code><\/p>\n<ul>\n<li>\n<p>projectName &#8212; \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435  project \u0432 projects[ ] \u0432 playwright.config  (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, desktop-chrome, safari, iphone 14, pixel 7, ipad \u0438 \u0442 \u0434 ).<\/p>\n<\/li>\n<li>\n<p>{testFilePath} &#8212; \u043f\u0443\u0442\u044c \u043e\u0442 testDir \u0434\u043e \u0444\u0430\u0439\u043b\u0430 c \u0442\u0435\u0441\u0442\u043e\u043c <code>e2e\/test-assets\/...<\/code><\/p>\n<\/li>\n<li>\n<p>{testFileName} &#8212; \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0442\u0435\u0441\u0442\u0430 \u043a\u0430\u043a \u043a\u0430\u0442\u0430\u043b\u043e\u0433 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Basket.spec.ts).<\/p>\n<\/li>\n<li>\n<p>{arg} \u2014 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0438\u0437 toHaveScreenshot(&#8216;&#8230;&#8217;) \u0435\u0441\u043b\u0438  \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439,  \u0438\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 {testName}.<\/p>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,<code>'Show five items in a basket' -&gt; 'Show-five-items-in-a-basket'.<\/code>  <\/p>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0438\u043c\u0435\u043d\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0432 \u0442\u0435\u0441\u0442\u0435, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b-\u0432\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e.<\/p>\n<p> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <code>Show-five-items-in-a-basket.png<\/code> \u2192 <code>Show-five-items-in-a-basket-1.png<\/code>, <code>Show-five-items-in-a-basket-2.png<\/code><\/p>\n<\/li>\n<li>\n<p>{ext} \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e .png)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440<\/strong>\ud83d\udc47<strong>:<\/strong><\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0435\u0441\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0435 \u043d\u0430 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0442\u043e\u0432\u0430\u0440\u043e\u0432 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435. <\/p>\n<p>\u041f\u0443\u0442\u044c \u043a \u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0443 <code>.\/tests\/e2e\/Basket.spec.ts<\/code>   \u0438\u043b\u0438  <code>.\/tests\/e2e\/test-assets\/Basket.spec.ts<\/code>.  <\/p>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u0433\u0434\u0435 \u0435\u0441\u0442\u044c  \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 toHaveScreenshot , \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: &#8216;Show five items in a basket&#8217;.   <\/p>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f  \u0432:<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 <strong>\u043d\u0435<\/strong> \u043b\u0435\u0436\u0438\u0442 \u0432 test-assets: <code>\/screenshots(snapshots)\/desktop-chrome\/e2e\/Basket.spec.ts\/Show-five-items-in-a-basket-1.png<\/code><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f <strong>\u0432\u043d\u0443\u0442\u0440\u0438<\/strong> \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0438 test-assets (\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432  \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445  projects \u0432  playwright.config), \u043f\u0443\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u044d\u0442\u0443 \u043f\u0430\u043f\u043a\u0443: .\/<code>screenshots(snapshots)\/desktop-chrome\/e2e\/test-assets\/Basket.spec.ts\/Show-five-items-in-a-basket-1.png<\/code><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\ud83d\udccc \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 (\u0441\u043f\u043e\u0439\u043b\u0435\u0440 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438)<\/h3>\n<p>\u0412 \u043b\u044e\u0431\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043f\u0435\u0440\u0432\u0430 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u0442\u0430\u043a\u043e\u0435 \u043a\u0430\u043a \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f.  \u0415\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442,  \u043d\u0443 \u0438 \u043b\u0430\u0434\u043d\u043e,  \u043e\u0434\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u043c\u0435\u043d\u044c\u0448\u0435 \ud83d\ude42.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u043e\u043c &#8212; \u044d\u0442\u043e  \u0433\u043b\u0443\u043f\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043e\u043b\u0433\u043e, \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434  \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u0430 + \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430 \u0431\u0435\u043a\u0435\u043d\u0434 \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432  \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432  \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0435\u0441\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043a\u0430\u043a \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u0430\u0443\u0435\u0442\u0435\u043d\u0444\u0438\u043a\u0430\u0446\u0438\u044f.  \u0422\u043e \u0435\u0441\u0442\u044c,  \u0441\u043f\u0435\u0440\u0432\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445  \u0438  \u0438\u0445 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 <strong>json<\/strong>, \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f ( localStorage, \u043a\u0443\u043a\u0438 \u0438 \u0441\u0435\u0441\u0441\u0438\u0438).<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c API \u0438 UI.  \u0412  \u043e\u0444\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Playwright  \u0443\u0439\u043c\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 &#8212; <a href=\"https:\/\/playwright.dev\/docs\/auth\" rel=\"noopener noreferrer nofollow\">\u0410\u0443\u0435\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/a><\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435,  \u043f\u043e\u043a\u0430\u0436\u0443 \u043d\u0435 \u0441\u0430\u043c\u044b\u0439  \u043b\u0443\u0447\u0448\u0438\u0439 \u0438 \u043d\u0435 \u0442\u043e\u043f, \u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0440\u043e\u043b\u044f\u043c\u0438  \u0447\u0435\u0440\u0435\u0437 UI, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0445 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0438\u0445 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<p><a href=\"https:\/\/playwright.dev\/docs\/auth\" rel=\"noopener noreferrer nofollow\">\u0410\u0443\u0435\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f (\u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0439 \u0440\u043e\u043b\u0438)<\/a>. \u042d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0434\u043e\u0431\u0435\u043d,  \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u043e\u043b\u0435\u0439 \u0432 end-to-end \u0442\u0435\u0441\u0442\u0430\u0445, \u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u044b \u0432\u043e \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<p>\u26a0\ufe0f \u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c?  <\/p>\n<p>\u041d\u0430\u0447\u0430\u0442\u044c \u0441\u0442\u043e\u0438\u0442 \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 <code>storageState<\/code>  \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u043e\u043b\u0438, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445  \u0441\u0435\u0441\u0441\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0417\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u0438  \u0432 storageState (\u0448\u0430\u0433\u0438 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b): <\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 (cookies, localStorage, sessionStorage, \u0442\u043e\u043a\u0435\u043d\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f) \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 storageState. <\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b storageState, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0430, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f. <\/p>\n<p>\u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0443\u0436\u0435 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0435\u0437 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p><strong>\u0428\u0430\u0433-1:<\/strong><\/p>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c 6 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e 3 \u0440\u043e\u043b\u044f\u043c,  \u0433\u0434\u0435 3 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f &#8212; \u044d\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0440\u043e\u043b\u044c\u044e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u043a  \u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b\u0438, 2 \u043a\u0430\u043a  \u043f\u0440\u043e\u0434\u0430\u0432\u0446\u044b  (\u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0435), 1 \u043a\u0430\u043a \u0430\u0434\u043c\u0438\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432\u0441\u0435.<\/p>\n<p>\u0423 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u0442\u0440\u0451\u0445 \u0440\u043e\u043b\u0435\u0439 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 \u043f\u0440\u0430\u0432\u0430 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u0445\u043e\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. \u0412\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e &#8212; \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 JSON-\u0444\u0430\u0439\u043b. \u0422\u0430\u043a \u043a\u0430\u043a  \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 6, \u0442\u043e \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e JSON \u0444\u0430\u0439\u043b\u043e\u0432 \u0431\u0443\u0434\u0435\u0442  \u0440\u0430\u0432\u043d\u043e 6.<\/p>\n<p><strong>\u041f\u0443\u0442\u0438 \u043a JSON-\u0444\u0430\u0439\u043b\u0430\u043c<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0447\u0435\u0440\u0435\u0437 storageState, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c <strong>\u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/strong><\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>auth-state-constants.ts <\/code>\u0432 \u043f\u0430\u043f\u043a\u0435<code> .\/constants\/auth\/,<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 AUTH_ROLE_STATES, \u0433\u0434\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u043e\u043b\u044f\u043c, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u0443\u0442\u0438 \u043a<code> auth.json <\/code>\u0444\u0430\u0439\u043b\u0430\u043c. <\/p>\n<pre><code>\/\/ .\/constants\/auth\/auth-state-constants.ts  \/** * \u041f\u0443\u0442\u0438 \u043a auth.json \u0444\u0430\u0439\u043b\u0430\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f storageSate *\/ export const AUTH_ROLE_STATES = {   customer: {     first: '.\/.auth\/first-customer-auth.json',     second: '.\/.auth\/second-customer-auth.json',     third: '.\/.auth\/third-customer-auth.json',   },   professional: {     first: '.\/.auth\/first-prof-auth.json',     second: '.\/.auth\/second-prof-auth.json',   },   admin: {     main: '.\/.auth\/admin-auth.json',   }, } <\/code><\/pre>\n<p><strong>\u0428\u0430\u0433-2: <\/strong><\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0441\u0435 email-\u044b \u0438  \u043f\u0430\u0440\u043e\u043b\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b  \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0436\u0435 \u043f\u0430\u043f\u043a\u0435 .\/constants\/auth\/, \u0430 \u0444\u0430\u0439\u043b \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u043a\u0430\u043a user-creds-constants.ts <\/p>\n<pre><code>\/\/ .\/constants\/auth\/user-creds-constants.ts    import { AUTH_ROLE_STATES } from '.\/auth-state-constants';  \/** *  \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 *\/ export const USER_CREDENTIALS = {   firstCustomer: {     email: 'test-customer@example.com',     password: 'superSecret123',     jsonPath: AUTH_ROLE_STATES.customer.first,   },    ......   firstProffi: {     email: 'test-proffi@example.com',     password: 'superSecret123',     jsonPath: AUTH_ROLE_STATES.professional.first,   },     ....   admin: {     email: 'test-admin@example.com',     password: 'superSecret123',     jsonPath: AUTH_ROLE_STATES.admin.main,   } } <\/code><\/pre>\n<p><strong>\u0428\u0430\u0433-3: <\/strong><\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u043f\u0435\u0440\u044c, \u043d\u0443\u0436\u043d\u043e  \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 JSON  \u0444\u0430\u0439\u043b\u044b \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 6 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>\u041a\u0430\u043a \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0437 \u043e\u0444\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u0441\u043f\u0435\u0440\u0432\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u043c  \u0444\u0430\u0439\u043b  globalAuth.setup.ts.  \u042d\u0442\u043e\u0442 setup \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u043b\u043e\u0432\u0438\u044f.  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0440\u043e\u043b\u044f\u043c\u0438 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<pre><code>\/\/ playwrightTests\/globalAuth.setup.ts  import { test as setup, expect } from '@playwright\/test';   async function loginAndSave(    page, email:    string,    password: string,     jsonPath: string ) {   const loginPage = new LoginPage(page)    \/\/ \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f   await loginPage.goto(loginPage.url)   await loginPage.login(email, password)   await expect(page).toHaveURL(...\/\/\u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u043d\u0430)       \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c storage state \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0440\u043e\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b   await page.context().storageState({ path: jsonPath })   await context.close() }  setup('customer 1', async({page}) =&gt; {    loginAndSave(       page,       USER_CREDENTIALS.firstCustomer.email,        USER_CREDENTIALS.firstCustomer.password   ) })   setup('proffessional 1', async({page}) =&gt; {    loginAndSave(       page,       USER_CREDENTIALS.firstProffi.email,        USER_CREDENTIALS.firstProffi.password   ) })  setup('admin', async({page}) =&gt; {    loginAndSave(       page,       USER_CREDENTIALS.admin.email,        USER_CREDENTIALS.admin.password   ) })<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 playwrightTest \u0434\u043e\u043b\u0436\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <code>.auth<\/code>, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f 6 JSON-\u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0441\u0441\u0438\u044f\u043c\u0438 (storage state) \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. <\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f JSON-\u0444\u0430\u0439\u043b\u044b \u0441\u0435\u0441\u0441\u0438\u0439:<\/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\/1c2\/09f\/c69\/1c209fc69993a439cc84f55a70742981.png\" alt=\"\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f .auth\" title=\"\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f .auth\" width=\"768\" height=\"512\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1c2\/09f\/c69\/1c209fc69993a439cc84f55a70742981.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1c2\/09f\/c69\/1c209fc69993a439cc84f55a70742981.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><strong>\u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f .auth<\/strong><\/figcaption><\/div>\n<\/figure>\n<p><strong>\u0415<\/strong>\u0441\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043b\u044e\u0431\u043e\u0439 JSON-\u0444\u0430\u0439\u043b, \u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e \u0432\u0441\u0451 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0435\u0441\u0441\u0438\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. <\/p>\n<\/div>\n<p><strong>\u0428\u0430\u0433-4: <\/strong><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 <code>globalAuth.setup.ts <\/code>(Setup), \u0432<code> playwright.config.ts <\/code> -&gt; \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 projects. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 (setup auth) \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b, \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 storageState \u0438 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0430, \u0433\u0434\u0435 \u0443\u043a\u0430\u0437\u0430\u043d setup auth \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438:<\/p>\n<pre><code>import { defineConfig } from '@playwright\/test';  export default defineConfig({   projects: [     {       \/\/ 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\/       name: 'setup auth',       testMatch: \/.*\\.setup\\.ts\/,       testDir: '.\/tests',       fullyParallel: true,     },     {        name: 'chrome',         use: { storageState: STORAGE_STATE_JSON_PATH },     },      {       name: 'firefox',       testDir: '.\/tests',       fullyParallel: true,       dependencies: ['setup']     }   ], }); <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u26a0\ufe0f \u041a\u0430\u043a \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c storageState?<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 <strong>storageState<\/strong> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430:<\/p>\n<p>1) \u0423\u043a\u0430\u0437\u0430\u0442\u044c storageState \u0432  playwright.config  -&gt; projects -&gt;project -&gt; use -&gt; storageState<\/p>\n<p>\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c project, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c setup auth. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c project \u043e\u0442 setup auth \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 dependencies. <a href=\"https:\/\/playwright.dev\/docs\/test-projects#running-sequence\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430  \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c setup<\/a><\/p>\n<p>Dependencies &#8212; \u044d\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0435\u0436\u0434\u0435, \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u044f\u0442\u0441\u044f \u0442\u0435\u0441\u0442\u044b \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u041e\u043d\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u043e\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<pre><code>  projects: [      {        name: 'chrome',         use: { storageState: STORAGE_STATE_JSON_PATH },      },      {       name: 'firefox',       testDir: '.\/tests',       fullyParallel: true,       dependencies: ['setup']     }   ]<\/code><\/pre>\n<p>2) \u0423\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c <code>.spec.ts<\/code>. <\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c  <code>test.use({ storageState: STORAGE_STATE_JSON_PATH })<\/code><\/p>\n<p>\u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043c\u0435\u043d\u044f\u0442\u044c storageState \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u0432\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438. <\/p>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435  \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u0438 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u0441\u0435\u043c \u0438\u043c \u043d\u0443\u0436\u0435\u043d \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 storageState.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 JSON-\u0444\u0430\u0439\u043b\u0430 storageState \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0432\u043d\u0443\u0442\u0440\u0438 .spec.ts.<\/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 storageState \u0432 \u0444\u0430\u0439\u043b\u0435, \u0433\u0434\u0435 \u043b\u0435\u0436\u0430\u0442 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b  <\/summary>\n<div class=\"spoiler__content\">\n<pre><code>import { test } from '@playwright\/test';  import { AUTH_ROLE_STATES } from '..\/authRoleStates';   \/\/ \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\u0435 test.use({ storageState: AUTH_ROLE_STATES.admin.main });  test('admin test', async ({ page }) =&gt; {    \/\/ page is authenticated as a user  });   test.describe(() =&gt; {   \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c storageState \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e test suite    test.use({ storageState: AUTH_ROLE_STATES.customer.first });    test('user test', async ({ page }) =&gt; {     \/\/ page is authenticated as a user   }); });<\/code><\/pre>\n<\/div>\n<\/details>\n<p>3) \u0411\u044b\u0432\u0430\u0435\u0442 \u0447\u0442\u043e, \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 storageState. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c  \u043f\u0435\u0440\u0435\u0434 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 suite:<\/p>\n<p><code> test.use({ storageState: { cookies: [], origins: [] } });<\/code><\/p>\n<pre><code>\/\/\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442 \u0432 spec.ts  test.describe(() =&gt; {   test.use({ storageState: { cookies: [], origins: [] } });    test('api test ', async ({ page }) =&gt; {        getTokenFromStorage(AUTH_ROLE_STATES.customer.first)         }); });<\/code><\/pre>\n<p>4) \u0422\u0430\u043a\u0436\u0435 \u0431\u044b\u0432\u0430\u0435\u0442 \u0447\u0442\u043e \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0435\u0439\u0441\u0430\u0445  \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440\u043b\u043e\u0433\u0430\u0443\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f  \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043d\u043e\u0432\u043e \u043b\u043e\u0433\u0438\u043d\u0438\u0442\u044c\u0441\u044f  \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443  \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043c\u0435\u0442\u0438\u0442\u044c  \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043d\u043e\u0432\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u0430\u043f <\/p>\n<pre><code> projects: [     {       \/\/ 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\/       name: 'setup auth',       testMatch: \/.*\\.setup\\.ts\/,       testDir: '.\/tests',       fullyParallel: true,     }     {              name: 'chrome',       testIgnore: \/.*\\.Smoke.spec\\.ts\/,       testDir: '.\/tests',       fullyParallel: true,       dependencies: ['setup']     }   ],<\/code><\/pre>\n<p><em>\u26a0\ufe0f <\/em>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439  \u0438\u0437 JSON<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 JSON-\u0444\u0430\u0439\u043b\u0430 storageState \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0432\u043d\u0443\u0442\u0440\u0438 .spec.ts.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u0437 JSON \u0444\u0430\u0439\u043b\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430 \u0438\u0437 json<\/summary>\n<div class=\"spoiler__content\">\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u043e\u043a\u0435\u043d \u0438\u0437 json \u0432 helpers\/auth-helper.ts<\/strong><\/p>\n<pre><code>\/\/helpers\/auth-helper.ts  export function getTokenFromStorage(storageName: string): string | undefined {   \/\/ \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c storageState \u0438\u0437 \u0444\u0430\u0439\u043b\u0430   const storageState = JSON.parse(     fs.readFileSync(storageName, 'utf-8')   );    \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432 origins \u0435\u0441\u0442\u044c localStorage   if (!storageState?.origins?.[0]?.localStorage) {     return undefined;   }    \/\/ \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0442\u043e\u043a\u0435\u043d \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 localStorage   const token = storageState.origins[0].localStorage.find(     (item: any) =&gt; item.name === 'auth_token'   )?.value;    return token; }<\/code><\/pre>\n<p><strong>\u0412\u044b\u0437\u043e\u0432\u0435\u043c  getTokenFromStorage  \u0432 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0435:<\/strong><\/p>\n<pre><code>\/\/\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442 \u0432 spec.ts  test.describe(() =&gt; {   test('api test ', async ({ page }) =&gt; {        getTokenFromStorage(AUTH_ROLE_STATES.customer.first)         }); });<\/code><\/pre>\n<\/div>\n<\/details>\n<h2> \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043b\u0430\u0441\u044c \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043d\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u043f\u0440\u0438\u0432\u043e\u0434\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0430 \u0447\u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c. \u041f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0433\u043b\u0430\u0432\u0430, \u043f\u043e\u0441\u0432\u044f\u0449\u0451\u043d\u043d\u0430\u044f \u0441\u0430\u043c\u0438\u043c \u0442\u0435\u0441\u0442\u0430\u043c, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.<\/p>\n<p><strong><em>\u041e\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 &#8212; \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 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u0445 \u0438\u043b\u0438 \u043f\u0440\u0438 \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<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/942656\/\"> https:\/\/habr.com\/ru\/articles\/942656\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0413\u043b\u0430\u0432\u0430 1. \u041a\u0430\u043a\u00a0\u0432\u0441\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u043e\u0441\u044c. \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0438 \u0432\u043e\u0434\u044b \u043e\u00a0\u043c\u043e\u0435\u043c\u00a0\u043b\u0438\u0447\u043d\u043e\u043c \u043e\u043f\u044b\u0442\u0435.<\/h3>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442!<br \/>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u0439\u043d\u0443\u0440\u0430.<\/p>\n<div class=\"floating-image\">\n<p>\u041c\u043e\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0441 Playwright \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u043e\u043a\u043e\u043b\u043e \u0434\u0432\u0443\u0445 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434. \u0417\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u044f \u043d\u0435 \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0430\u0441\u044c \u0441 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438, \u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043d\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043e\u043f\u044b\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u0434\u0440\u0443\u0433\u0438\u043c.<\/p>\n<\/div>\n<figure class=\"full-width\">\n<div><figcaption>\u041c\u0443\u043b\u044c\u0442\u044f\u0448\u043d\u044b\u0439 \u0434\u0440\u0430\u043a\u0443\u043b\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442! \u041d\u0435 \u0441\u043a\u0432\u0435\u0440\u043d\u043e\u0441\u043b\u043e\u0432\u0438\u0442!<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b\u0441\u043b\u044c \u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 Playwright \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0432 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e Codeception \u043d\u0435 \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0440\u044f\u0434\u043e\u043c \u0437\u0430\u0434\u0430\u0447, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0447\u0430\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0441 WebView.<\/p>\n<p>\u0410 <strong>\u043c\u0438\u043d\u0443\u0441\u044b<\/strong> \u0431\u044b\u043b\u0438 \u0432\u0435\u0441\u043e\u043c\u044b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <strong>Codeception<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u274c \u0414\u043e PHP 8 \u0432\u0441\u0451 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 Codeception \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0443\u0447\u043d\u044b\u043c. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u044d\u0442\u043e\u0442 \u0433\u0435\u043c\u043e\u0440: \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e 8-\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 PHP, \u043b\u0438\u0431\u043e \u0432\u0441\u0451 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0427\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0438\u0434\u0435\u044f \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u043d\u044f \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u044f\u043b\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0430 \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 API-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 (\u041f\u0440\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u044f \u0437\u0430 \u044d\u0442\u043e \u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438) .<\/p>\n<\/li>\n<li>\n<p>\u274c \u0421\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435! \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0430 \u043a\u0435\u0439\u0441\u043e\u0432 \u043d\u0430 WEBVIEW \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 (\u0430 \u044d\u0442\u043e \u0431\u044b\u043b \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043c\u0438\u043d\u0443\u0441). \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u043c\u0438 &#8212; \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e Chrome \u0447\u0435\u0440\u0435\u0437 WebDriver)<\/p>\n<\/li>\n<li>\n<p>\u274c \u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 <\/p>\n<\/li>\n<li>\n<p>\u274c \u041d\u0435\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p>\u274c \u041c\u0435\u043d\u044c\u0448\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u274c \u0414\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433 \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0433 \u0431\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0433\u0447\u0435. \u0412 Codeception \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438: \u043d\u0435\u043b\u044c\u0437\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u0438\u0434\u0435\u0442\u044c, \u043a\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0443\u0445\u043e\u0434\u0438\u0442 \u0438 \u043a\u0430\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438. \u0412\u0441\u0451 \u044d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>\u274c \u041d\u0435 \u0431\u044b\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u274c \u0412 Codeception \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0438\u0434\u043e\u0432 \u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0440\u043e\u0434\u0435 <strong>see, dontSee<\/strong> \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0442\u0435\u043a\u0441\u0442\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 <strong>soft-\u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432<\/strong><\/p>\n<\/li>\n<li>\n<p>\u274c \u041f\u043e\u0438\u0441\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f <strong>\u0422\u041e\u041b\u042c\u041a\u041e  <\/strong>\u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b: <code>data-test-id<\/code>, <code>id, class \u0438 \u0442 \u0434<\/code>. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430 (<code>class<\/code>) \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043b\u043e\u0445\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0438\u043b\u0438 \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u044b( class=&#187;yellow__1a2b3&#8243; \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0430  class=&#187;yellow__97dhfgg&#187;)<\/p>\n<\/li>\n<li>\n<p>\u274c \u041c\u0430\u043b\u043e \u0441\u0442\u0430\u0442\u0435\u0439 \u0441 best practices<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0412\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043b\u044e\u0441\u043e\u0432 <\/strong>Playwright<strong> \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0448\u0430\u044e\u0442 \u043c\u0438\u043d\u0443\u0441\u044b Codeception :<\/strong><\/p>\n<ul>\n<li>\n<p>\u2705 <strong><em>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432<\/em><\/strong>. \u0422\u0435\u0441\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u0440\u043e\u0441\u0441\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0441\u0442\u0438.<\/em><\/strong> Playwright \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 Chromium, Firefox, WebKit \u0438 \u0434\u0430\u0436\u0435 \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432.<\/em> <\/strong>\u0412\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 Playwright \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0447\u0435\u043c \u043d\u0430 Codeception \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u0432 CI\/CD  (\u0441\u043c. \u0422\u0430\u0431\u043b\u0438\u0446\u0430 1)<\/p>\n<\/li>\n<li>\n<p>\u2705<em> <\/em><strong><em>\u041b\u0451\u0433\u043a\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f UI-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Codegen<\/em><\/strong><em> <\/em>\u2014 \u043c\u043e\u0436\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0423\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u0435\u0431\u0430\u0433\u0433\u0438\u043d\u0433 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 <\/em><\/strong>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441 <strong>\u043f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c<\/strong> \u0442\u0435\u0441\u0442\u0430 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430. \u0412 Playwright \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0433\u0438\u0431\u043a\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430: \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442, \u0433\u0440\u0443\u043f\u043f\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043f\u0430\u0432\u0448\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044e Trace Viewer \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0438 DOM-\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435 \u0442\u0435\u0441\u0442\u0430, \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u043e\u0442\u0432\u0435\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043e\u0448\u0438\u0431\u043a\u0438, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0431\u044b\u0441\u0442\u0440\u044b\u043c \u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435<\/em><\/strong><em>.<\/em> \u0412 Playwright \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 expect().toHaveScreenshot(), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043f\u0440\u044f\u043c\u043e \u0432 \u0442\u0435\u0441\u0442\u0435 (\u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043d\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435).<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041c\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u043e\u0432 \u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432 \u0438 soft-\u0430\u0441\u0441\u0435\u0440\u0442\u044b<\/em><\/strong>, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0442\u0435\u043a\u0441\u0442\u0430, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 (await elementHandle.isChecked(), await elementHandle.isEditable(), await elementHandle.isEnabled()).  \u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <strong>soft-\u0430\u0441\u0441\u0435\u0440\u0442\u043e\u0432 <\/strong>(\u043c\u044f\u0433\u043a\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u0434\u0435\u043b\u0430\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438\u043c \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u0413\u0438\u0431\u043a\u0438\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/em><\/strong>. \u0412 Playwright \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043d\u0438\u043c \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 (heading, label, text, paragraph \u0438 \u0442. \u043f.), \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b (data-test-id, id \u0438 \u0442 \u0434), \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 (\u0446\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0446\u0432\u0435\u0442 \u0444\u043e\u043d\u0430), \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 (locator.getByRole(), locator.getByText(), locator.getByTestId()), \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u2705 <strong><em>\u041e\u0431\u0448\u0438\u0440\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0441\u0442\u0430\u0442\u044c\u0438.<\/em><\/strong><em> <\/em>\u041a\u0440\u043e\u043c\u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0430\u0442\u0435\u0439, \u0433\u0430\u0439\u0434\u043e\u0432 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0441 \u0432\u044b\u0445\u043e\u0434\u043e\u043c \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0442\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432, \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f API-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0434\u0435\u0431\u0430\u0433\u0430.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\">\n<div><figcaption>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 1. \u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 Playwright vs Codeception<\/figcaption><\/div>\n<\/figure>\n<p>\u2757 <strong>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435!  <\/strong>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u044b, <strong>\u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0435\u0441\u044f \u043a WebView<\/strong> \u2014 \u044d\u0442\u043e <strong>\u043e\u0431\u0449\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0441 best practices<\/strong>, \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u0430 \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u2757<strong>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435! <\/strong>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f  \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442  \u0432 \u0441\u043a\u0440\u044b\u0442\u043e\u043c \u0442\u0435\u043a\u0441\u0435.<\/p>\n<hr\/>\n<h3>\u0413\u043b\u0430\u0432\u0430 2. \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \ud83d\ude80 \u041c\u043e\u0438 best practices <\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u043b\u0430\u0432\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0441\u043b\u0443\u0436\u0430\u0449\u0430\u044f \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u043e\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u044b\u0445 \u0438 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432.  \u0410 \u0438\u043c\u0435\u043d\u043d\u043e:<em> PageObject-\u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, helpers, step pattern, config, snapshots.<\/em><\/p>\n<p><strong>\u041f\u0440\u0438\u0447\u0438\u043d\u0430<\/strong>, \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0441\u044c \u043d\u0430 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <strong>\u0441\u0430\u043c\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u044d\u0442\u0438\u0445 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/strong>. \u0412\u0441\u0451, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 <code>common<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 <code>snapshots<\/code> \u0438 <code>config<\/code>.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0432\u0441\u0451 \u043f\u043e\u0434\u0440\u044f\u0434, \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u043b\u0438 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c. \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u0435\u0434\u0451\u0442 \u043a \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u044e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u044e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434-\u0440\u0435\u0432\u044c\u044e \u0438 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 -&gt; \u043a \u0445\u0430\u043e\u0441\u0443.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0442 \u0445\u0430\u043e\u0441 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b \u0438\u043b\u0438 \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a  \u0440\u0430\u0437\u0433\u0440\u0435\u0431\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0445\u0430\u043e\u0441, \u044f \u0443\u0434\u0435\u043b\u044f\u044e \u043e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p><strong><em>\u0418 \u0442\u0430\u043a\u0441, \u043d\u0430\u0447\u043d\u0435\u043c \ud83d\ude80\ud83d\udc47<\/em><\/strong><\/p>\n<h4>\ud83d\uddc2 \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430<\/h4>\n<p>C \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u043d\u0435\u043c? \u041a\u043e\u043d\u0435\u0448\u043d\u043e \u0436\u0435, \u0441 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. <\/p>\n<p>\u0418 \u0442\u0430\u043a  \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0443\u0436\u043d\u0430 \u0442\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u044f \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e  QA  \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0430\u044f ( \u0431\u0435\u0437 \u043a\u0440\u0430\u0441\u043e\u0442\u044b \u0436\u0438\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f!)<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0432\u0438\u0434\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f). \u0412\u0430\u0436\u043d\u043e \u0443\u0442\u043e\u0447\u043d\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u043d\u0443\u0436\u043d\u044b \u043b\u0438 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043b\u0438 e2e-\u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f UI-\u043f\u0440\u043e\u0435\u043a\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438 API, \u0438 UI \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 (\u043f\u0440\u0438 \u044d\u0442\u043e\u043c API-\u0442\u0435\u0441\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0437 UI)<\/p>\n<\/li>\n<li>\n<p>\u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b devDependencies  \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c  package.json ,  \u0438\u043b\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. <\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u043e\u0439 package.json \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0415\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 <code>package.json<\/code>:<\/p>\n<ul>\n<li>\n<p> \u0442\u043e \u044d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 <code>node_modules<\/code><\/p>\n<\/li>\n<li>\n<p> \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 <\/p>\n<\/li>\n<li>\n<p>\u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 CI\/CD<\/p>\n<\/li>\n<li>\n<p> \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p> \u043c\u043e\u0436\u0435\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043e\u0431\u0440\u0430\u0437\u0430 (\u0435\u0441\u043b\u0438 \u043d\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b <code>dependencies<\/code> \u0438 <code>devDependencies<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0445 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u0441\u043d\u0438\u0436\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c <code>package.json)<\/code><\/p>\n<\/li>\n<\/ul>\n<p>&#171;\u042f \u0431\u044b \u043d\u0435 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u043b\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 (devDependencies) \u0441 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c package.json \u0438 \u0432\u044b\u043d\u0435\u0441\u043b\u0430 \u0431\u044b \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c package.json, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0447\u0438\u0441\u0442\u043e\u0442\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430&#187;<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0442\u0440\u0451\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432: <strong>common<\/strong>, <strong>snapshots<\/strong> \u0438 <strong>tests<\/strong> \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.<\/p>\n<div class=\"floating-image\">\n<figure class=\"float\">\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430  \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439  \u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 <\/figcaption><\/div>\n<\/figure>\n<p><strong>&#8212; common<\/strong> \u2013 \u043e\u0431\u0449\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 (\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b, \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0448\u0430\u0433\u0438).<\/p>\n<p><strong>&#8212; snapshots<\/strong> \u2013 \u0441\u043d\u0438\u043c\u043a\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432).<\/p>\n<p>&#8212; <strong>tests<\/strong> \u2013 \u0441\u0430\u043c\u0438 \u0442\u0435\u0441\u0442\u044b, \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0442\u0438\u043f\u0430\u043c (smoke, e2e, api)<\/p>\n<p>&#8212; <strong>playwright.config.ts <\/strong>&#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043e\u0431\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Playwright<\/p>\n<p>\ud83d\udcc1 <strong>\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong> \ud83d\udccc <strong>(\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c!)<\/strong><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0434\u043b\u044f \u044f\u0441\u043d\u043e\u0441\u0442\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439.<\/p>\n<\/div>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0444\u0430\u0439\u043b\u043e\u0432, <strong>\u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u0443 <em>\u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435<\/em><\/strong>, \u043e\u0442\u0440\u0430\u0436\u0430\u044e\u0449\u0435\u0435 \u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<ul>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b, c\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>kebab-case<\/code> + \u043e\u043a\u0430\u043d\u0447\u0430\u043d\u0438\u0435 <code>locators<\/code>.  \u041f\u0440\u0438\u043c\u0435\u0440: <code>filter-locators.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b,  c\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435  \u0445\u0435\u043b\u043f\u0435\u0440\u044b (services)<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>kebab-case<\/code>   + \u043e\u043a\u0430\u043d\u0447\u0430\u043d\u0438\u0435  \u043d\u0430 <code>helper<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: <code>date-format-helper.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b  c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>kebab-case<\/code> \u0438 \u043e\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 <code>constants<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440:  <code>profile-constants.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>PascalCase<\/code> \u0438 \u043e\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 <code>Component<\/code> \u0438\u043b\u0438 <code>Page<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: UserProfilePage.ts, <code>FilterComponent.ts<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0439\u043b\u044b  c  \u0441\u0430\u043c\u0438\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>PascalCase<\/code> \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c <code>.spec.ts <\/code>. \u041f\u0440\u0438\u043c\u0435\u0440:  ProfileSettings.spec.ts\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <code>kebab-case<\/code>. \u041f\u0440\u0438\u043c\u0435\u0440: <code>api-routes.ts<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u0430 <strong>\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0444\u0438\u0447\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u0434\u0435\u043b\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0439 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0439.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f\u0445 <strong>common(support)<\/strong> \u0438\u043b\u0438 <strong>tests<\/strong> \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438\u0445 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0432 \u043e\u0434\u043d\u0443 \u043f\u0430\u043f\u043a\u0443. \u042d\u0442\u043e \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e.<\/p>\n<ol>\n<li>\n<p> \u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong>Authorization<\/strong>) \u2192 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443.   \u041f\u0440\u0438\u043c\u0435\u0440: <code>pages\/auth\/LoginPage.ts<\/code>, <code>pages\/auth\/RegisterPage.ts<\/code><\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0439 \u0444\u0438\u0447\u0438 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong> ProfilePage.ts,  EditProfileTest.spec.ts<\/strong>) \u2192 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043b\u044f \u043d\u0435\u0451 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443.<\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p>\ud83d\udc49 <strong>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0447\u0442\u043e \u043a \u0447\u0435\u043c\u0443 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <em>common (support) <\/em><\/strong>\u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Playwright.<\/p>\n<p>\u042d\u0442\u0430 \u043f\u0430\u043f\u043a\u0430 \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <strong>\u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434<\/strong>, \u043d\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0439\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0438\u043b\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c.<\/p>\n<div class=\"floating-image\">\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f <strong>common(<\/strong>\u0438\u043b\u0438 \u0436\u0435<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-472819","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472819","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=472819"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/472819\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=472819"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=472819"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=472819"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}