{"id":21663,"date":"2023-05-06T18:20:05","date_gmt":"2023-05-06T14:50:05","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/"},"modified":"2023-05-06T18:20:05","modified_gmt":"2023-05-06T14:50:05","slug":"improving-design-system-visual-testing-consistency-with-docker-530a","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/","title":{"rendered":"\u0628\u0647\u0628\u0648\u062f \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u0633\u06cc\u0633\u062a\u0645 \u0637\u0631\u0627\u062d\u06cc \u0628\u0627 Docker"},"content":{"rendered":"<div data-article-id=\"1459280\" id=\"article-body\">\n<p>\u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u06cc\u06a9 \u0631\u0627\u0647 \u0639\u0627\u0644\u06cc \u0628\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u0645\u0624\u0644\u0641\u0647 UI \u0634\u0645\u0627 \u062f\u0631 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0637\u0631\u0627\u062d\u06cc \u0627\u0633\u062a.  \u0628\u0627 \u0627\u06cc\u0646 \u062d\u0627\u0644\u060c \u0647\u0646\u06af\u0627\u0645 \u06a9\u0627\u0631 \u0628\u0631 \u0631\u0648\u06cc \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u0628\u0627 \u0686\u0646\u062f\u06cc\u0646 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0648 \u062a\u0644\u0627\u0634 \u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u06cc\u0627 CI\u060c \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0645\u0634\u06a9\u0644 \u0633\u0627\u0632 \u0634\u0648\u062f\u060c \u0632\u06cc\u0631\u0627 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u0628\u0631\u0627\u06cc \u0647\u0631 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0645\u062a\u0641\u0627\u0648\u062a \u0628\u0647 \u0646\u0638\u0631 \u0628\u0631\u0633\u062f.  \u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0644\u0627\u0632\u0645 \u0627\u0633\u062a \u06a9\u0647 \u062a\u0633\u062a \u0647\u0627 \u0631\u0627 \u0631\u0648\u06cc \u0647\u0645\u0627\u0646 \u0645\u0631\u0648\u0631\u06af\u0631 \u0648 \u0645\u062d\u06cc\u0637 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0627\u0632 \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u062d\u0627\u0635\u0644 \u0634\u0648\u062f.<\/p>\n<p>Docker \u06cc\u06a9 \u067e\u0644\u062a\u0641\u0631\u0645 \u0645\u0646\u0628\u0639 \u0628\u0627\u0632 \u0627\u0633\u062a \u06a9\u0647 \u0628\u0647 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u06af\u0627\u0646 \u0627\u06cc\u0646 \u0627\u0645\u06a9\u0627\u0646 \u0631\u0627 \u0645\u06cc \u062f\u0647\u062f \u062a\u0627 \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627 \u0631\u0627 \u062f\u0631 \u062f\u0627\u062e\u0644 \u06a9\u0627\u0646\u062a\u06cc\u0646\u0631\u0647\u0627\u06cc \u0627\u06cc\u0632\u0648\u0644\u0647 \u0627\u06cc\u062c\u0627\u062f\u060c \u0627\u0633\u062a\u0642\u0631\u0627\u0631 \u0648 \u0627\u062c\u0631\u0627 \u06a9\u0646\u0646\u062f.  \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 Docker\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u0632 \u0646\u062a\u0627\u06cc\u062c \u062b\u0627\u0628\u062a \u062f\u0631 \u0645\u062d\u06cc\u0637\u200c\u0647\u0627\u06cc \u0645\u062e\u062a\u0644\u0641 \u0648 \u0646\u0633\u062e\u0647 \u0645\u0631\u0648\u0631\u06af\u0631 \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u062d\u0627\u0635\u0644 \u06a9\u0646\u06cc\u0645.<\/p>\n<p>\u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0627\u0632 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0637\u0631\u0627\u062d\u06cc \u0639\u0627\u0644\u06cc \u0627\u0644\u0647\u0627\u0645 \u06af\u0631\u0641\u062a\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a \u06a9\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634 \u0628\u0635\u0631\u06cc \u062e\u0648\u062f \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0631\u062f\u0647 \u0627\u0633\u062a\u060c \u06a9\u0647 \u0627\u0644\u0647\u0627\u0645 \u0628\u062e\u0634 \u0645\u0646 \u0628\u0631\u0627\u06cc \u06a9\u0634\u0641 \u0646\u062d\u0648\u0647 \u0639\u0645\u0644\u06a9\u0631\u062f \u0622\u0646 \u0628\u0648\u062f.  \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u062c\u0631\u0627\u06cc \u06a9\u0627\u0645\u0644 \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u062f\u0631 \u0627\u06cc\u0646 \u0645\u062e\u0632\u0646 GitHub \u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f.  \u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u062f\u0631 \u0645\u0648\u0631\u062f \u0646\u062d\u0648\u0647 \u0627\u062c\u0631\u0627\u06cc \u0622\u0646 \u0628\u062d\u062b \u06a9\u0646\u06cc\u0645.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"\u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%D9%85%D8%A4%D9%84%D9%81%D9%87_%D8%B1%D8%A7%D8%A8%D8%B7_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%DB%8C\" >\u0627\u06cc\u062c\u0627\u062f \u0645\u0624\u0644\u0641\u0647 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%AA%D8%B3%D8%AA_%D8%A8%D8%B5%D8%B1%DB%8C_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\" >\u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D9%BE%DB%8C%D8%B4_%D9%86%DB%8C%D8%A7%D8%B2%D9%87%D8%A7\" >\u067e\u06cc\u0634 \u0646\u06cc\u0627\u0632\u0647\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D8%A8%D9%84%D9%87\" >\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0628\u0644\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%DA%AF%D8%B2%D8%A7%D8%B1%D8%B4%DA%AF%D8%B1_%D8%A7%D8%B3%D8%AA\" >\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06af\u0632\u0627\u0631\u0634\u06af\u0631 \u0627\u0633\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7\" >\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062a\u0633\u062a \u0647\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%A7%D8%AC%D8%B1%D8%A7_%D8%AA%D8%B3%D8%AA\" >\u062f\u0631 \u062d\u0627\u0644 \u0627\u062c\u0631\u0627 \u062a\u0633\u062a<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7%DB%8C_%D8%B4%DA%A9%D8%B3%D8%AA_%D8%AE%D9%88%D8%B1%D8%AF%D9%87\" >\u0628\u0631\u0631\u0633\u06cc \u062a\u0633\u062a \u0647\u0627\u06cc \u0634\u06a9\u0633\u062a \u062e\u0648\u0631\u062f\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/improving-design-system-visual-testing-consistency-with-docker-530a\/#%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_CI\" >\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc CI<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%D9%85%D8%A4%D9%84%D9%81%D9%87_%D8%B1%D8%A7%D8%A8%D8%B7_%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%DB%8C\"><\/span>\n<p>  \u0627\u06cc\u062c\u0627\u062f \u0645\u0624\u0644\u0641\u0647 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0627\u0632 \u0644\u0631\u0646\u0627 \u0628\u0631\u0627\u06cc \u0645\u062f\u06cc\u0631\u06cc\u062a \u0628\u0633\u062a\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"o\">-<\/span> <span class=\"nx\">packages<\/span>\n    <span class=\"o\">-<\/span> <span class=\"nx\">core<\/span> <span class=\"c1\">\/\/ Core component<\/span>\n    <span class=\"o\">-<\/span> <span class=\"nx\">design<\/span><span class=\"o\">-<\/span><span class=\"nx\">tokens<\/span> <span class=\"c1\">\/\/ Tokens<\/span>\n    <span class=\"o\">-<\/span> <span class=\"nx\">visual<\/span><span class=\"o\">-<\/span><span class=\"nx\">test<\/span> <span class=\"c1\">\/\/ UI Testing<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<ul>\n<li>\n<code>core<\/code>  \u0628\u0633\u062a\u0647: \u0627\u06cc\u0646 \u062c\u0632\u0621 \u0627\u0635\u0644\u06cc \u0633\u06cc\u0633\u062a\u0645 \u0637\u0631\u0627\u062d\u06cc \u0627\u0633\u062a.  \u0645\u0627 \u0627\u0632 Vue 3\u060c Vite \u0648 TypeScript \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.  \u0645\u0627 \u0647\u0645\u0686\u0646\u06cc\u0646 \u0627\u0632 Storybook \u0628\u0631\u0627\u06cc \u0646\u0645\u0627\u06cc\u0634 \u0645\u0648\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u0648 Jest \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u0648\u0627\u062d\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<li>\n<code>design-tokenks<\/code>  \u0628\u0633\u062a\u0647: \u0645\u0627 \u062a\u0648\u06a9\u0646 \u0647\u0627 \u0631\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u0628\u0633\u062a\u0647 \u062a\u0648\u0644\u06cc\u062f \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<li>\n<code>visual-testing<\/code>  \u0628\u0633\u062a\u0647: \u0645\u0627 \u0627\u062c\u0632\u0627\u06cc UI \u0631\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u0628\u0633\u062a\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AA%D8%B3%D8%AA_%D8%A8%D8%B5%D8%B1%DB%8C_%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u0646 \u0628\u0633\u062a\u0647 \u0627\u0632 \u0686\u0646\u062f\u06cc\u0646 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<ul>\n<li>\n<code>jest<\/code>: \u0645\u0627 \u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f \u0645\u0648\u0627\u0631\u062f \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<li>\n<code>jest-html-reporter<\/code>: \u0645\u0627 \u06cc\u06a9 \u06af\u0632\u0627\u0631\u0634\u06af\u0631 \u0633\u0641\u0627\u0631\u0634\u06cc \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0646\u0634\u0627\u0646 \u062f\u0647\u06cc\u0645 \u06a9\u062f\u0627\u0645 \u062a\u0633\u062a \u0647\u0627\u06cc \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u0646\u0627\u0645\u0648\u0641\u0642 \u0647\u0633\u062a\u0646\u062f.<\/li>\n<li>\n<code>jest-image-snapshot<\/code>: \u0645\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0628\u0631\u0627\u06cc \u06af\u0631\u0641\u062a\u0646 \u0635\u0641\u062d\u0647 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u0648 \u0628\u0631\u0631\u0633\u06cc \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0628\u06cc\u0646 \u062a\u0633\u062a \u0647\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<li>\n<code>jest-puppeteer-docker<\/code>: \u0645\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc Puppeteer \u062f\u0631 Docker \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<li>\n<code>puppeteer<\/code>: \u0645\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0628\u0631\u0627\u06cc \u062a\u0639\u0627\u0645\u0644 \u0628\u0627 \u0645\u0631\u0648\u0631\u06af\u0631 \u0628\u0631\u0627\u06cc \u0628\u0627\u0632 \u06a9\u0631\u062f\u0646 \u0635\u0641\u062d\u0647 \u0628\u0631\u0627\u06cc \u0628\u0631\u0631\u0633\u06cc \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0628\u0635\u0631\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%D8%B4_%D9%86%DB%8C%D8%A7%D8%B2%D9%87%D8%A7\"><\/span>\n<p>  <strong>\u067e\u06cc\u0634 \u0646\u06cc\u0627\u0632\u0647\u0627<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0642\u0628\u0644 \u0627\u0632 \u0627\u062c\u0631\u0627\u06cc \u062a\u0633\u062a\u060c \u0628\u0627\u06cc\u062f Docker \u0631\u0627 \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645.  \u0633\u0627\u062f\u0647 \u062a\u0631\u06cc\u0646 \u0631\u0627\u0647 \u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0622\u0646 \u0646\u0635\u0628 Docker Desktop \u0627\u0633\u062a.  \u0645\u0627 \u0647\u0645\u0686\u0646\u06cc\u0646 \u0628\u0627\u06cc\u062f \u06a9\u062a\u0627\u0628 \u062f\u0627\u0633\u062a\u0627\u0646 \u0631\u0627 \u0627\u0632 \u0631\u0648\u06cc \u0628\u0633\u0627\u0632\u06cc\u0645 <code>core<\/code> \u0628\u0633\u062a\u0647 \u062a\u0627 \u0628\u062a\u0648\u0627\u0646\u06cc\u0645 \u0627\u0632 \u0622\u0646 \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u0645.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D8%A8%D9%84%D9%87\"><\/span>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0628\u0644\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0627 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc Jest \u0631\u0627 \u0628\u0631\u0627\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0627\u0632 \u062a\u0633\u062a \u0648\u06cc\u0698\u0648\u0627\u0644 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0631\u062f\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">exports<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"na\">preset<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">jest-puppeteer-docker<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"c1\">\/\/ specify a list of setup files to be executed after the test framework has been set up but before any test suites are run.<\/span>\n  <span class=\"na\">setupFilesAfterEnv<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">.\/jest-setup\/test-environment-setup.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span>\n  <span class=\"c1\">\/\/ executed once before any test suites are run<\/span>\n  <span class=\"na\">globalSetup<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/jest-setup\/setup.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"c1\">\/\/ The function will be triggered once after all test suites<\/span>\n  <span class=\"na\">globalTeardown<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/jest-setup\/teardown.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">testMatch<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">**\/?(*.)+(visual.spec).[tj]s?(x)<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span>\n  <span class=\"na\">modulePathIgnorePatterns<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">&lt;rootDir&gt;\/dist\/<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span>\n    <span class=\"c1\">\/\/ add jest-html-reporter to be our costume reporters<\/span>\n  <span class=\"na\">reporters<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n    <span class=\"dl\">'<\/span><span class=\"s1\">default<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">[<\/span>\n      <span class=\"dl\">'<\/span><span class=\"s1\">jest-html-reporter<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">outputPath<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/visual-test-result\/index.html<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">pageTitle<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Test Result<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">includeFailureMsg<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n        <span class=\"c1\">\/\/ Path to a javascript file that should be injected into the test report,<\/span>\n        <span class=\"na\">customScriptPath<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/inject-fail-images.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">],<\/span>\n  <span class=\"p\">],<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0633\u067e\u0633\u060c \u0641\u0627\u06cc\u0644 \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0631\u0627 \u0627\u0632 \u0641\u0627\u06cc\u0644 \u0633\u0627\u062e\u062a Storybook \u0628\u0647 \u0645\u0642\u062f\u0627\u0631\u062f\u0647\u06cc \u0627\u0648\u0644\u06cc\u0647 \u0633\u0631\u0648\u0631 HTTP \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"na\">setup<\/span><span class=\"p\">:<\/span> <span class=\"nx\">setupPuppeteer<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">jest-puppeteer-docker<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">path<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">path<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">http<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">http<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">fs<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">fs<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">server<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">http<\/span><span class=\"p\">.<\/span><span class=\"nx\">createServer<\/span><span class=\"p\">((<\/span><span class=\"nx\">req<\/span><span class=\"p\">,<\/span> <span class=\"nx\">res<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ parse URL<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">url<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nx\">URL<\/span><span class=\"p\">(<\/span><span class=\"nx\">req<\/span><span class=\"p\">.<\/span><span class=\"nx\">url<\/span><span class=\"p\">,<\/span> <span class=\"s2\">`http:\/\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">req<\/span><span class=\"p\">.<\/span><span class=\"nx\">headers<\/span><span class=\"p\">.<\/span><span class=\"nx\">host<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ serve static files from \"static\" directory<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">filePath<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">path<\/span><span class=\"p\">.<\/span><span class=\"nx\">join<\/span><span class=\"p\">(<\/span><span class=\"nx\">__dirname<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/storybook-static<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">url<\/span><span class=\"p\">.<\/span><span class=\"nx\">pathname<\/span><span class=\"p\">);<\/span>\n  <span class=\"nx\">fs<\/span><span class=\"p\">.<\/span><span class=\"nx\">readFile<\/span><span class=\"p\">(<\/span><span class=\"nx\">filePath<\/span><span class=\"p\">,<\/span> <span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">,<\/span> <span class=\"nx\">data<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ if file not found, return 404 error<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">writeHead<\/span><span class=\"p\">(<\/span><span class=\"mi\">404<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Content-Type<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text\/plain<\/span><span class=\"dl\">'<\/span> <span class=\"p\">});<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">write<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">404 Not Found<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">end<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ if file found, return file contents<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">writeHead<\/span><span class=\"p\">(<\/span><span class=\"mi\">200<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">Content-Type<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"nx\">getContentType<\/span><span class=\"p\">(<\/span><span class=\"nx\">filePath<\/span><span class=\"p\">)<\/span> <span class=\"p\">});<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">write<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">end<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">});<\/span>\n\n<span class=\"c1\">\/\/ helper function to get content type based on file extension<\/span>\n<span class=\"kd\">function<\/span> <span class=\"nx\">getContentType<\/span><span class=\"p\">(<\/span><span class=\"nx\">filePath<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">extname<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">path<\/span><span class=\"p\">.<\/span><span class=\"nx\">extname<\/span><span class=\"p\">(<\/span><span class=\"nx\">filePath<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">switch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">extname<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.html<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text\/html<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.css<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text\/css<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text\/javascript<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.json<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">application\/json<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.png<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/png<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.jpg<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.jpeg<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">image\/jpeg<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">default<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">application\/octet-stream<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">exports<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async<\/span> <span class=\"p\">(<\/span><span class=\"nx\">jestConfig<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ start server on port 3000<\/span>\n  <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">__SERVER__<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">server<\/span><span class=\"p\">.<\/span><span class=\"nx\">listen<\/span><span class=\"p\">(<\/span><span class=\"mi\">3000<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nx\">log<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Server started on port 3000<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">});<\/span>\n\n  <span class=\"k\">await<\/span> <span class=\"nx\">setupPuppeteer<\/span><span class=\"p\">(<\/span><span class=\"nx\">jestConfig<\/span><span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0633\u067e\u0633\u060c \u06cc\u06a9 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u067e\u0627\u0631\u06af\u06cc \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.  \u062f\u0631 \u0627\u06cc\u0646 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc\u060c \u0633\u0631\u0648\u0631 HTTP \u0631\u0627 \u0645\u06cc \u0628\u0646\u062f\u06cc\u0645 \u0648 \u0646\u062a\u0627\u06cc\u062c \u062a\u0633\u062a \u0631\u0627 \u062f\u0631 \u0641\u0627\u06cc\u0644 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u06af\u0632\u0627\u0631\u0634\u06af\u0631 \u06a9\u067e\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645.  \u0628\u0631\u0627\u06cc \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0628\u06cc\u0634\u062a\u0631 \u062f\u0631 \u0645\u0648\u0631\u062f \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0648 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u062d\u0630\u0641\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0645\u0633\u062a\u0646\u062f\u0627\u062a \u0631\u0627 \u0645\u0637\u0627\u0644\u0639\u0647 \u06a9\u0646\u06cc\u062f <code>jest-puppeteer-docker<\/code>.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"kd\">const<\/span> <span class=\"nx\">fs<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">fs<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">fse<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">fs-extra<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">path<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">path<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"na\">teardown<\/span><span class=\"p\">:<\/span> <span class=\"nx\">teardownPuppeteer<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">jest-puppeteer-docker<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n<span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">exports<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">globalTeardown<\/span><span class=\"p\">(<\/span><span class=\"nx\">jestConfig<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">__SERVER__<\/span><span class=\"p\">.<\/span><span class=\"nx\">close<\/span><span class=\"p\">();<\/span>\n  <span class=\"k\">await<\/span> <span class=\"nx\">teardownPuppeteer<\/span><span class=\"p\">(<\/span><span class=\"nx\">jestConfig<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">dirname<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">path<\/span><span class=\"p\">.<\/span><span class=\"nx\">join<\/span><span class=\"p\">(<\/span><span class=\"nx\">__dirname<\/span><span class=\"p\">,<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"nx\">fs<\/span><span class=\"p\">.<\/span><span class=\"nx\">copyFileSync<\/span><span class=\"p\">(<\/span>\n    <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">dirname<\/span><span class=\"p\">}<\/span><span class=\"s2\">\/jest-reporters\/inject-fail-images.js`<\/span><span class=\"p\">,<\/span>\n    <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">dirname<\/span><span class=\"p\">}<\/span><span class=\"s2\">\/visual-test-result\/inject-fail-images.js`<\/span>\n  <span class=\"p\">);<\/span>\n\n  <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">fse<\/span><span class=\"p\">.<\/span><span class=\"nx\">copySync<\/span><span class=\"p\">(<\/span>\n      <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">dirname<\/span><span class=\"p\">}<\/span><span class=\"s2\">\/src\/__image_snapshots__\/__diff_output__`<\/span><span class=\"p\">,<\/span>\n      <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">dirname<\/span><span class=\"p\">}<\/span><span class=\"s2\">\/visual-test-result\/__diff_output__`<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">{<\/span>\n        <span class=\"na\">overwrite<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">{}<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0639\u062f \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>jest-puppeteer-docker<\/code> \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc  \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u062f\u06cc\u06af\u0631\u06cc \u0631\u0627 \u0627\u06cc\u0646\u062c\u0627 \u0628\u0628\u06cc\u0646\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"kd\">const<\/span> <span class=\"nx\">getConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">jest-puppeteer-docker\/lib\/config<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">baseConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">getConfig<\/span><span class=\"p\">();<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">customConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Object<\/span><span class=\"p\">.<\/span><span class=\"nx\">assign<\/span><span class=\"p\">(<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"na\">connect<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n      <span class=\"na\">defaultViewport<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">width<\/span><span class=\"p\">:<\/span> <span class=\"mi\">1040<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">height<\/span><span class=\"p\">:<\/span> <span class=\"mi\">768<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">},<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"na\">browserContext<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">incognito<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">chromiumFlags<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">\u2013ignore-certificate-errors<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">},<\/span>\n  <span class=\"nx\">baseConfig<\/span>\n<span class=\"p\">);<\/span>\n\n<span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">exports<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">customConfig<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062f\u0631 \u0646\u0647\u0627\u06cc\u062a\u060c \u06cc\u06a9 \u062a\u0627\u0628\u0639 \u0633\u0631\u0627\u0633\u0631\u06cc \u0628\u0631\u0627\u06cc \u067e\u06cc\u0645\u0627\u06cc\u0634 \u0628\u0647 \u0635\u0641\u062d\u0647 \u06a9\u062a\u0627\u0628 \u062f\u0627\u0633\u062a\u0627\u0646 \u0648 \u06cc\u06a9 \u062a\u0627\u0628\u0639 \u0633\u0631\u0627\u0633\u0631\u06cc \u062f\u06cc\u06af\u0631 \u0628\u0631\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">toMatchImageSnapshot<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">jest-image-snapshot<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n<span class=\"nx\">jest<\/span><span class=\"p\">.<\/span><span class=\"nx\">setTimeout<\/span><span class=\"p\">(<\/span><span class=\"mi\">10000<\/span><span class=\"p\">);<\/span>\n\n<span class=\"nx\">expect<\/span><span class=\"p\">.<\/span><span class=\"nx\">extend<\/span><span class=\"p\">({<\/span> <span class=\"nx\">toMatchImageSnapshot<\/span> <span class=\"p\">});<\/span>\n\n<span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">goto<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async<\/span> <span class=\"p\">(<\/span><span class=\"nx\">id<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">goto<\/span><span class=\"p\">(<\/span>\n    <span class=\"s2\">`http:\/\/host.docker.internal:3000\/iframe.html?id=<\/span><span class=\"p\">${<\/span><span class=\"nx\">id<\/span><span class=\"p\">}<\/span><span class=\"s2\">&amp;viewMode=story`<\/span>\n  <span class=\"p\">);<\/span>\n  <span class=\"k\">await<\/span> <span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">waitForNavigation<\/span><span class=\"p\">({<\/span>\n    <span class=\"na\">waitUntil<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">networkidle0<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">testUI<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">waitForSelector<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">#root<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">previewHtml<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">$<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">body<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n  <span class=\"nx\">expect<\/span><span class=\"p\">(<\/span><span class=\"k\">await<\/span> <span class=\"nx\">previewHtml<\/span><span class=\"p\">.<\/span><span class=\"nx\">screenshot<\/span><span class=\"p\">()).<\/span><span class=\"nx\">toMatchImageSnapshot<\/span><span class=\"p\">();<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%DA%AF%D8%B2%D8%A7%D8%B1%D8%B4%DA%AF%D8%B1_%D8%A7%D8%B3%D8%AA\"><\/span>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u06af\u0632\u0627\u0631\u0634\u06af\u0631 \u0627\u0633\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u067e\u0633 \u0627\u0632 \u0627\u062a\u0645\u0627\u0645 \u062a\u0633\u062a\u060c \u0645\u0639\u0645\u0648\u0644\u0627\u064b \u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u0645 \u0646\u062a\u0627\u06cc\u062c \u0622\u0632\u0645\u0627\u06cc\u0634 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u0645.  \u0627\u06af\u0631 \u062a\u0633\u062a \u0647\u0627\u06cc \u0646\u0627\u0645\u0648\u0641\u0642 \u0648\u062c\u0648\u062f \u062f\u0627\u0634\u062a\u0647 \u0628\u0627\u0634\u062f\u060c \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u0645 \u0646\u062a\u06cc\u062c\u0647 \u0645\u0642\u0627\u06cc\u0633\u0647 \u0631\u0627 \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u0645\u0627\u06cc\u0634 \u062f\u0647\u06cc\u0645 <code>packages\/visual-test\/visual-test-result\/<\/code>.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">addEventListener<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">DOMContentLoaded<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"p\">[...<\/span><span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">querySelectorAll<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">.failureMsg<\/span><span class=\"dl\">'<\/span><span class=\"p\">)].<\/span><span class=\"nx\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">fail<\/span><span class=\"p\">,<\/span> <span class=\"nx\">i<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">imagePath<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`__diff_output__\/<\/span><span class=\"p\">${<\/span>\n      <span class=\"p\">(<\/span><span class=\"nx\">fail<\/span><span class=\"p\">.<\/span><span class=\"nx\">textContent<\/span><span class=\"p\">.<\/span><span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">__diff_output__\/<\/span><span class=\"dl\">'<\/span><span class=\"p\">)[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">||<\/span> <span class=\"dl\">''<\/span><span class=\"p\">).<\/span><span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">png<\/span><span class=\"dl\">'<\/span><span class=\"p\">)[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n    <span class=\"p\">}<\/span><span class=\"s2\">png`<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">imagePath<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">div<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">createElement<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">div<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">div<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">margin-top: 16px<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">a<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">createElement<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">a<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">href<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">imagePath<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">_blank<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">img<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">createElement<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">img<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">img<\/span><span class=\"p\">.<\/span><span class=\"nx\">src<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">imagePath<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">;<\/span>\n      <span class=\"nx\">img<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">width: 100%<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">appendChild<\/span><span class=\"p\">(<\/span><span class=\"nx\">img<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">div<\/span><span class=\"p\">.<\/span><span class=\"nx\">appendChild<\/span><span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">fail<\/span><span class=\"p\">.<\/span><span class=\"nx\">appendChild<\/span><span class=\"p\">(<\/span><span class=\"nx\">div<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">});<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D8%B1%D8%AF%D9%86_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7\"><\/span>\n<p>  <strong>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u062a\u0633\u062a \u0647\u0627<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0627\u06cc \u0627\u0641\u0632\u0648\u062f\u0646 \u062a\u0633\u062a\u200c\u0647\u0627\u06cc \u062c\u062f\u06cc\u062f\u060c \u0645\u0639\u0645\u0648\u0644\u0627\u064b \u06af\u0631\u0641\u062a\u0646 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0634\u0627\u062a \u0627\u0632 \u0647\u0631 \u0635\u0641\u062d\u0647 \u06a9\u062a\u0627\u0628 \u062f\u0627\u0633\u062a\u0627\u0646 \u0622\u0633\u0627\u0646\u200c\u062a\u0631 \u0627\u0633\u062a.  \u0628\u0647 \u0645\u062b\u0627\u0644 \u0632\u06cc\u0631 \u0646\u06af\u0627\u0647 \u06a9\u0646\u06cc\u062f\u060c \u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u0627 \u06cc\u06a9 \u062c\u0632\u0621 \u062f\u06a9\u0645\u0647 \u0628\u0627 5 \u0635\u0641\u062d\u0647 \u0645\u062e\u062a\u0644\u0641 \u062f\u0627\u0631\u06cc\u0645.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/05\/\u0628\u0647\u0628\u0648\u062f-\u0633\u0627\u0632\u06af\u0627\u0631\u06cc-\u062a\u0633\u062a-\u0628\u0635\u0631\u06cc-\u0633\u06cc\u0633\u062a\u0645-\u0637\u0631\u0627\u062d\u06cc-\u0628\u0627-Docker.png\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"549\" title=\"\"><\/p>\n<p>\u0633\u067e\u0633\u060c \u0645\u0627 \u062a\u0633\u062a \u0645\u0648\u0631\u062f\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0647\u0631 \u0635\u0641\u062d\u0647 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"nx\">describe<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Button<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nx\">test<\/span><span class=\"p\">.<\/span><span class=\"nx\">each<\/span><span class=\"p\">([[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">variants<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">size<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">disabled<\/span><span class=\"dl\">'<\/span><span class=\"p\">],<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">full-width<\/span><span class=\"dl\">'<\/span><span class=\"p\">]])(<\/span>\n    <span class=\"dl\">'<\/span><span class=\"s1\">%p<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n    <span class=\"k\">async<\/span> <span class=\"p\">(<\/span><span class=\"nx\">variant<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">goto<\/span><span class=\"p\">(<\/span><span class=\"s2\">`buttons-button--<\/span><span class=\"p\">${<\/span><span class=\"nx\">variant<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">page<\/span><span class=\"p\">.<\/span><span class=\"nx\">evaluateHandle<\/span><span class=\"p\">(<\/span><span class=\"s2\">`document.querySelector(\".c-button\")`<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">testUI<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">});<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0647\u0645\u0686\u0646\u06cc\u0646 \u0627\u06af\u0631 \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u062f \u0628\u0639\u062f \u0627\u0632 \u0639\u0645\u0644 \u0639\u0646\u0635\u0631 \u062e\u0627\u0635\u06cc \u0627\u0632 \u0635\u0641\u062d\u0647 \u0646\u0645\u0627\u06cc\u0634 \u0628\u06af\u06cc\u0631\u06cc\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u0632 Puppeteer API \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AF%D8%B1_%D8%AD%D8%A7%D9%84_%D8%A7%D8%AC%D8%B1%D8%A7_%D8%AA%D8%B3%D8%AA\"><\/span>\n<p>  \u062f\u0631 \u062d\u0627\u0644 \u0627\u062c\u0631\u0627 \u062a\u0633\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc \u062a\u0633\u062a \u0647\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0645\u0631\u0627\u062d\u0644 \u0632\u06cc\u0631 \u0631\u0627 \u062f\u0646\u0628\u0627\u0644 \u06a9\u0646\u06cc\u062f:<\/p>\n<ul>\n<li>\u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u06a9\u062a\u0627\u0628 \u062f\u0627\u0633\u062a\u0627\u0646 \u0628\u0633\u0627\u0632\u06cc\u062f <code>yarn workspace @contra-ui\/vue build-storybook --quiet<\/code>\n<\/li>\n<li>\u0641\u0627\u06cc\u0644 \u0633\u0627\u062e\u062a Storybook \u0631\u0627 \u0627\u0632 \u06a9\u067e\u06cc \u06a9\u0646\u06cc\u062f <code>core<\/code> \u0628\u0633\u062a\u0647 \u0628\u0647 <code>visual-test<\/code> \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 <code>yarn workspace @contra-ui\/visual-test copy<\/code>\n<\/li>\n<li>\u062f\u0633\u06a9\u062a\u0627\u067e Docker \u062e\u0648\u062f \u0631\u0627 \u0628\u0627\u0632 \u06a9\u0646\u06cc\u062f \u0648 \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0622\u0646 \u062a\u0633\u062a \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f <code>yarn workspace @contra-ui\/visual-test test<\/code>.  \u0627\u06af\u0631 \u0628\u0631\u0627\u06cc \u0627\u0648\u0644\u06cc\u0646 \u0628\u0627\u0631 \u062a\u0633\u062a \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f\u060c \u0645\u062f\u062a\u06cc \u0637\u0648\u0644 \u0645\u06cc \u06a9\u0634\u062f \u062a\u0627 \u062f\u0627\u06a9\u0631 \u062a\u0635\u0648\u06cc\u0631 \u0631\u0627 \u062f\u0627\u0646\u0644\u0648\u062f \u06a9\u0646\u062f \u0648 \u0638\u0631\u0641 \u0631\u0627 \u0628\u0633\u0627\u0632\u062f.<\/li>\n<li>\u0646\u062a\u06cc\u062c\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634 \u0631\u0627 \u062f\u0631 <code>packages\/visual-test\/src\/image_snapshots<\/code> \u0628\u0631\u0627\u06cc \u062f\u06cc\u062f\u0646 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0634\u0627\u062a \u0627\u06af\u0631 \u0645\u0648\u0631\u062f \u0627\u0646\u062a\u0638\u0627\u0631 \u0627\u0633\u062a<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C_%D8%AA%D8%B3%D8%AA_%D9%87%D8%A7%DB%8C_%D8%B4%DA%A9%D8%B3%D8%AA_%D8%AE%D9%88%D8%B1%D8%AF%D9%87\"><\/span>\n<p>  <strong>\u0628\u0631\u0631\u0633\u06cc \u062a\u0633\u062a \u0647\u0627\u06cc \u0634\u06a9\u0633\u062a \u062e\u0648\u0631\u062f\u0647<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0627\u06cc \u0628\u0631\u0631\u0633\u06cc \u062a\u0633\u062a \u0646\u0627\u0645\u0648\u0641\u0642 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0641\u0627\u06cc\u0644 \u06af\u0632\u0627\u0631\u0634 HTML \u0631\u0627 \u062f\u0631 \u0622\u0646 \u0628\u0627\u0632 \u06a9\u0646\u06cc\u062f <code>packages\/visual-test\/visual-test-result\/<\/code>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/05\/1683384605_727_\u0628\u0647\u0628\u0648\u062f-\u0633\u0627\u0632\u06af\u0627\u0631\u06cc-\u062a\u0633\u062a-\u0628\u0635\u0631\u06cc-\u0633\u06cc\u0633\u062a\u0645-\u0637\u0631\u0627\u062d\u06cc-\u0628\u0627-Docker.png\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"520\" title=\"\"><\/p>\n<p>Jest \u062a\u0641\u0627\u0648\u062a \u0647\u0627 \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u067e\u0648\u0634\u0647 \u0642\u0631\u0627\u0631 \u0645\u06cc \u062f\u0647\u062f \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u062f\u0631 \u0622\u0646 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f <code>packages\/visual-test\/src\/__image_snapshots__\/__diff_output__\/<\/code>.  \u0628\u0631\u0627\u06cc \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u0622\u0632\u0645\u0648\u0646\u060c \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0622\u0646 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>-u<\/code> \u067e\u0631\u0686\u0645: <code>yarn workspace @contra-ui\/visual-test test<\/code><\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_CI\"><\/span>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc CI<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0633\u067e\u0633 \u0645\u0631\u062d\u0644\u0647 \u0627\u06cc \u0631\u0627 \u06a9\u0647 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0627\u0646\u062c\u0627\u0645 \u062f\u0627\u062f\u0647 \u0627\u06cc\u0645 \u0628\u0647 CI \u0645\u0646\u062a\u0642\u0644 \u0645\u06cc \u06a9\u0646\u06cc\u0645.  \u0633\u0647 \u0645\u0631\u062d\u0644\u0647 \u0627\u0636\u0627\u0641\u06cc \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f \u06a9\u0647 \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f \u062e\u0648\u062f\u06a9\u0627\u0631 \u0631\u0648\u0627\u0628\u0637 \u0639\u0645\u0648\u0645\u06cc \u0628\u0631\u0627\u06cc \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc \u062a\u0633\u062a \u0647\u0627\u06cc \u0646\u0627\u0645\u0648\u0641\u0642 \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632 \u0627\u0633\u062a.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">build-pr<\/span>\n<span class=\"na\">on<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">pull_request<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">branches<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s\">main<\/span>\n\n<span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">install-dependency<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install depedency<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Checkout repository<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v3<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install Node.js<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/setup-node@v3<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">node-version<\/span><span class=\"pi\">:<\/span> <span class=\"m\">16<\/span>\n          <span class=\"na\">cache<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">yarn'<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install dependencies<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn --immutable<\/span>\n\n  <span class=\"na\">visual-tests<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Visual tests<\/span>\n    <span class=\"na\">needs<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"nv\">install-dependency<\/span><span class=\"pi\">]<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Checkout repository<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v3<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install Node.js<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/setup-node@v3<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">node-version<\/span><span class=\"pi\">:<\/span> <span class=\"m\">16<\/span>\n          <span class=\"na\">cache<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">yarn'<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install dependencies<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn --immutable<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Run Lerna bootstrap<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn lerna:bootstrap<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Build Storybook<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn workspace @contra-ui\/vue build-storybook --quiet<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Copy Storybook for visual tests<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn workspace @contra-ui\/visual-test copy<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Run visual tests<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yarn workspace @contra-ui\/visual-test test -u<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Check for any snapshots changes<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">sh scripts\/porcelain.sh<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Set patch branch name<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">failure()<\/span>\n        <span class=\"na\">id<\/span><span class=\"pi\">:<\/span> <span class=\"s\">vars<\/span>\n        <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">echo ::set-output name=branch-name::\"visual-snapshots\/${{ github.head_ref }}\"<\/span>\n\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Create pull request with new snapshots<\/span>\n        <span class=\"na\">if<\/span><span class=\"pi\">:<\/span> <span class=\"s\">failure()<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">peter-evans\/create-pull-request@v4<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">commit-message<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">test(visual):<\/span><span class=\"nv\"> <\/span><span class=\"s\">update<\/span><span class=\"nv\"> <\/span><span class=\"s\">snapshots'<\/span>\n          <span class=\"na\">title<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">update<\/span><span class=\"nv\"> <\/span><span class=\"s\">visual<\/span><span class=\"nv\"> <\/span><span class=\"s\">snapshots:<\/span><span class=\"nv\"> <\/span><span class=\"s\">${{<\/span><span class=\"nv\"> <\/span><span class=\"s\">github.event.pull_request.title<\/span><span class=\"nv\"> <\/span><span class=\"s\">}}'<\/span>\n          <span class=\"na\">body<\/span><span class=\"pi\">:<\/span> <span class=\"s\">This is an auto-generated PR with visual snapshot updates for \\#${{ github.event.number }}.<\/span>\n          <span class=\"na\">labels<\/span><span class=\"pi\">:<\/span> <span class=\"s\">automated pr<\/span>\n          <span class=\"na\">branch<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ steps.vars.outputs.branch-name }}<\/span>\n          <span class=\"na\">base<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${{ github.head_ref }}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<ul>\n<li>\n<p>\u06af\u0627\u0645 <code>name: Check for any snapshots changes<\/code><br \/>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647 \u0628\u0631\u0631\u0633\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 \u06a9\u0647 \u0622\u06cc\u0627 commit \u062c\u062f\u06cc\u062f\u06cc \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f \u06cc\u0627 \u062e\u06cc\u0631.  \u0686\u0648\u0646 \u0645\u0627 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0631\u062f\u06cc\u0645 <code>-u<\/code> \u067e\u0631\u0686\u0645\u060c \u0628\u0647 \u0637\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0641\u0627\u06cc\u0644 \u0645\u0648\u062c\u0648\u062f \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc \u062f\u0647\u062f.  \u0648\u0642\u062a\u06cc \u0647\u0631 \u0641\u0627\u06cc\u0644 \u0627\u0635\u0644\u0627\u062d \u0634\u062f\u0647 \u0627\u06cc \u0631\u0627 \u067e\u06cc\u062f\u0627 \u0645\u06cc \u06a9\u0646\u06cc\u0645\u060c \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0628\u0627 \u06cc\u06a9 \u06a9\u062f \u062e\u0631\u0648\u062c \u063a\u06cc\u0631 \u0635\u0641\u0631 \u062e\u0627\u0631\u062c \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<pre class=\"highlight shell\"><code><span class=\"nb\">echo<\/span> <span class=\"s2\">\"--------\"<\/span>\n<span class=\"nb\">echo<\/span> <span class=\"s2\">\"Checking for uncommitted build outputs...\"<\/span>\n<span class=\"k\">if<\/span> <span class=\"o\">[<\/span> <span class=\"nt\">-z<\/span> <span class=\"s2\">\"<\/span><span class=\"si\">$(<\/span>git status <span class=\"nt\">--porcelain<\/span><span class=\"si\">)<\/span><span class=\"s2\">\"<\/span> <span class=\"o\">]<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">then\n    <\/span><span class=\"nb\">echo<\/span> <span class=\"s2\">\"Working copy is clean\"<\/span>\n<span class=\"k\">else\n    <\/span><span class=\"nb\">echo<\/span> <span class=\"s2\">\"Another Pull Request has been created. Please check it to accept or reject the visual changes.\"<\/span>\n    git status\n    <span class=\"nb\">exit <\/span>1\n<span class=\"k\">fi<\/span>\n<\/code><\/pre>\n<\/li>\n<li>\n<p>\u06af\u0627\u0645 <code>name: Set patch branch name<\/code><br \/>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647 \u0627\u06af\u0631 \u0645\u0631\u0627\u062d\u0644 \u0642\u0628\u0644\u06cc \u0634\u06a9\u0633\u062a \u062e\u0648\u0631\u062f\u0647 \u0628\u0627\u0634\u062f\u060c \u0646\u0627\u0645 \u0634\u0627\u062e\u0647 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0645\u062a\u063a\u06cc\u0631 \u062e\u0631\u0648\u062c\u06cc \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<\/li>\n<li>\n<p>\u06af\u0627\u0645 <code>name: Create pull request with new snapshots<\/code><br \/>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647\u060c \u0645\u0627 \u06cc\u06a9 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0634\u0634 \u0628\u0631\u0627\u06cc \u0634\u0627\u062e\u0647 \u0634\u06a9\u0633\u062a \u062e\u0648\u0631\u062f\u0647 \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc \u06a9\u0646\u06cc\u0645\u060c \u0627\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647 \u0628\u0631\u0627\u06cc \u0645\u0627 \u0622\u0633\u0627\u0646 \u062a\u0631 \u0645\u06cc \u06a9\u0646\u062f \u06a9\u0647 \u0628\u0628\u06cc\u0646\u06cc\u0645 \u0686\u0647 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u062a\u063a\u06cc\u06cc\u0631 \u06a9\u0631\u062f\u0647 \u0627\u0633\u062a \u0648 \u062f\u0631 \u0635\u0648\u0631\u062a \u0627\u0646\u062a\u0638\u0627\u0631 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u0645 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0628\u067e\u0630\u06cc\u0631\u06cc\u0645\u060c \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0645\u062b\u0627\u0644 \u062f\u0631\u062e\u0648\u0627\u0633\u062a pull \u0627\u0633\u062a:<\/p>\n<\/li>\n<\/ul>\n<p>\u0647\u0645\u0686\u0646\u06cc\u0646 \u0628\u0627\u06cc\u062f \u0645\u062c\u0648\u0632\u0647\u0627\u06cc \u06af\u0631\u062f\u0634 \u06a9\u0627\u0631 \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 \u0635\u0641\u062d\u0647 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0628\u0647 \u0631\u0648\u0632 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0627\u06a9\u0634\u0646 GitHub \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0634\u0634 \u0641\u0639\u0627\u0644 \u0634\u0648\u062f.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/nabfollower.com\/blog\/wp-content\/uploads\/2023\/05\/1683384605_922_\u0628\u0647\u0628\u0648\u062f-\u0633\u0627\u0632\u06af\u0627\u0631\u06cc-\u062a\u0633\u062a-\u0628\u0635\u0631\u06cc-\u0633\u06cc\u0633\u062a\u0645-\u0637\u0631\u0627\u062d\u06cc-\u0628\u0627-Docker.png\" alt=\"\u062a\u0648\u0636\u06cc\u062d\u0627\u062a \u062a\u0635\u0648\u06cc\u0631\" loading=\"lazy\" width=\"800\" height=\"336\" title=\"\"><\/p>\n<p>\u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062f\u0627\u06a9\u0631 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u0648\u0627\u0642\u0639\u0627\u064b \u0628\u0647 \u0637\u0648\u0631 \u06a9\u0627\u0645\u0644 \u0645\u0648\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0642\u0631\u0627\u0631 \u06af\u06cc\u0631\u062f \u062a\u0627 \u0622\u0632\u0645\u0627\u06cc\u0634\u0627\u062a \u0628\u0635\u0631\u06cc \u0645\u0627 \u0631\u0627 \u0647\u0645 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u0648 \u0647\u0645 \u062f\u0631 CI \u0633\u0627\u0632\u06af\u0627\u0631\u062a\u0631 \u06a9\u0646\u062f.  \u0627\u0645\u06cc\u062f\u0648\u0627\u0631\u0645 \u0627\u06cc\u0646 \u067e\u0633\u062a \u0628\u0647 \u0634\u0645\u0627 \u0627\u06cc\u062f\u0647 \u0647\u0627\u06cc\u06cc \u062f\u0627\u062f\u0647 \u0628\u0627\u0634\u062f.  \u0634\u0645\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u06a9\u062f \u06a9\u0627\u0645\u0644 \u0631\u0627 \u062f\u0631 \u0627\u06cc\u0646 \u0645\u062e\u0632\u0646 GitHub \u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u062a\u0633\u062a \u0628\u0635\u0631\u06cc \u06cc\u06a9 \u0631\u0627\u0647 \u0639\u0627\u0644\u06cc \u0628\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u0645\u0624\u0644\u0641\u0647 UI \u0634\u0645\u0627 \u062f\u0631 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0637\u0631\u0627\u062d\u06cc \u0627\u0633\u062a. \u0628\u0627 \u0627\u06cc\u0646 \u062d\u0627\u0644\u060c \u0647\u0646\u06af\u0627\u0645 \u06a9\u0627\u0631 \u0628\u0631 \u0631\u0648\u06cc \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 \u0628\u0627 \u0686\u0646\u062f\u06cc\u0646 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0648 \u062a\u0644\u0627\u0634 \u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0628\u0647 \u0635\u0648\u0631\u062a \u0645\u062d\u0644\u06cc \u06cc\u0627 CI\u060c \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0645\u0634\u06a9\u0644 \u0633\u0627\u0632 \u0634\u0648\u062f\u060c \u0632\u06cc\u0631\u0627 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u0628\u0631\u0627\u06cc \u0647\u0631 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u0645\u062a\u0641\u0627\u0648\u062a \u0628\u0647 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-21663","post","type-post","status-publish","format-standard","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/21663","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=21663"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/21663\/revisions"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=21663"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=21663"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=21663"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}