Skip to content

Commit 09e6f26

Browse files
committed
Mock server
* Organize tests and examples * Add first pass at docs * Test with Ember Data model
1 parent 26024da commit 09e6f26

19 files changed

Lines changed: 214 additions & 53 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { fetch } from 'whatwg-fetch';
2+
3+
let createMock = async function(path, method, statusCode, response) {
4+
return await fetch('/__mock-request', {
5+
method: 'post',
6+
headers: {
7+
"Content-Type": "application/json",
8+
},
9+
body: JSON.stringify({
10+
path,
11+
method,
12+
statusCode,
13+
response
14+
}),
15+
});
16+
}
17+
18+
export let mockServer = {
19+
async get(path, response, status = 200) {
20+
return createMock(path, "GET", status, response);
21+
},
22+
23+
async post(path, response, status = 200) {
24+
return createMock(path, "POST", status, response);
25+
},
26+
27+
async patch(path, response, status = 200) {
28+
return createMock(path, "PATCH", status, response);
29+
},
30+
31+
async put(path, response, status = 200) {
32+
return createMock(path, "PUT", status, response);
33+
},
34+
35+
async delete(path, response, status = 200) {
36+
return createMock(path, "DELETE", status, response);
37+
},
38+
39+
async cleanUp() {
40+
return fetch('/__cleanup-mocks');
41+
}
42+
};

addon-test-support/index.js

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,15 @@
11
import { fetch } from 'whatwg-fetch';
22
import { setupContext, teardownContext } from '@ember/test-helpers';
3+
import { mockServer } from './-private/mock-server';
34
import param from 'jquery-param';
45

5-
let cleanupMocks = function() {
6-
return fetch('/__cleanup-mocks');
7-
};
8-
9-
let createMock = async function(path, method, statusCode, response) {
10-
return await fetch('/__mock-request', {
11-
method: 'post',
12-
headers: {
13-
"Content-Type": "application/json",
14-
},
15-
body: JSON.stringify({
16-
path,
17-
method,
18-
statusCode,
19-
response
20-
}),
21-
});
22-
}
23-
24-
export let mockServer = {
25-
async get(path, response, status = 200) {
26-
return createMock(path, "GET", status, response);
27-
},
28-
29-
async post(path, response, status = 200) {
30-
return createMock(path, "POST", status, response);
31-
},
32-
33-
async patch(path, response, status = 200) {
34-
return createMock(path, "PATCH", status, response);
35-
},
36-
37-
async put(path, response, status = 200) {
38-
return createMock(path, "PUT", status, response);
39-
},
40-
41-
async delete(path, response, status = 200) {
42-
return createMock(path, "DELETE", status, response);
43-
}
44-
};
45-
466
export function setup(hooks) {
477
hooks.beforeEach(function() {
488
return setupContext(this);
499
});
5010

5111
hooks.afterEach(async function() {
52-
await cleanupMocks();
12+
await mockServer.cleanUp();
5313
return teardownContext(this);
5414
});
5515
}
@@ -76,6 +36,8 @@ export async function visit(url, options = {}) {
7636
return result;
7737
}
7838

39+
export { mockServer };
40+
7941
// private
8042

8143
let fetchFromEmberCli = async function(url, headers) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import DS from 'ember-data';
2+
3+
export default DS.JSONAPIAdapter.extend({
4+
namespace: 'api'
5+
});

tests/dummy/app/models/post.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import DS from 'ember-data';
2+
3+
export default DS.Model.extend({
4+
title: DS.attr('string'),
5+
});

tests/dummy/app/pods/application/route.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ export default Route.extend({
77
afterModel() {
88
this.set('headData.title', 'Fastboot testing');
99
}
10-
1110
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Network mocking
2+
3+
Just about every Ember application ends up having pages that require data from an external API. It's common to use tools like [Mirage](https://www.ember-cli-mirage.com/) to mock the network when testing these applications.
4+
5+
It makes sense that we would also want to mock the network in FastBoot tests. However, since FastBoot runs inside of Node.js, we'll need to use a network mocking library that is written for node applications.
6+
7+
FastBoot Testing exposes an API for networking mocking in node that can be used to intercept requests made from your FastBoot app.
8+
9+
The following example shows how to mock a test that fetches blog post data.
10+
11+
```js
12+
import { module, test } from 'qunit';
13+
import { setup, visit, mockServer } from 'ember-cli-fastboot-testing/test-support';
14+
15+
module('Fastboot | Blog post page', function(hooks) {
16+
setup(hooks);
17+
18+
test('it can render a blog post', async function(assert) {
19+
await mockServer.get('/api/posts/1', {
20+
type: 'post',
21+
id: '1',
22+
attributes: {
23+
title: 'Hello world!'
24+
}
25+
});
26+
27+
await visit('/posts/1');
28+
29+
assert.dom('[data-test-id="title"]').hasText("Hello world!");
30+
});
31+
});
32+
```
33+
34+
The `mockServer#get` method maps a URL to a response for the lifecycle of the test. At the end of each test the `mockServer` is reset.
35+
36+
By default, the `mockServer` will use a status code of 200. However, an optional status code can be passed in as the third parameter.
37+
38+
```js
39+
test('it renders the 404 page when it cannot fetch a blog post', async function(assert) {
40+
await mockServer.get(
41+
'/api/posts/1',
42+
{ error: 'Post not found' },
43+
404
44+
);
45+
46+
await visit('/posts/1');
47+
48+
assert.dom('[data-test-id="page-not-found"]').exists();
49+
});
50+
```
51+
52+
The `mockServer` also exposes `post`, `patch`, `put`, and `delete` mocking methods.

tests/dummy/app/pods/docs/template.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
{{nav.section 'Usage & options'}}
1111
{{nav.item 'Visit helper' 'docs.visit'}}
12+
{{nav.item 'Network mocking' 'docs.network-mocking'}}
1213

1314
{{nav.section 'Tips & tricks'}}
1415
{{nav.item 'Debugging' 'docs.debugging'}}

tests/dummy/app/pods/examples/network/post/route.js renamed to tests/dummy/app/pods/examples/network/other/get-request/route.js

File renamed without changes.

tests/dummy/app/pods/examples/network/get/template.hbs renamed to tests/dummy/app/pods/examples/network/other/get-request/template.hbs

File renamed without changes.

tests/dummy/app/pods/examples/network/get/route.js renamed to tests/dummy/app/pods/examples/network/other/post-request/route.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import fetch from 'fetch';
44
export default Route.extend({
55

66
async model() {
7-
let response = await fetch('/api/posts');
7+
let response = await fetch('/api/posts', { method: 'post' });
88
return await response.json();
99
}
1010

0 commit comments

Comments
 (0)