Server
The Mirage server.
Note that this
within your routes
function refers to the server instance, which is the same instance that server
refers to in your tests.
Properties
db: any
Returns the Mirage Db instance.
inflector: any
Mirage needs know the singular and plural versions of certain words for some of its APIs to work.
For example, whenever you define a model
new Server({
models: {
post: Model
}
})
Mirage will pluralize the word "post" and use it to create a db.posts
database collection.
To accomplish this, Mirage uses an object called an Inflector. An Inflector is an object with two methods, singularize
and pluralize
, that Mirage will call whenever it needs to inflect a word.
Mirage has a default inflector, so if you write
new Server()
you'll be using the node inflected package. This can be customized if you have irregular words or need to change the defaults. You can wead more in the guide on customizing inflections.
You typically should be able to make your customizations using the provided inflector. It's good to match any custom inflections your backend uses, as this will keep your Mirage code more consistent and simpler.
You can also override the inflector completely and provide your own pluralize
and singularize
methods:
new Server({
inflector: {
pluralize(word) {
// your logic
},
singularize(word) {
// your logic
}
}
})
logging: any
Set to true
or false
to explicitly specify logging behavior.
By default, server responses are logged in non-testing environments. Logging is disabled by default in testing, so as not to clutter CI test runner output.
For example, to enable logging in tests, write the following:
test('I can view all users', function() {
server.logging = true;
server.create('user');
visit('/users');
// ...
});
You can also write a custom log message using the Pretender server's handledRequest
hook. (You can access the pretender server from your Mirage server via server.pretender
.)
To override,
new Server({
routes() {
this.pretender.handledRequest = function(verb, path, request) {
let { responseText } = request;
// log request and response data
}
}
})
namespace: any
Set the base namespace used for all routes defined with get
, post
, put
or del
.
For example,
new Server({
routes() {
this.namespace = '/api';
// this route will handle the URL '/api/contacts'
this.get('/contacts', 'contacts');
}
})
Note that only routes defined after this.namespace
are affected. This is useful if you have a few one-off routes that you don't want under your namespace:
new Server({
routes() {
// this route handles /auth
this.get('/auth', function() { ...});
this.namespace = '/api';
// this route will handle the URL '/api/contacts'
this.get('/contacts', 'contacts');
};
})
If your app is loaded from the filesystem vs. a server (e.g. via Cordova or Electron vs. localhost
or https://yourhost.com/
), you will need to explicitly define a namespace. Likely values are /
(if requests are made with relative paths) or https://yourhost.com/api/...
(if requests are made to a defined server).
For a sample implementation leveraging a configured API host & namespace, check out this issue comment.
pretender: any
Mirage uses pretender.js as its xhttp interceptor. In your Mirage config, this.pretender
refers to the actual Pretender instance, so any config options that work there will work here as well.
new Server({
routes() {
this.pretender.handledRequest = (verb, path, request) => {
console.log(`Your server responded to ${path}`);
}
}
})
Refer to Pretender's docs if you want to change any options on your Pretender instance.
schema: any
Returns the Mirage Schema (ORM) instance.
timing: any
Set the number of milliseconds for the the Server's response time.
By default there's a 400ms delay during development, and 0 delay in testing (so your tests run fast).
new Server({
routes() {
this.timing = 400; // default
}
})
To set the timing for individual routes, see the timing
option for route handlers.
urlPrefix: any
Sets a string to prefix all route handler URLs with.
Useful if your app makes API requests to a different port.
new Server({
routes() {
this.urlPrefix = 'http://localhost:8080'
}
})
Methods
create(type: any, traitsAndOverrides: any): any
Generates a single model of type type, inserts it into the database (giving it an id), and returns the data that was added.
test("I can view a contact's details", function() {
let contact = server.create('contact');
visit('/contacts/' + contact.id);
andThen(() => {
equal( find('h1').text(), 'The contact is Link');
});
});
You can override the attributes from the factory definition with a hash passed in as the second parameter. For example, if we had this factory
export default Factory.extend({
name: 'Link'
});
we could override the name like this:
test("I can view the contacts", function() {
server.create('contact', {name: 'Zelda'});
visit('/');
andThen(() => {
equal( find('p').text(), 'Zelda' );
});
});
createList(type: any, amount: any, traitsAndOverrides: any): any
Creates amount models of type type, optionally overriding the attributes from the factory with attrs.
Returns the array of records that were added to the database.
Here's an example from a test:
test("I can view the contacts", function() {
server.createList('contact', 5);
let youngContacts = server.createList('contact', 5, {age: 15});
visit('/');
andThen(function() {
equal(currentRouteName(), 'index');
equal( find('p').length, 10 );
});
});
And one from setting up your development database:
new Server({
seeds(server) {
let contact = server.create('contact')
server.createList('address', 5, { contact })
}
})
loadFixtures(...args: String): any
By default, fixtures
will be loaded during testing if you don't have factories defined, and during development if you don't have seeds
defined. You can use loadFixtures()
to also load fixture files in either of these environments, in addition to using factories to seed your database.
server.loadFixtures()
loads all the files, and server.loadFixtures(file1, file2...)
loads selective fixture files.
For example, in a test you may want to start out with all your fixture data loaded:
test('I can view the photos', function() {
server.loadFixtures();
server.createList('photo', 10);
visit('/');
andThen(() => {
equal( find('img').length, 10 );
});
});
or in development, you may want to load a few reference fixture files, and use factories to define the rest of your data:
new Server({
...,
seeds(server) {
server.loadFixtures('countries', 'states');
let author = server.create('author');
server.createList('post', 10, {author_id: author.id});
}
})
passthrough(...paths: String, options: Array): any
By default, if your app makes a request that is not defined in your server config, Mirage will throw an error. You can use passthrough
to whitelist requests, and allow them to pass through your Mirage server to the actual network layer.
Note: Put all passthrough config at the bottom of your routes, to give your route handlers precedence.
To ignore paths on your current host (as well as configured namespace
), use a leading /
:
this.passthrough('/addresses');
You can also pass a list of paths, or call passthrough
multiple times:
this.passthrough('/addresses', '/contacts');
this.passthrough('/something');
this.passthrough('/else');
These lines will allow all HTTP verbs to pass through. If you want only certain verbs to pass through, pass an array as the last argument with the specified verbs:
this.passthrough('/addresses', ['post']);
this.passthrough('/contacts', '/photos', ['get']);
You can pass a function to passthrough
to do a runtime check on whether or not the request should be handled by Mirage. If the function returns true
Mirage will not handle the request and let it pass through.
this.passthrough(request => {
return request.queryParams.skipMirage;
});
If you want all requests on the current domain to pass through, simply invoke the method with no arguments:
this.passthrough();
Note again that the current namespace (i.e. any namespace
property defined above this call) will be applied.
You can also allow other-origin hosts to passthrough. If you use a fully-qualified domain name, the namespace
property will be ignored. Use two * wildcards to match all requests under a path:
this.passthrough('http://api.foo.bar/**');
this.passthrough('http://api.twitter.com/v1/cards/**');
In versions of Pretender prior to 0.12, passthrough
only worked with jQuery >= 2.x. As long as you're on Pretender@0.12 or higher, you should be all set.
shutdown(): any
Shutdown the server and stop intercepting network requests.