Visit Routes, Click Links, Assert Pages
Application (Acceptance) Tests
setupApplicationTest boots the full app in a single process for true end-to-end flows — visit, click, fillIn, assert.
What you'll learn
- Use setupApplicationTest
- Drive flows with visit, click, and fillIn
- Stub the network with ember-cli-mirage or msw
Acceptance tests boot the whole app — router, services, components — and drive it like a real user. They are the slowest layer, so reserve them for critical paths.
A Signup Flow
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, click, fillIn, currentURL } from '@ember/test-helpers';
module('Acceptance | signup', function (hooks) {
setupApplicationTest(hooks);
test('signs up and lands on dashboard', async function (assert) {
await visit('/signup');
await fillIn('input[name=email]', 'a@b.co');
await fillIn('input[name=password]', 'shh!');
await click('button[type=submit]');
assert.strictEqual(currentURL(), '/dashboard');
assert.dom('[data-test-greeting]').includesText('Welcome');
});
}); visit boots the app at a URL and waits for everything to settle.
Mocking the Network
You almost never want real HTTP in tests. Two popular options:
- ember-cli-mirage — purpose-built for Ember Data; declarative models and factories.
- msw — service-worker style; works the same as your other apps.
// tests/mirage/index.ts (mirage example)
import { createServer } from 'miragejs';
export function startMirage() {
return createServer({
routes() {
this.post('/api/signup', () => ({ ok: true }));
},
});
} data-test-* Selectors
Add explicit hooks for tests so refactors do not break:
<button data-test-save type="submit">Save</button> await click('[data-test-save]');