{"id":21754,"date":"2018-06-27T16:43:11","date_gmt":"2018-06-27T16:43:11","guid":{"rendered":"http:\/\/testing_functional_ui_the_cloudinary_way"},"modified":"2024-06-06T12:36:49","modified_gmt":"2024-06-06T19:36:49","slug":"testing_functional_ui_the_cloudinary_way","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way","title":{"rendered":"Testing Functional UI the Cloudinary Way"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>You may have heard that we recently launched our <a href=\"https:\/\/cloudinary.com\/products\/digital_asset_management\">Digital Asset Management<\/a> (DAM) system. On top of other challenges, that was our first launch targeted at the nondeveloper audience, to whom the UI is a central element of a product\u2019s capabilities.<\/p>\n<p>Releasing robust products on time require comprehensive automated testing at all levels: Unit , API, and UI testing. This post describes our solution for end-to-end UI automation testing, which serves both QA engineers and front-end developers in minimizing bugs in releases and in speeding up testing for faster development and shorter release cycles.<\/p>\n<h2>Objectives<\/h2>\n<p>Right off the bat, we had these objectives in mind:<\/p>\n<ul>\n<li>Create a JavaScript-based test automation framework with Node.js so that  developers can stay in their \u201ccomfort zone.\u201d<\/li>\n<li>Facilitate root-cause error analysis through informative reports for a thorough investigation of failed tests. The reports must be human friendly, containing as many relevant details as possible, such as logs, screenshots, and page sources.<\/li>\n<li>Execute in parallel for fast, continuous integration feedback.<\/li>\n<li>Build configurable test suites for various platforms and setups (deployment, pull requests, on demand, and such).<\/li>\n<li>Enhance browser coverage by running tests on various browsers with local and remote setups.<\/li>\n<li>Develop reusable components with a functional interface that mimics user actions and that supports test maintenance and readability.<\/li>\n<\/ul>\n<h2>Implementation<\/h2>\n<p>Let\u2019s now introduce our new test automation framework <code>wdio-allure-ts<\/code>, which promises to help you quickly start authoring end-to-end JavaScript ui tests with a useful, informative report.<\/p>\n<p>First, some background: We considered and tested many other leading testing solutions, such as <em><a href=\"https:\/\/github.com\/webdriverio\/wdio-allure-reporter\">Allure Reporter<\/a><\/em>, which offers a pleasing and functional design. You can also easily integrate it with Node.js and Jenkins. However, Allure Reporter falls short in several ways:<\/p>\n<ul>\n<li>The Reporter logs WebDriver commands (<code>GET<\/code> and <code>POST<\/code>) that give no clues on failures.<\/li>\n<li>Page-source and browser-console logs of failed tests are absent in the reports.<\/li>\n<li>Most of the errors reflect timeouts only. No clear failure reasons.\n<a href=\"http:\/\/webdriver.io\/\">WebdriverIO<\/a>, a Node.js testing utility, meets our needs.  With a sizable community coupled with simple setups for configuration and customization, WebdriverIO supports third-party integrations (automation testing reports, test runners), Page Object Model, and synchronous execution.\nAlso, we chose <a href=\"https:\/\/www.typescriptlang.org\">TypeScript<\/a> instead of plain JavaScript for IntelliSense support, which spells fast and seamless development with typed variables..\nSubsequently, we blended those tools into our new, open-source solution for end-to-end functional testing: <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts\"><code>wdio-allure-ts<\/code><\/a>.That solution wraps the most common WebdriverIO actions, generating intuitive error messages in case of failure, custom logs for the Allure Reporter, more validations for enhanced stability, and last, but not least, IntelliSense.<\/li>\n<\/ul>\n<h2>Example With Pure WebdriverIO<\/h2>\n<p>Now take a look at an example of an action that, after validating that a particular element is visible, clicks it, logs every step to the Reporter, and throws meaningful errors for failures, if any.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n <span class=\"hljs-keyword\">const<\/span> selector: string = <span class=\"hljs-string\">\"someSelector\"<\/span>;\n logger(<span class=\"hljs-string\">`Click an element with selector: <span class=\"hljs-subst\">${selector}<\/span>`<\/span>);\n <span class=\"hljs-keyword\">try<\/span> {\n   logger(<span class=\"hljs-string\">`Validate element with selector <span class=\"hljs-subst\">${selector}<\/span> is visible`<\/span>);\n   browser.isVisible(selector);\n } <span class=\"hljs-keyword\">catch<\/span> (error) {\n   <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Error<\/span>(<span class=\"hljs-string\">`Tried to click not visible element, <span class=\"hljs-subst\">${error}<\/span>`<\/span>);\n }\n\n <span class=\"hljs-keyword\">try<\/span> {\n   logger(<span class=\"hljs-string\">\"Perform click action\"<\/span>);\n   browser.click(selector);\n } <span class=\"hljs-keyword\">catch<\/span> (error) {\n   <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Error<\/span>(\n     <span class=\"hljs-string\">`Failed to click an element by given selector <span class=\"hljs-subst\">${selector}<\/span>. <span class=\"hljs-subst\">${error}<\/span>`<\/span>\n   );\n }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Example with <code>wdio-allure-ts<\/code>:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">const<\/span> selector: string = <span class=\"hljs-string\">\"someSelector\"<\/span>;\nBrowserUtils.click(selector);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You can see that our new framework offers the same capabilities with much cleaner code. Because the framework automatically handles logging and error reporting,  automation developers can focus on testing the business logic.\nYou can add more report logs with a simple Reporter API for log levels: step, debug, error, info, and warning. The logs are displayed on the terminal and reflected in  the report.\nExample:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">\n<span class=\"hljs-keyword\">import<\/span> { Reporter } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'wdio-allure-ts'<\/span>;\nReporter.step(<span class=\"hljs-string\">'Step log entry'<\/span>);\nReporter.error(<span class=\"hljs-string\">'Error log entry'<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p><strong>Terminal Output<\/strong><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/f_auto,q_auto\/blog\/wdio-allure-ts\/terminal_report.png\" alt=\"Terminal Output\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1096\" height=\"498\"\/>\nNote the difference in the highlighted areas between the original report and the one created with <code>wdio-allure-ts<\/code>.\n<strong>Original Report<\/strong><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/f_auto,q_auto\/blog\/wdio-allure-ts\/allure_report_origin.png\" alt=\"Original Report\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2880\" height=\"1522\"\/><\/p>\n<p><strong>wdio-allure-ts Report(<a href=\"https:\/\/cloudinary.github.io\/wdio-allure-ts-example\/allure-report\/index.html\">live report example<\/a>):<\/strong><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/f_auto,q_auto\/blog\/wdio-allure-ts\/allure_report_updated.png\" alt=\"wdio-allure-ts Report\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2862\" height=\"1072\"\/><\/p>\n<h2>That\u2019s It. Ready to Try?<\/h2>\n<p>For you to take a crack at it, we\u2019ve created a <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\">sample project<\/a> with a quick introduction to our framework and its usage on a real-world application\nThe project contains examples for the following:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/tree\/master\/src\/tests\">Tests<\/a> for implementation.<\/li>\n<li>\n<a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/tree\/master\/src\/pages\">Page Object Model<\/a>.<\/li>\n<li>Allure Reporter, integrated and <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/0edb5c064cee25ecd41cc85b41aa1cc7caca7ae0\/wdio.conf.js#L159\">configured<\/a> for attaching screenshots, <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/0edb5c064cee25ecd41cc85b41aa1cc7caca7ae0\/wdio.conf.js#L260\">browser logs<\/a>, and <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/0edb5c064cee25ecd41cc85b41aa1cc7caca7ae0\/wdio.conf.js#L268\">HTML source<\/a> on test failures.<\/li>\n<li>Configurations for <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/master\/wdio.dev.conf.js\">local<\/a> and <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/master\/wdio.ci.conf.js\">CI execution<\/a>.<\/li>\n<li>Selenium grid for test execution.<\/li>\n<\/ul>\n<p>Just clone the repo, read the <a href=\"https:\/\/github.com\/cloudinary\/wdio-allure-ts-example\/blob\/master\/README.md\">README<\/a>, and create new tests according to the examples.\nWe\u2019d love to hear your thoughts and ideas for integrating <code>wdio-allure-ts<\/code> into your testing workflow. Send them to us in the Comments section below please.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":21755,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[177],"class_list":["post-21754","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-javascript"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Automated UI Testing with End-to-End JavaScript Tests<\/title>\n<meta name=\"description\" content=\"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing Functional UI the Cloudinary Way\" \/>\n<meta property=\"og:description\" content=\"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-27T16:43:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-06T19:36:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1540\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Testing Functional UI the Cloudinary Way\",\"datePublished\":\"2018-06-27T16:43:11+00:00\",\"dateModified\":\"2024-06-06T19:36:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA\",\"keywords\":[\"Javascript\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2018\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\",\"url\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\",\"name\":\"Automated UI Testing with End-to-End JavaScript Tests\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA\",\"datePublished\":\"2018-06-27T16:43:11+00:00\",\"dateModified\":\"2024-06-06T19:36:49+00:00\",\"description\":\"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA\",\"width\":1540,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Testing Functional UI the Cloudinary Way\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Automated UI Testing with End-to-End JavaScript Tests","description":"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way","og_locale":"en_US","og_type":"article","og_title":"Testing Functional UI the Cloudinary Way","og_description":"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.","og_url":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way","og_site_name":"Cloudinary Blog","article_published_time":"2018-06-27T16:43:11+00:00","article_modified_time":"2024-06-06T19:36:49+00:00","og_image":[{"width":1540,"height":847,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts-jpg?_i=AA","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way"},"author":{"name":"","@id":""},"headline":"Testing Functional UI the Cloudinary Way","datePublished":"2018-06-27T16:43:11+00:00","dateModified":"2024-06-06T19:36:49+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA","keywords":["Javascript"],"inLanguage":"en-US","copyrightYear":"2018","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way","url":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way","name":"Automated UI Testing with End-to-End JavaScript Tests","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA","datePublished":"2018-06-27T16:43:11+00:00","dateModified":"2024-06-06T19:36:49+00:00","description":"This post describes a solution for automated end-to-end UI testing, which serves both QA and developers in minimizing bugs in releases and speeding up testing.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA","width":1540,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/testing_functional_ui_the_cloudinary_way#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Testing Functional UI the Cloudinary Way"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649721899\/Web_Assets\/blog\/wdio-allure-ts\/wdio-allure-ts.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=21754"}],"version-history":[{"count":1,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21754\/revisions"}],"predecessor-version":[{"id":34466,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21754\/revisions\/34466"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/21755"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=21754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=21754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=21754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}