# Write acceptance tests and component tests for Ember code in Discourse

**URL:** https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167
**Category:** Developer Guides
**Tags:** testing, ember, tutorial, code
**Created:** [August 24, 2016, 8:48pm UTC](https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167 "2016-08-24T20:48:02Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [August 24, 2016, 8:48pm UTC](https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167/1 "2016-08-24T20:48:02Z")

</div>

Automated tests are a great way to protect your code against future regressions. Many people are familiar with how to do this in our Rails codebase with [rspec](http://rspec.info/), but the Javascript side can be somewhat of an enigma to some.

Fortunately, it’s pretty easy these days to add basic tests to your Ember code!

### Component Tests

In the [previous tutorial](https://meta.discourse.org/t/adding-ember-components-to-discourse/48891) in this series we added a component called `fancy-snack` to display our snack with a fading background. Let’s write a test for it. Create the following file:

**test/javascripts/components/snack-test.js**

```js
import componentTest from "helpers/component-test";

moduleForComponent("fancy-snack", { integration: true });

componentTest("test the rendering", {
  template: "{{fancy-snack snack=testSnack}}",

  setup() {
    this.set("testSnack", {
      name: "Potato Chips",
      description: "Now with extra trans fat!",
    });
  },

  test(assert) {
    assert.equal(this.$(".fancy-snack-title h1").text(), "Potato Chips");
    assert.equal(
      this.$(".fancy-snack-description p").text(),
      "Now with extra trans fat!"
    );
  },
});

```

To run the test, open your browser on your development server to `/qunit?module=component%3Afancy-snack`. Your browser will then perform the component tests and output something like “2 assertions of 2 passed, 0 failed.”

Note that while on the `/qunit` page you can run other tests. You can simply select a new test from the `Module` dropdown box at the top of the screen.

Let’s step through the test to understand how it works.

The `template` line tells Ember how we’d like to insert our component. It’s the exact same markup you’d use to place the component in a handlebars template so it should be familiar:

```js
template: '{{fancy-snack snack=testSnack}}’,

```

Note that it is passing `testSnack` through as the `snack` parameter. That is defined in the `setup()` method:

```js
setup() {
  this.set('testSnack', {
    name: 'Potato Chips',
    description: 'Now with extra trans fat!'
  });
},

```

I’ve just put in some dummy data. That’s all we need to do to have Ember render the component. Finally, we have a couple of assertions in the `test()` method:

```js
test(assert) {
  assert.equal(this.$('.fancy-snack-title h1').text(), 'Potato Chips');
  assert.equal(this.$('.fancy-snack-description p').text(), 'Now with extra trans fat!');
}

```

If you use `this.$()` you get access to a [jQuery](http://jquery.com/) selector in your template. The assertions here use that selector to grab the value of the snack’s title and snack’s description and compare them with what we expect. If the values match then the assertions will pass and our test is all working.

It’s worth noting that you don’t need to test every little thing in a component like this. You should use some discretion and try to figure out what things in your code are likely to break or cause confusion to other developers down the road. If you test too many things in your template, it will mean it’s a pain for someone else in the future to change it. Just start small, testing the most obvious things, and in time you’ll get the hang of it.

### Acceptance Tests

[Acceptance tests](https://guides.emberjs.com/release/testing/acceptance/) are often easier to write, and can be more powerful than component tests as they test your application the same way a user would in their browser. I often start with acceptance tests, and then if I am making a complicated component I’ll add tests for it too.

Here’s how we can write an acceptance test that will visit our `/admin/snack` route and confirm that the snack was rendered:

**test/javascripts/acceptance/snack-test.js**

```js
import { acceptance } from "helpers/qunit-helpers";
acceptance("Snack");

test("Visit Page", function (assert) {
  visit("/admin/snack");
  andThen(() => {
    assert.ok(exists(".fancy-snack-title"), "the snack title is present");
  });
});

```

The `test()` in this case almost reads like English! The first command says visit the URL of `/admin/snack`. After that, there is an `andThen()` method. This method is necessary to make sure that all the background work is finished before the tests continue. Since Javascript and Ember code is asynchronous, we need to make sure Ember is done everything it needs to do before our assertions are executed. Finally, it tests to see if the `.fancy-snack-title` element is present.

However, if you run this test by visiting `/qunit?module=Acceptance%3A%20Snack` you’ll find that the test will fail, due to an AJAX error.

If you recall, our code includes both a Rails side and a Javascript side which performed an AJAX request to get its data. The acceptance test ran the Javascript side, but it didn’t know what to do to get its data from Rails.

To fix this, we need to add a fake response, using the excellent [pretender](https://github.com/pretenderjs/pretender) library. Open up the `test/javascripts/helpers/create-pretender.js` file and look for the line that says:

```js
this.get("/admin/plugins", () => response({ plugins: [] }));

```

Right below it, add a line to return a fake snack object for our acceptance test to work with:

```js
this.get("/admin/snack.json", () => {
  return response({ name: "snack name", description: "snack description" });
});

```

You can read the above code as “for any request to `/admin/snack.json`, respond with the following `response`.”

If you refresh the URL `/qunit?module=Acceptance%3A%20Snack`, your acceptance test should retrieve its data via pretender and the tests should pass.

### Where to go from here

You might try building out a small feature, and adding tests to make sure it works. You could even try using [TDD](https://en.wikipedia.org/wiki/Test-driven_development) by creating your tests before you write any code on the front end. Depending on what you’re working on and your personal preferences, you might find this a more enjoyable way to go about this. Good luck and happy coding 🙂

* * *

This document is version controlled - suggest changes [on github](https://github.com/discourse/discourse/blob/main/docs/developer-guides/docs/03-code-internals/04-acceptance-tests.md).

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [January 31, 2017, 9:53pm UTC](https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167/2 "2017-01-31T21:53:50Z")

</div>

My prior experience in writing qunit tests was based on the other howto

> [@Developing Discourse Plugins - Part 6 - Add acceptance tests](https://meta.discourse.org/t/beginner-s-guide-to-creating-discourse-plugins-part-6-acceptance-tests/32619):
>
> Previous tutorial: [Developing Discourse Plugins - Part 5 - Add an admin interface](https://meta.discourse.org/t/developing-discourse-plugins-part-5-add-an-admin-interface/31761) Did you know that Discourse has two large test suites for its code base? On the server side, our Ruby code has a test suite that uses [rspec](https://rspec.info/). For the browser application, we have a [qunit](https://qunitjs.com/) suite that has [ember-testing](https://guides.emberjs.com/release/testing/testing-application/) included. Assuming you have a development environment set up, if you visit the http://localhost:3000/tests URL you will start running the JavaScript test suite in your browser. One fun aspect is that …

i.e. “acceptance” was simply

```plaintext
acceptance("Purple Tentacle", { loggedIn: true });

```

I have seen in other plugins where the test code contained “fake” JSON to test against. I wasn’t sure if that would be as good as testing against “real” data, so I wanted to avoid doing it that way.

The six tests passed, but I got a couple of rather angry looking “unhandled request” errors.

After finding an example of some “setup” code, I tried it and it solved the errors.

> <https://github.com/Mittineague/discourse-newpage/blob/master/test/javascripts/acceptance/discourse-newpage-test.js.es6#L7-L18>

It works, but I’m not really sure why, nor why it’s needed for some but not for the majority of plugins I’ve seen that have qunit tests.

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [February 1, 2017, 6:22pm UTC](https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167/3 "2017-02-01T18:22:01Z")

</div>

For a long time we weren’t great with testing plugins, so not many people followed our example and added tests.

You are right to add a response using [pretender](https://github.com/pretenderjs/pretender) to handle AJAX calls.

---

<div class="post-metadata">

### Author: ![davidag](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/davidag/32/363501_2.png) [@davidag](https://meta.discourse.org/u/davidag)
#### Post date: [February 23, 2024, 12:42pm UTC](https://meta.discourse.org/t/write-acceptance-tests-and-component-tests-for-ember-code-in-discourse/49167/4 "2024-02-23T12:42:10Z")

</div>

Just a note that the `/qunit` path is obsolete. It’s `/tests` now. It took me a while to figure it out 🙂
