{"id":362,"date":"2020-02-07T12:00:00","date_gmt":"2020-02-07T12:00:00","guid":{"rendered":"http:\/\/yer.ac\/blog\/?p=362"},"modified":"2020-02-20T08:30:22","modified_gmt":"2020-02-20T08:30:22","slug":"%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress","status":"publish","type":"post","link":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/","title":{"rendered":"\u26a1lightning-fast testing of web applications with Cypress"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.cypress.io\/\">Cypress (Cypress.io) <\/a>is an automation framework for web app testing built and configured with Javascript. Automated front-end testing is definitely not new, but Cypress really is something different. It&#8217;s silly fast, requires almost no setup, has quick-to-learn syntax and has a really nice, feature packed test runner. <\/p>\n\n\n\n<p><strong>Why Cypress?<\/strong> I&#8217;ll let you read the summary on the summary page at <a href=\"https:\/\/www.cypress.io\/how-it-works\">cypress<\/a><a href=\"http:\/\/cypress.io\">.io<\/a>, whilst also stealing this image from their blurb<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1089\" height=\"402\" data-attachment-id=\"397\" data-permalink=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/image-6-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&amp;ssl=1\" data-orig-size=\"1089,402\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-6\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=700%2C258&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=700%2C258\" alt=\"\" class=\"wp-image-397\" srcset=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?w=1089&amp;ssl=1 1089w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?resize=300%2C111&amp;ssl=1 300w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?resize=700%2C258&amp;ssl=1 700w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?resize=768%2C284&amp;ssl=1 768w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?resize=800%2C295&amp;ssl=1 800w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p><strong>TL;DR: <\/strong>Why have all those libraries to manage, drivers to install and syntax&#8217;s to remember?! <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Don&#8217;t we already have tons of testing frameworks?<\/h2>\n\n\n\n<p>Yes. I have previously used tooling like Selenium with C#, and know our QA team use paid tooling like Sahi Pro, for a start. <\/p>\n\n\n\n<p>Whilst these tools are OK, they often feel clunky with tooling oddities and not-to-friendly syntax. Supplementary to this, a lot of these tools are Selenium based which means they are all  sharing the same annoyances. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-up-cypress\">Setting up<\/h2>\n\n\n\n<p>To get going with Cypress, simply run the NPM command: <code>npm install cypress --save-dev<\/code> within the folder you want to use Cypress from. Note that Yarn variants are also available and can be found on their site.<\/p>\n\n\n\n<p>If the command executes successfully, you should have a new <code>.\/node_modules<\/code> directory and the package-lock.json.<\/p>\n\n\n\n<p>To setup and open Cypress for the first time, simply execute the command below, whilst in the context of your installation folder.<\/p>\n\n\n\n<p><code>.\/node_modules\/.bin\/cypress open<\/code><\/p>\n\n\n\n<p>This will do a couple of things:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Create a folder named <code>cypress<\/code> within your working directory &#8211; This will be where all your test descriptions and configuration lives<\/li><li>Opens up the Cypress App.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"787\" height=\"379\" data-attachment-id=\"363\" data-permalink=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/image-27\/\" data-orig-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?fit=787%2C379&amp;ssl=1\" data-orig-size=\"787,379\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?fit=700%2C337&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?fit=700%2C337\" alt=\"\" class=\"wp-image-363\" srcset=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?w=787&amp;ssl=1 787w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?resize=300%2C144&amp;ssl=1 300w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?resize=700%2C337&amp;ssl=1 700w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image.png?resize=768%2C370&amp;ssl=1 768w\" sizes=\"auto, (max-width: 787px) 100vw, 787px\" \/><figcaption>Cypress test explorer launched for the first time.<\/figcaption><\/figure>\n\n\n\n<p>Feel free to explore the examples which provide samples of common tests, but we won&#8217;t cover them in this post.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project structure<\/h2>\n\n\n\n<p>If you open the Cypress folder in VS code, you will find the default project files for a Cypress project.<\/p>\n\n\n\n<p><strong>Integration<\/strong>: This folder will contain all the spec files for this project. Creating sub folders within here will be echoed in the test runner. For example, you may have a folder structure like  .\/integration\/cms\/account which contains just the tests for the account functionality. How you structure this is up to you.<\/p>\n\n\n\n<p><strong>Support: <\/strong>The support folder contains 2 files, <code>index.js<\/code> and <code>commands.js<\/code>. The <code>index.js<\/code> file will be ran before every single test fixture and is useful if you need to do something common like reset state. The index file also imports the <code>commands.js<\/code> file.<\/p>\n\n\n\n<p><code>commands.js<\/code> is imported by the index file, and is another place to store common code, but has the advantage that it can be called from any test fixture, at any stage. An example of this could be storing the login method here under a command named <code>DoLogin<\/code> which saves having to define this in every fixture. <\/p>\n\n\n\n<p><strong>Plugins:<\/strong> Contains a single file <code>index.js<\/code> which is a jump-off point for importing or defining changes to how Cypress works. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Diving into testing with a real example<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Creating and running tests<\/h3>\n\n\n\n<p>First of all, I will delete the examples folder. For this post I will be &#8220;testing&#8221; the Twitter desktop site as all my real examples are for enterprise or private software. <\/p>\n\n\n\n<p class=\"has-background has-luminous-vivid-amber-background-color\"><strong>NOTE<\/strong>: This software is not designed for general browsing automation and should only be used against websites you maintain\/own. In fact, a lot of sites try to block this and I actually struggled to find a public site I could use this against consistently! <\/p>\n\n\n\n<p><strong>Create a test fixture\/spec<\/strong><\/p>\n\n\n\n<p>Create a new file underneath the &#8220;Integration folder&#8221; named &#8220;MyTest.spec.js&#8221; the &#8220;.spec&#8221; is a naming standard for defining specifications which I suggest you keep, but isn&#8217;t strict.<\/p>\n\n\n\n<p>The structure of this file should be as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>describe(\"Twitter example tests\", function() {\n  it(\"Page should load\", function() {\n    cy.visit(\"https:\/\/twitter.com\/login\");\n  });\n});\n<\/code><\/pre>\n\n\n\n<p>Each file contains a single description, which in turn can contain many steps. I advise a high level of granularity when writing tests, such as a test spec for testing the login page with several steps is fine, having one that tests your website with hundreds of steps, not so much. <\/p>\n\n\n\n<p>If you save this file, and still have the test runner open, it should have automatically found this new test. If you closed the runner, simply re-run the <code> .\/node_modules\/.bin\/cypress open<\/code> command again.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"774\" height=\"187\" data-attachment-id=\"370\" data-permalink=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/image-1-7\/\" data-orig-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?fit=774%2C187&amp;ssl=1\" data-orig-size=\"774,187\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?fit=700%2C169&amp;ssl=1\" src=\"https:\/\/i2.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?fit=700%2C169\" alt=\"\" class=\"wp-image-370\" srcset=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?w=774&amp;ssl=1 774w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?resize=300%2C72&amp;ssl=1 300w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?resize=700%2C169&amp;ssl=1 700w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-1.png?resize=768%2C186&amp;ssl=1 768w\" sizes=\"auto, (max-width: 774px) 100vw, 774px\" \/><\/figure>\n\n\n\n<p>Clicking on this test will open up a new browser instance (based on the one selected in the drop down &#8211; seen in the top right of the screenshot above). The test runner will open a split-window with the executing tests (and results) on the left, and the browser view on the right.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1149\" height=\"380\" data-attachment-id=\"379\" data-permalink=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/image-4-5\/\" data-orig-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?fit=1149%2C380&amp;ssl=1\" data-orig-size=\"1149,380\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-4\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?fit=700%2C232&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?fit=700%2C232\" alt=\"\" class=\"wp-image-379\" srcset=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?w=1149&amp;ssl=1 1149w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?resize=300%2C99&amp;ssl=1 300w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?resize=700%2C232&amp;ssl=1 700w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?resize=768%2C254&amp;ssl=1 768w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-4.png?resize=800%2C265&amp;ssl=1 800w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p>Of course, this test passes as it doesn&#8217;t actually *do* anything!  Let&#8217;s change this! You don&#8217;t need to close this runner either, as any changes to this test will be picked up automatically and re-ran.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"> Basic Interactions<\/h3>\n\n\n\n<p>For this example, we will take the existing test above and have it test logging in to the website and navigating to the settings panel.<\/p>\n\n\n\n<p><strong>Loading a web page<\/strong>: A redirect or page load is done with <code>cy.visit(url)<\/code>. For this example we used <code>cy.visit(\"https:\/\/twitter.com\/login\");<\/code><\/p>\n\n\n\n<p><strong>Locating an element:<\/strong> This is done similar to how jQuery finds objects in that you can find them on type, id, class or data attribute. The flow is always to find an item first, then chose what to do with it.  For this we need to find 2 text boxes- one for user and one for password.<\/p>\n\n\n\n<p>As Twitter does some magic with their element classes I will be locating the boxes by their unique attributes.  If I use the code below, you can see the test will pass as it finds the element on the page. Hovering over the test in the test steps will highlight the matching field.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>describe(\"Twitter example tests\", function() {\n  it(\"Page should load\", function() {\n    cy.visit(\"https:\/\/twitter.com\/login\");\n    cy.get(\"input[name='session[username_or_email]']\");\n  });\n});<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1152\" height=\"320\" data-attachment-id=\"380\" data-permalink=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/image-5-4\/\" data-orig-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?fit=1152%2C320&amp;ssl=1\" data-orig-size=\"1152,320\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image-5\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?fit=700%2C194&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?fit=700%2C194\" alt=\"\" class=\"wp-image-380\" srcset=\"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?w=1152&amp;ssl=1 1152w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?resize=300%2C83&amp;ssl=1 300w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?resize=700%2C194&amp;ssl=1 700w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?resize=768%2C213&amp;ssl=1 768w, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-5.png?resize=800%2C222&amp;ssl=1 800w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p><strong>Interacting with an element<\/strong>:  Once we have located the element we can interact with it with methods such as <code>.type()<\/code>, <code>.click()<\/code> and more. In this example I want to set the username and password field appropriately and then click the enter button, so the code now looks like: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>describe(\"Twitter example tests\", function() {\n  it(\"Page should load\", function() {\n    cy.visit(\"https:\/\/twitter.com\/login\");\n    cy.get(\"input[name='session[username_or_email]']\")\n      .first()\n      .type(\"MyHandle\");\n    cy.get(\"input[name='session[password]']\")\n      .first()\n      .type(\"password1234\");\n\n    cy.get(\"form[action='\/sessions']\")\n      .first()\n      .submit();\n  });\n});<\/code><\/pre>\n\n\n\n<p>If we run this now we can see that the page is loaded, the form is filled out and the form is submitted. The test passes, but should fail as the actual login fails due to incorrect details.<\/p>\n\n\n\n<p><strong>Finding text: <\/strong> One way we could validate if the test above succeeds is to check for the existence of an object, or some text on the page which states the login was not a success. To do this we can add the line <code> cy.contains(\"The username and password you entered did not match our records. Please double-check and try again.\"); <\/code> which will check the entire DOM for that specific text. We could also find a specific element using <code>.get()<\/code> and chaining on the <code>.contains()<\/code> method.<\/p>\n\n\n\n<p><strong>Waiting:<\/strong> Waiting is part of all web applications, and although Cypress will retry a few times if it cannot locate an element, it does not have a long timeout.  The <code>cy.get()<\/code> takes in an additional options object in which a timeout can be specified. For example: <code> cy.get(\".some-class-which-isnt-visible-yet\", { timeout: 30000 }); <\/code> would pause the execution of the test until the element is located, or the 30,000ms timeout occurs. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code sharing and re-use<\/h2>\n\n\n\n<p>Lets say we have expanded our tests so we have a new test which detects if the word &#8220;Home&#8221; is displayed to the user on their dashboard once logged in.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>describe(\"Twitter tweet tests\", function() {\n  it(\"When logged in the word Home appears\", function() {\n    cy.contains(\"Home\");\n  });\n});<\/code><\/pre>\n\n\n\n<p>Running this will fail as it doesn&#8217;t know which website to use. We could use the <code>cy.visit()<\/code> method, but as each test is ran is isolation of the others we wouldn&#8217;t be logged in. Whilst we could just copy the login code from the first test into this one (either in the <code>it<\/code> method, or in a <code>beforeEach<\/code> block), its a little messy to do so and introduces duplication and more maintenance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Commands &amp; Shared Code<\/h3>\n\n\n\n<p>Remember that commands.js file under the Support directory? Lets create a new command which will do our login from a central place! We will simply cut and paste in the contents of the login section of the previous test, like so:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Cypress.Commands.add(\"twitterLogin\", () => {\n  cy.visit(\"https:\/\/twitter.com\/login\");\n  cy.get(\"input[name='session[username_or_email]']\")\n    .first()\n    .type(\"MyValidUser\");\n  cy.get(\"input[name='session[password]']\")\n    .first()\n    .type(\"MyPassword\");\n\n  cy.get(\"form[action='\/sessions']\")\n    .first()\n    .submit();\n});<\/code><\/pre>\n\n\n\n<p>This tells Cypress that there is a command available called &#8220;twitterLogin&#8221; and which steps to execute when this command is called. Now we can simply update the login.spec.js to be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>describe(\"Twitter tweet tests!\", function() {\n  it(\"Can compose a tweet\", function() {\n    cy.twitterLogin();\n    cy.contains(\n      \"The username and password you entered did not match our records. Please double-check and try again.\"\n    );\n  });\n});<\/code><\/pre>\n\n\n\n<p>Now, we can call <code>cy.twitterLogin()<\/code> from any of our spec files!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Final thoughts<\/h2>\n\n\n\n<p>Cypress may well become my favorite UI testing framework. In less than a day I was able to gain enough knowledge to put together a fairly large proof of concept for testing one of our front end applications. The only &#8220;difficulties&#8221; were things like persisting authentication which only took a few google searches to solve. I may have other posts around adding additional flexibility in the future.<\/p>\n\n\n\n<p>The main benefit to me (other than the flexibility, speed, and the obvious) is that the syntax is flexible enough for a developer, but easy enough for somebody with less coding knowledge (QA, BA, etc).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cypress (Cypress.io) is an automation framework for web app testing built and configured with Javascript. Automated front-end testing is definitely not new, but Cypress really is something different. It&#8217;s silly fast, requires almost no setup, has quick-to-learn syntax and has a really nice, feature packed test runner. Why Cypress? I&#8217;ll let you read the summary &hellip;<\/p>\n","protected":false},"author":1,"featured_media":397,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[11],"tags":[32,12,3],"class_list":["post-362","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-testing","tag-cypress","tag-javascript","tag-testing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.<\/title>\n<meta name=\"description\" content=\"Using Cypress to end-to-end any web application with minimal effort\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/\u26a1lightning-fast-testing-of-web-applications-with-cypress\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.\" \/>\n<meta property=\"og:description\" content=\"Using Cypress to end-to-end any web application with minimal effort\" \/>\n<meta property=\"og:url\" content=\"https:\/\/yer.ac\/blog\/2020\/02\/07\/\u26a1lightning-fast-testing-of-web-applications-with-cypress\/\" \/>\n<meta property=\"og:site_name\" content=\"yer.ac | Adventures of a developer, and other things.\" \/>\n<meta property=\"article:published_time\" content=\"2020-02-07T12:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-02-20T08:30:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i1.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1089\" \/>\n\t<meta property=\"og:image:height\" content=\"402\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"yer.ac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"yer.ac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/\"},\"author\":{\"name\":\"yer.ac\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"headline\":\"\u26a1lightning-fast testing of web applications with Cypress\",\"datePublished\":\"2020-02-07T12:00:00+00:00\",\"dateModified\":\"2020-02-20T08:30:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/\"},\"wordCount\":1448,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"image\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/image-6.png?fit=1089%2C402&ssl=1\",\"keywords\":[\"Cypress\",\"Javascript\",\"Testing\"],\"articleSection\":[\"Testing\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/\",\"url\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/\",\"name\":\"\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/image-6.png?fit=1089%2C402&ssl=1\",\"datePublished\":\"2020-02-07T12:00:00+00:00\",\"dateModified\":\"2020-02-20T08:30:22+00:00\",\"description\":\"Using Cypress to end-to-end any web application with minimal effort\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/image-6.png?fit=1089%2C402&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/yer.ac\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/02\\\/image-6.png?fit=1089%2C402&ssl=1\",\"width\":1089,\"height\":402},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/2020\\\/02\\\/07\\\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/yer.ac\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u26a1lightning-fast testing of web applications with Cypress\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/yer.ac\\\/blog\\\/\",\"name\":\"yer.ac | Adventures of a developer, and other things.\",\"description\":\"Blog to keep track of things I am upto\",\"publisher\":{\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/yer.ac\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/yer.ac\\\/blog\\\/#\\\/schema\\\/person\\\/4638b9d868c7d3747bd3bb01fbc8153d\",\"name\":\"yer.ac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\",\"caption\":\"yer.ac\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.","description":"Using Cypress to end-to-end any web application with minimal effort","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:\/\/yer.ac\/blog\/2020\/02\/07\/\u26a1lightning-fast-testing-of-web-applications-with-cypress\/","og_locale":"en_US","og_type":"article","og_title":"\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.","og_description":"Using Cypress to end-to-end any web application with minimal effort","og_url":"https:\/\/yer.ac\/blog\/2020\/02\/07\/\u26a1lightning-fast-testing-of-web-applications-with-cypress\/","og_site_name":"yer.ac | Adventures of a developer, and other things.","article_published_time":"2020-02-07T12:00:00+00:00","article_modified_time":"2020-02-20T08:30:22+00:00","og_image":[{"width":1089,"height":402,"url":"https:\/\/i1.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","type":"image\/png"}],"author":"yer.ac","twitter_card":"summary_large_image","twitter_misc":{"Written by":"yer.ac","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#article","isPartOf":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/"},"author":{"name":"yer.ac","@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"headline":"\u26a1lightning-fast testing of web applications with Cypress","datePublished":"2020-02-07T12:00:00+00:00","dateModified":"2020-02-20T08:30:22+00:00","mainEntityOfPage":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/"},"wordCount":1448,"commentCount":0,"publisher":{"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"image":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","keywords":["Cypress","Javascript","Testing"],"articleSection":["Testing"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/","url":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/","name":"\u26a1lightning-fast testing of web applications with Cypress - yer.ac | Adventures of a developer, and other things.","isPartOf":{"@id":"https:\/\/yer.ac\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#primaryimage"},"image":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","datePublished":"2020-02-07T12:00:00+00:00","dateModified":"2020-02-20T08:30:22+00:00","description":"Using Cypress to end-to-end any web application with minimal effort","breadcrumb":{"@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#primaryimage","url":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","contentUrl":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","width":1089,"height":402},{"@type":"BreadcrumbList","@id":"https:\/\/yer.ac\/blog\/2020\/02\/07\/%e2%9a%a1lightning-fast-testing-of-web-applications-with-cypress\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/yer.ac\/blog\/"},{"@type":"ListItem","position":2,"name":"\u26a1lightning-fast testing of web applications with Cypress"}]},{"@type":"WebSite","@id":"https:\/\/yer.ac\/blog\/#website","url":"https:\/\/yer.ac\/blog\/","name":"yer.ac | Adventures of a developer, and other things.","description":"Blog to keep track of things I am upto","publisher":{"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/yer.ac\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/yer.ac\/blog\/#\/schema\/person\/4638b9d868c7d3747bd3bb01fbc8153d","name":"yer.ac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg","caption":"yer.ac"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/67ed010c9cc7986d40647e061c6dcdb06d818776591c7e954055adb629621113?s=96&d=retro&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2020\/02\/image-6.png?fit=1089%2C402&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/paP5IW-5Q","jetpack-related-posts":[{"id":411,"url":"https:\/\/yer.ac\/blog\/2020\/02\/07\/supporting-multiple-configurations-in-cypress\/","url_meta":{"origin":362,"position":0},"title":"Supporting multiple configurations in Cypress","author":"yer.ac","date":"February 7, 2020","format":false,"excerpt":"By default, Cypress will support a single configuration based on the optional file cypress.json as described in their documentation here. Whilst this works fine for most, it would be great if we could have access to a cypress.dev.json for local development, or even better, a whole host of configuration files\u2026","rel":"","context":"In &quot;Testing&quot;","block_context":{"text":"Testing","link":"https:\/\/yer.ac\/blog\/category\/testing\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":599,"url":"https:\/\/yer.ac\/blog\/2026\/01\/23\/from-acceptance-criteria-to-playwright-tests-with-mcp\/","url_meta":{"origin":362,"position":1},"title":"From Acceptance Criteria to Playwright Tests with MCP","author":"yer.ac","date":"January 23, 2026","format":false,"excerpt":"Modern UI test tooling has quietly raised the bar for who can participate. Playwright is powerful, but it assumes comfort with TypeScript, selectors, repo structure, and terminal use. That gap often collapses testing back onto developers, creating pressure to almost validate their own work. This proof of concept explores using\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/yer.ac\/blog\/category\/development\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2026\/01\/cover.png?fit=1200%2C800&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":69,"url":"https:\/\/yer.ac\/blog\/2019\/04\/08\/attempting-to-use-mocha-chai-to-unit-test-es6\/","url_meta":{"origin":362,"position":2},"title":"Attempting to use Mocha &#038; Chai to unit test ES6.","author":"yer.ac","date":"April 8, 2019","format":false,"excerpt":"In this post I will cover using Mocha (JS test framework) and Chai (For BDD syntax) to unit test ES6 Javascript in VS Code. I started working on a small side project, for no reason other than to play with ES6+. It's a(nother) relatively simple toast library written in as\u2026","rel":"","context":"In &quot;Development&quot;","block_context":{"text":"Development","link":"https:\/\/yer.ac\/blog\/category\/development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":181,"url":"https:\/\/yer.ac\/blog\/2019\/06\/21\/using-time-tracking-software-to-your-advantage\/","url_meta":{"origin":362,"position":3},"title":"Using time tracking software to your advantage.","author":"yer.ac","date":"June 21, 2019","format":false,"excerpt":"Ugh, Time tracking! People often convulse when hearing \"Time tracking\" in a work context. Although some companies use this to ensure their pesky workers aren't having any downtime and are constantly little cash cows, I believe it can be used for good and more importantly boost your own productivity. Why\u2026","rel":"","context":"In &quot;Productivity&quot;","block_context":{"text":"Productivity","link":"https:\/\/yer.ac\/blog\/category\/productivity\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/06\/image.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/06\/image.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/06\/image.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/06\/image.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":78,"url":"https:\/\/yer.ac\/blog\/2019\/04\/09\/debugging-es6-mocha-unit-tests-using-vs-code\/","url_meta":{"origin":362,"position":4},"title":"Debugging ES6 Mocha unit tests using VS Code","author":"yer.ac","date":"April 9, 2019","format":false,"excerpt":"The world of Mocha, VS Code and Node is still fairly new to me. Typically in the past all my JS unit tests have been debuggable in-browser using DevTools, but with Mocha this is not the case (As I am not deploying my spec files). I got Mocha to load\u2026","rel":"","context":"In &quot;Development&quot;","block_context":{"text":"Development","link":"https:\/\/yer.ac\/blog\/category\/development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2019\/04\/image-1.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":576,"url":"https:\/\/yer.ac\/blog\/2025\/08\/18\/vibing-in-kiro-to-create-a-self-serve-portainer-wrapper\/","url_meta":{"origin":362,"position":5},"title":"Vibing in Kiro to create a self-serve Portainer wrapper.","author":"yer.ac","date":"August 18, 2025","format":false,"excerpt":"On a Friday afternoon with half an hour to spare, I tested Kiro, Amazon\u2019s new agentic IDE, against a real-world problem: giving my team a simple way to start and stop Docker services in Portainer. With nothing more than a rough prompt, a PowerShell script, and a few \u201cTrust command\u201d\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/yer.ac\/blog\/category\/development\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/yer.ac\/blog\/wp-content\/uploads\/2025\/08\/Untitled-1.png?fit=1200%2C649&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/comments?post=362"}],"version-history":[{"count":42,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/362\/revisions"}],"predecessor-version":[{"id":417,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/posts\/362\/revisions\/417"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/media\/397"}],"wp:attachment":[{"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/media?parent=362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/categories?post=362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yer.ac\/blog\/wp-json\/wp\/v2\/tags?post=362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}