<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jessy Jordan</title>
    <description>The latest articles on DEV Community by Jessy Jordan (@jayjayjpg).</description>
    <link>https://dev.to/jayjayjpg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F364113%2F8a450821-75d9-4da7-a9f3-742830d631eb.jpg</url>
      <title>DEV Community: Jessy Jordan</title>
      <link>https://dev.to/jayjayjpg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jayjayjpg"/>
    <language>en</language>
    <item>
      <title>What is a software blueprint?</title>
      <dc:creator>Jessy Jordan</dc:creator>
      <pubDate>Sat, 17 Jul 2021 11:15:28 +0000</pubDate>
      <link>https://dev.to/jayjayjpg/what-is-a-software-blueprint-5388</link>
      <guid>https://dev.to/jayjayjpg/what-is-a-software-blueprint-5388</guid>
      <description>&lt;p&gt;A &lt;strong&gt;software blueprint&lt;/strong&gt; is a &lt;strong&gt;high-level plan&lt;/strong&gt; or outline used in the development of software.&lt;/p&gt;

&lt;p&gt;When the term blueprint is used in programming, it usually refers to one of two related, yet slightly different concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a high-level, graphical or written piece of &lt;strong&gt;documentation&lt;/strong&gt; of software architecture ("blueprint for &lt;strong&gt;humans&lt;/strong&gt;")&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a piece of code serving as a template for &lt;strong&gt;code-generating tools&lt;/strong&gt; that build or configure applications ("blueprint for &lt;strong&gt;machines&lt;/strong&gt;")&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, software blueprints are a powerful tool for planning, building and maintaining software projects.&lt;/p&gt;

&lt;p&gt;And first, let's take a look into how software blueprints are used &lt;strong&gt;as documentation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blueprints as software design documentation
&lt;/h2&gt;

&lt;p&gt;Blueprints may be used to &lt;strong&gt;design&lt;/strong&gt; and &lt;strong&gt;document the architecture&lt;/strong&gt; of applications. It serves as a &lt;strong&gt;high-level representation of software design&lt;/strong&gt; that supports the development process in several ways:&lt;/p&gt;

&lt;p&gt;As part of the planning process of upcoming feature work, a blueprint communicates &lt;strong&gt;implementation requirements&lt;/strong&gt; across an engineering team more efficiently; a software architect may design a new feature and they can then use a blueprint to provide the feature requirements to the software engineers who will implement it later on.&lt;/p&gt;

&lt;p&gt;In a similar manner, blueprints help teams consisting of both engineering and non-engineering professionals to collaborate on the development of business applications; blueprints empower stakeholders of either department to define requirements using common terminology that doesn't require in-depth, technical knowledge. This way, a &lt;strong&gt;software blueprinting process&lt;/strong&gt; reduces the number of cycles needed for planning, implementing and iterating on features by getting application requirements defined well from the beginning. This in turn helps to &lt;strong&gt;reduce the overall development time&lt;/strong&gt; of applications significantly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo9v1ctvqki1xy58mlhv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo9v1ctvqki1xy58mlhv.jpg" alt="Title: An Architect in His Studio. Old ink drawing from the 19th century showing a man in a wealthy-looking coat sitting in front of his desk in his small studio room and working on a blueprint for a cathedral. You can see one of his employees in the background serving him tea"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Through this process, blueprints become an effective strategy for maintaining documentation of software architecture. As a business goes through the iterative process of blueprinting feature work upfront and implementing features according to the design, a growing documentation for the business's software architecture is created automatically.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Unified Modeling Language (UML)&lt;/strong&gt; software architects oftentimes visualize the design of the systems they and their team are implementing. Many products and open-source tools support software design with UML, such as &lt;a href="https://www.eclipse.org/papyrus/" rel="noopener noreferrer"&gt;Papyrus&lt;/a&gt;, &lt;a href="https://visualstudio.microsoft.com/" rel="noopener noreferrer"&gt;Visual Studio&lt;/a&gt; or &lt;a href="https://www.lucidchart.com/" rel="noopener noreferrer"&gt;Lucidchart&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more insight into the rationale behind &lt;strong&gt;blueprints as documentation&lt;/strong&gt; and UML specifically, you may want to continue reading &lt;a href="https://martinfowler.com/bliki/UmlAsBlueprint.html" rel="noopener noreferrer"&gt;"UmlAsBlueprint"&lt;/a&gt; by &lt;a href="https://twitter.com/martinfowler" rel="noopener noreferrer"&gt;Martin Fowler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But the term blueprint isn't only used to describe software design plans that help &lt;strong&gt;people&lt;/strong&gt; to implement said software. "Blueprint" also refers to those design plans that help &lt;strong&gt;computers&lt;/strong&gt; to &lt;strong&gt;implement software automatically&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blueprints as automatic programming templates
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;automatic programming&lt;/strong&gt; a computer program, when run, generates code automatically based on a specific configuration. The configuration for these &lt;strong&gt;code generators&lt;/strong&gt; can come from &lt;strong&gt;direct user input&lt;/strong&gt; (e.g. parameters provided to a shell command) and - from &lt;strong&gt;blueprints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz8f4r3b5m2v0uh0xjo0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz8f4r3b5m2v0uh0xjo0.jpg" alt="Old ink drawing of blueprints for the construction of the towers of the cathedral in Cologne, Germany"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As part of the code generation process, the blueprint outlines the layout and configuration of the resulting program. This makes the blueprint useful in scaffolding and extending applications; a software engineer who uses blueprints in their development process can &lt;strong&gt;focus&lt;/strong&gt; on the implementation of the &lt;strong&gt;business logic&lt;/strong&gt; itself and worry less about how their implementation fits into the code base.&lt;/p&gt;

&lt;p&gt;Therefore when used as &lt;strong&gt;code generator templates&lt;/strong&gt;, blueprints improve the immediate developer experience significantly and can reduce overall development time. Lastly, they facilitate scaling and maintaining large applications by making extending applications easier.&lt;/p&gt;

&lt;p&gt;Many different tools and &lt;strong&gt;frameworks&lt;/strong&gt; already support blueprints and code generators for developers. This includes, for example and among many others, the &lt;a href="https://flask.palletsprojects.com/en/2.0.x/tutorial/views/#create-a-blueprint" rel="noopener noreferrer"&gt;Python web framework Flask&lt;/a&gt;, the &lt;a href="https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/Blueprints/" rel="noopener noreferrer"&gt;Blueprint visual scripting system of Unreal Engine&lt;/a&gt;, and the &lt;a href="https://cli.emberjs.com/release/advanced-use/blueprints/" rel="noopener noreferrer"&gt;JavaScript framework EmberJS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blueprints as documentation and automatic programming tool
&lt;/h2&gt;

&lt;p&gt;Blueprints are a &lt;strong&gt;powerful tool&lt;/strong&gt; in planning, documenting and implementing software applications.&lt;/p&gt;

&lt;p&gt;Blueprints - when used as documentation for software architecture - are critical for successfully planning and executing development cycles, whereas blueprints - when used as a template for code generators - are an integral part of maintaining and scaling code bases gracefully.&lt;/p&gt;




&lt;p&gt;Have you created or used software blueprints before? Let me know in the comments below! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>software</category>
      <category>uml</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Blueprints in Ember Are Cool and How They Save You Time Writing Tests</title>
      <dc:creator>Jessy Jordan</dc:creator>
      <pubDate>Sat, 10 Jul 2021 12:10:52 +0000</pubDate>
      <link>https://dev.to/jayjayjpg/why-blueprints-in-ember-are-cool-and-how-they-save-you-time-writing-tests-1p0b</link>
      <guid>https://dev.to/jayjayjpg/why-blueprints-in-ember-are-cool-and-how-they-save-you-time-writing-tests-1p0b</guid>
      <description>&lt;p&gt;Developing and maintaining a growing &lt;strong&gt;front-end&lt;/strong&gt; code base is complex on its own. And only sufficient &lt;strong&gt;test coverage&lt;/strong&gt; will allow you to continue to build features with confidence and without the fear of critical regressions.&lt;/p&gt;

&lt;p&gt;Therefore, automatic testing is an important part of your and your team's joint efforts to build web applications, including your Ember apps.&lt;/p&gt;

&lt;p&gt;Still, writing tests can be time-consuming.&lt;/p&gt;

&lt;p&gt;Despite &lt;strong&gt;powerful testing tools&lt;/strong&gt; available in the JavaScript and &lt;a href="https://emberobserver.com/categories/testing"&gt;Ember ecosystem&lt;/a&gt; today, and even considering that the &lt;a href="https://guides.emberjs.com/release/testing/"&gt;framework already provides you a great foundation for testing&lt;/a&gt;, you might still need to spend some time defining your own project-specific test setup.&lt;/p&gt;

&lt;p&gt;You may have written custom stubs and mocks for those services, network requests and third-party libraries that can't be easily simulated during your testing scenarios otherwise. And as your application grows, often the number of custom testing helpers you need to include in many, if not all, of your test files increases as well.&lt;/p&gt;

&lt;p&gt;This in turn introduces a new entry barrier for developers who are new to the code base and who want to write their first test: Due to a lack of familiarity with all the project-specific configurations, they might either spend a lot of time trying to figure out what kind of setup to copy-paste from existing test files of your test suite into their own.&lt;/p&gt;

&lt;p&gt;Or due to a lack of time, they might just avoid writing that test altogether.&lt;/p&gt;

&lt;p&gt;Still, &lt;strong&gt;writing tests&lt;/strong&gt; is important and should require you as little on-ramp time as possible - even as your application grows.&lt;/p&gt;

&lt;p&gt;What if you could &lt;strong&gt;automate&lt;/strong&gt; the project-specific &lt;strong&gt;setup of your tests&lt;/strong&gt;, so you can focus on the actual work of writing the testing scenarios for your features instead of worrying about how to setup the test to begin with?&lt;/p&gt;

&lt;p&gt;Fortunately, Ember CLI has you covered with tools to do exactly that.&lt;/p&gt;

&lt;p&gt;But first, let's take a look into how &lt;strong&gt;test scaffolding in in Ember apps&lt;/strong&gt; works in general, and secondly, how we can modify the process for our testing needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy Test Scaffolding with Generate Commands
&lt;/h2&gt;

&lt;p&gt;Out of the box, the &lt;a href="https://cli.emberjs.com/"&gt;Ember CLI&lt;/a&gt; already provides you with &lt;a href="https://cli.emberjs.com/release/basic-use/cli-commands/#generatemorefiles"&gt;several &lt;code&gt;generate&lt;/code&gt; commands&lt;/a&gt; to get started with writing your tests.&lt;/p&gt;

&lt;p&gt;This is how you would start off writing an application test for &lt;code&gt;my-feature&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create a pre-configured application test file for 'my-feature'&lt;/span&gt;
ember generate acceptance-test my-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this command in your shell will provide you with the following setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/acceptance/my-feature-test.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ember/test-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupApplicationTest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Acceptance | my feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupApplicationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visiting /my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;currentURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://cli.emberjs.com/release/advanced-use/blueprints/"&gt;official Ember CLI Guides&lt;/a&gt; for more information on how to &lt;strong&gt;generate and use blueprints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the next step, you would usually start to modify the test file with your own &lt;strong&gt;custom testing setup&lt;/strong&gt;, e.g. by invoking test utils you have written yourself or by importing methods from other testing libraries you frequently use.&lt;/p&gt;

&lt;p&gt;Luckily, you don't need to do all of this work by hand.&lt;/p&gt;

&lt;p&gt;Instead, you can automate this modification process and instruct the cli's &lt;code&gt;generate&lt;/code&gt; command to create a custom test file, instead of the default one.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Ember CLI blueprints&lt;/strong&gt; come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blueprints Define Your Testing Scaffold Layout
&lt;/h2&gt;

&lt;p&gt;Anytime you run &lt;code&gt;ember generate acceptance-test xyz&lt;/code&gt;, the cli will create your test file based on your command-line input and the &lt;a href="https://github.com/emberjs/ember.js/blob/master/blueprints/acceptance-test/qunit-rfc-232-files/tests/acceptance/__name__-test.js"&gt;framework blueprint that is associated with the &lt;code&gt;acceptance-test&lt;/code&gt; parameter&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blueprints/acceptance-test/qunit-rfc-232-files/tests/acceptance/__name__-test.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ember/test-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupApplicationTest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;%= friendlyTestName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupApplicationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visiting /&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;currentURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration of the process itself, e.g. which naming convention to use to name your test modules, is done in the blueprint's &lt;a href="https://github.com/emberjs/ember.js/blob/master/blueprints/acceptance-test/index.js"&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blueprints/acceptance-test/index.js&lt;/span&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pathUtil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-cli-path-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stringUtils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-cli-string-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useTestFrameworkDetector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-framework-detector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTestFrameworkDetector&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generates an acceptance test for a feature.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;testFolderRoot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stringUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dasherize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmberCLIAddon&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;testFolderRoot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pathUtil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRelativeParentPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;destroyAppExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tests/helpers/destroy-app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;friendlyTestName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Acceptance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;stringUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dasherize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; | &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;testFolderRoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testFolderRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;friendlyTestName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;destroyAppExists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And even better: You can also customize the default scaffolding by &lt;strong&gt;overriding&lt;/strong&gt; existing blueprints.&lt;/p&gt;

&lt;p&gt;By generating your own &lt;code&gt;acceptance-test&lt;/code&gt;  blueprint in your project, you can now extend this functionality with your own, custom acceptance test setup in a single &lt;code&gt;generate&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Your Own Testing Blueprint for Your Ember App
&lt;/h2&gt;

&lt;p&gt;To get started, you can use &lt;code&gt;ember generate&lt;/code&gt; while in your Ember application's directory again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ember generate blueprint acceptance-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should leave you with a new blueprint configuration file at &lt;code&gt;blueprints/acceptance-test-index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;

  &lt;span class="c1"&gt;// locals(options) {&lt;/span&gt;
  &lt;span class="c1"&gt;//   // Return custom template variables here.&lt;/span&gt;
  &lt;span class="c1"&gt;//   return {&lt;/span&gt;
  &lt;span class="c1"&gt;//     foo: options.entity.options.foo&lt;/span&gt;
  &lt;span class="c1"&gt;//   };&lt;/span&gt;
  &lt;span class="c1"&gt;// }&lt;/span&gt;

  &lt;span class="c1"&gt;// afterInstall(options) {&lt;/span&gt;
  &lt;span class="c1"&gt;//   // Perform extra work here.&lt;/span&gt;
  &lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create your own modified version of &lt;strong&gt;acceptance test blueprints&lt;/strong&gt;, you can lend most of the &lt;a href="https://github.com/emberjs/ember.js/tree/master/blueprints/acceptance-test"&gt;framework's default setup&lt;/a&gt; for your specific test setup.&lt;/p&gt;

&lt;p&gt;For a recent app, which uses QUnit and the &lt;a href="https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md"&gt;latest Ember QUnit API&lt;/a&gt;, your &lt;code&gt;index.js&lt;/code&gt; could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blueprints/acceptance-test/index.js&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stringUtils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-cli-string-utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generates an acceptance test for a feature.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;destroyAppExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/tests/helpers/destroy-app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;friendlyTestName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Acceptance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;stringUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dasherize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; | &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;testFolderRoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tests/acceptance/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;friendlyTestName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;destroyAppExists&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, copy over the directory structure &lt;a href="https://github.com/emberjs/ember.js/tree/master/blueprints/acceptance-test"&gt;from the list of framework blueprints&lt;/a&gt; for your particular test setup into the a new &lt;code&gt;blueprints/acceptance-test/files&lt;/code&gt; directory in your project, including the default template &lt;code&gt;__name__-test.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We assume you're working with a recent Ember app using the latest Ember QUnit API in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# copy from framework blueprints file layout...
-- qunit-rfc-232-files
    |-- tests
        |-- acceptance
            |-- __name__-test.js

# ...to your project's file layout
-- files
    |-- tests
        |-- acceptance
            |-- __name__-test.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blueprints/acceptance-test/files/tests/acceptance/__name__-test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ember/test-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupApplicationTest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;%= friendlyTestName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupApplicationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visiting /&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;currentURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can modify the template at &lt;code&gt;blueprints/acceptance-test/files/tests/acceptance/__name__-test.js&lt;/code&gt; to your needs.&lt;/p&gt;

&lt;p&gt;In this example, we want to ensure that in each new acceptance test file generated in the future, an additional helper util from our project is imported, that &lt;a href="https://github.com/elwayman02/ember-sinon-qunit"&gt;ember-sinon-qunit&lt;/a&gt; is setup correctly and - most importantly - that our module description sparkles ✨:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// blueprints/acceptance-test/files/tests/acceptance/__name__-test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ember/test-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupApplicationTest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupStripe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-ember-app/tests/helpers/stripe-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;%= friendlyTestName %&amp;gt; ✨✨✨&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupApplicationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;setupStripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testStub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visiting /&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;currentURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;%= dasherizedModuleName %&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, if we run the &lt;code&gt;generate&lt;/code&gt; command for creating an acceptance test again, the cli will use our custom testing blueprint configuration and &lt;strong&gt;modify our test file&lt;/strong&gt; accordingly. Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ember generate acceptance-test my-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/acceptance/my-feature-test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentURL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ember/test-helpers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupApplicationTest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ember-qunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupStripe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-ember-app/tests/helpers/stripe-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Acceptance | my feature ✨✨✨&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupApplicationTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;setupStripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testStub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visiting /my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;currentURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/my-feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're all set to start testing with one single command!&lt;/p&gt;

&lt;h2&gt;
  
  
  Improve Your Developer Experience with Ember and Custom Blueprints
&lt;/h2&gt;

&lt;p&gt;You can &lt;strong&gt;save yourself and your team time&lt;/strong&gt; by automating the setup of your test files leveraging blueprints in Ember.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blueprints&lt;/strong&gt; allow you to override the templates for existing testing &lt;code&gt;generate&lt;/code&gt; commands, such as &lt;code&gt;ember generate acceptance-test&lt;/code&gt; or &lt;code&gt;ember generate component-test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Beyond the scope of testing and which &lt;code&gt;generate&lt;/code&gt; commands the framework already offers, you can &lt;a href="https://cli.emberjs.com/release/advanced-use/blueprints/"&gt;add your own &lt;code&gt;generate&lt;/code&gt; commands&lt;/a&gt;, too. If you always wanted to make it easier to write documentation for your project, why not create a &lt;code&gt;ember generate docs&lt;/code&gt;  blueprint today?&lt;/p&gt;




&lt;p&gt;Jessy is a Senior Frontend Engineer at &lt;a href="https://meroxa.io/"&gt;Meroxa&lt;/a&gt;, a public speaker and an organizer of the &lt;a href="https://twitter.com/emberliners"&gt;EmberJS Berlin&lt;/a&gt; meetup. Also, if you're into design, devops or data engineering, &lt;a href="https://jobs.lever.co/meroxa"&gt;come join us!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ember</category>
      <category>javascript</category>
      <category>testing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The difference between ember serve and npm run start</title>
      <dc:creator>Jessy Jordan</dc:creator>
      <pubDate>Sun, 27 Jun 2021 14:16:42 +0000</pubDate>
      <link>https://dev.to/jayjayjpg/the-difference-between-ember-serve-and-npm-run-start-2m5p</link>
      <guid>https://dev.to/jayjayjpg/the-difference-between-ember-serve-and-npm-run-start-2m5p</guid>
      <description>&lt;h1&gt;
  
  
  The difference between &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm run start&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;When you have built a single-page-application using &lt;a href="https://github.com/ember-cli/ember-cli"&gt;Ember CLI&lt;/a&gt;, you have two options for starting your app locally. You can either use the CLI's &lt;code&gt;ember serve&lt;/code&gt; command directly or you can use the handy &lt;code&gt;npm&lt;/code&gt; alias that is created for you after generating a new Ember app: &lt;code&gt;npm run start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But what's the difference between those two?&lt;/p&gt;

&lt;h2&gt;
  
  
  What &lt;code&gt;npm run start&lt;/code&gt; is used for
&lt;/h2&gt;

&lt;p&gt;First, &lt;code&gt;npm run start&lt;/code&gt; allows you to create your own default boot up command for your application by e.g. passing additional parameters to &lt;code&gt;ember serve&lt;/code&gt; and hide this modified booting instruction away in one, single, shorthand command via a definition in your &lt;code&gt;package.json&lt;/code&gt;. This makes you type less and can make your life easier when developing your app locally.&lt;/p&gt;

&lt;p&gt;If you want to learn more about how to modify the &lt;code&gt;ember serve&lt;/code&gt; command, check out the official &lt;a href="https://cli.emberjs.com/release/advanced-use/cli-commands-reference/#emberserve"&gt;Ember CLI Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a fresh Ember app though, the functionality of both &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm run start&lt;/code&gt; will be almost identical. Emphasis on &lt;em&gt;almost&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm run start&lt;/code&gt; don't behave the same way
&lt;/h2&gt;

&lt;p&gt;Recently, while working on one of my side projects, I tried to boot up an Ember application using TailwindCSS by running the &lt;code&gt;ember serve&lt;/code&gt; command. The build process was kicked off, but ultimately failed with the following error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object.entries(...).flatMap is not a function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stack trace pointed to issues with the &lt;code&gt;PostCSS&lt;/code&gt; compiler I had been using to integrate TailwindCSS with my app's styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object.entries(...).flatMap is not a function
    at PostcssCompiler.Plugin (/home/jayjayjpg/Documents/projects/my/project/node_modules/broccoli-plugin/index.js:7:31)
    at new CachingWriter (/home/jayjayjpg/Documents/projects/my/project/node_modules/broccoli-caching-writer/index.js:18:10)
    at new PostcssCompiler (/home/jayjayjpg/Documents/projects/my/project/node_modules/broccoli-postcss-single/index.js:20:5)
    at Object.keys.map (/home/jayjayjpg/Documents/projects/my/project/node_modules/ember-cli-postcss/index.js:36:12)
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After some debugging and double-checking my setup that I have followed from Chris Masters' &lt;a href="https://github.com/chrism/emberjs-tailwind-purgecss#emberjs-tailwind-10-and-purgecss-working-example"&gt;working example for TailwindCSS in an Ember app&lt;/a&gt; in my &lt;code&gt;ember-cli-build.js&lt;/code&gt; was correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ember-cli-build.js
'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const isProduction = EmberApp.env() === 'production';

const purgeCSS = {
  module: require('@fullhuman/postcss-purgecss'),
  options: {
    content: [
      // add extra paths here for components/controllers which include tailwind classes
      './app/index.html',
      './app/templates/**/*.hbs',
      './app/components/**/*.hbs'
    ],
    defaultExtractor: content =&amp;gt; content.match(/[A-Za-z0-9-_:/]+/g) || []
  }
}

module.exports = function(defaults) {
  let app = new EmberApp(defaults, {
    postcssOptions: {
      compile: {
        plugins: [
          {
            module: require('postcss-import'),
            options: {
              path: ['node_modules']
            }
          },
          require('tailwindcss')('./app/tailwind.config.js'),
          ...isProduction ? [purgeCSS] : []
        ]
      }
    }
  });
  return app.toTree();
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...I started to do a quick google search, to see if any other folks using TailwindCSS ran into a similar issue.&lt;/p&gt;

&lt;p&gt;And indeed, I found a couple of issues &lt;a href="https://github.com/tailwindlabs/tailwindcss/issues/3503"&gt;here&lt;/a&gt; and &lt;a href="https://stackoverflow.com/questions/64907613/typeerror-object-entries-flatmap-is-not-a-function"&gt;there&lt;/a&gt; that pointed to the fact, that the &lt;code&gt;.flatMap&lt;/code&gt; method used at build time of my application was a more recent feature of Node and only available from Node v11+.&lt;/p&gt;

&lt;p&gt;I confirmed that I was still on an older version of Node, that this would explain the lacking support of the &lt;code&gt;.flatMap&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node -v
10.16.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...and was enthusiastic about quickly resolving the build problem with an upgrade of Node. Since I was using &lt;a href="https://github.com/nvm-sh/nvm"&gt;nvm&lt;/a&gt; my upgrade turned out as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvm install 14
nvm use 14
rm -rf node_modules/ &amp;amp;&amp;amp; npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As soon as the installation finished, I tried my luck again by running &lt;code&gt;ember serve&lt;/code&gt;, and to my surprise - the build failed again with the very same &lt;code&gt;.flatMap is not a function&lt;/code&gt; error!&lt;/p&gt;

&lt;p&gt;Still in disbelief, I tried running &lt;code&gt;npm run start&lt;/code&gt; instead and lo and behold - my app built successfully?&lt;/p&gt;

&lt;p&gt;How could my application build fail when the build command was run directly, but still succeed when its alias was executed?&lt;/p&gt;

&lt;h2&gt;
  
  
  How Node, NVM and Ember CLI work together
&lt;/h2&gt;

&lt;p&gt;Once I checked on the versions of my Ember CLI and my Node installs, it became more clear, why &lt;code&gt;npm run start&lt;/code&gt; and &lt;code&gt;ember serve&lt;/code&gt; would behave differently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node -v
v14.17.1

ember -v
ember-cli: 3.26.1
node: 10.16.3
os: linux x64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How come that Ember CLI was linked to an older version of Node different from my local Node version?&lt;/p&gt;

&lt;p&gt;In my case, I've been using &lt;code&gt;nvm&lt;/code&gt; to switch between different versions of Node on my machine.&lt;/p&gt;

&lt;p&gt;When using &lt;a href="https://github.com/nvm-sh/nvm"&gt;nvm&lt;/a&gt;, it's important to be mindful on how this will affect the usage of globally installed packages. Nvm ensures that any global installs of binaries end up in a dedicated, versioned directory of &lt;code&gt;nvm&lt;/code&gt; in the user's &lt;code&gt;HOME&lt;/code&gt; directory. On Linux, you can verify this by checking the Ember CLI's binary location as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;whereis ember
ember: /home/jayjayjpg/.nvm/versions/node/v10.16.3/bin/ember 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A while ago I had installed Ember CLI globally via &lt;code&gt;npm install -g ember-cli&lt;/code&gt; while on Node 10.16.3. This instructed &lt;code&gt;nvm&lt;/code&gt; to store the binary in the related 10.16.3 Node directory and make it available via this Node version. Now whenever I would run &lt;code&gt;ember serve&lt;/code&gt; on my command line, this outdated binary would be used, running on Node 10.16.3, regardless if I had instructed &lt;code&gt;nvm&lt;/code&gt; to switch to Node v.14.17.1 or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Switching to Node 10.16.3
nvm use 10

node -v
v10.16.3

ember -v
node: 10.16.3

# Switching to Node 14.17.1
nvm use 14

node -v
v14.17.1

ember -v
node: 10.16.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever I would run &lt;code&gt;npm run start&lt;/code&gt; though, my project's &lt;a href="https://github.com/ember-learn/guides-source/issues/1133#issuecomment-539917741"&gt;local Ember CLI version would be used&lt;/a&gt; leading to a successful app build.&lt;/p&gt;

&lt;p&gt;The behavior of &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm run start&lt;/code&gt; doesn't have to differ this way though, as &lt;code&gt;nvm&lt;/code&gt; provides you with a &lt;a href="https://github.com/nvm-sh/nvm#migrating-global-packages-while-installing"&gt;command to migrate all of your already existing, global npm installations&lt;/a&gt; over to a newer version of Node and make them available when switching to said version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvm install 14 --reinstall-packages-from=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the migration I could now see my global Ember CLI binary associated with the newer Node version and residing in the path that I'd expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;whereis ember
ember: /home/jayjayjpg/.nvm/versions/node/v14.17.1/bin/ember

ember -v
ember-cli: 3.26.1
node: 14.17.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, upon running &lt;code&gt;ember serve&lt;/code&gt;, the app would build successfully using Node v.14.17.1 just as it would using &lt;code&gt;npm run start&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's the difference between &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm run start&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;In a fresh Ember app and in nearly all cases, &lt;code&gt;npm run start&lt;/code&gt; and &lt;code&gt;ember serve&lt;/code&gt; function the exact same way. But if you have a different version of Ember CLI installed globally versus locally or if you're using version managers for Node, the outcome of these two commands may differ from each other.&lt;/p&gt;

&lt;p&gt;This post has been inspired by &lt;a href="https://stackoverflow.com/a/63342128"&gt;this great response&lt;/a&gt; on Stackoverflow to the question &lt;a href="https://stackoverflow.com/questions/63340251/is-there-a-difference-between-ember-serve-and-npm-start"&gt;"Is there a difference between &lt;code&gt;ember serve&lt;/code&gt; and &lt;code&gt;npm start&lt;/code&gt;?"&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>ember</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
