├── .editorconfig ├── .ember-cli ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── LICENSE.md ├── README.md ├── addon ├── .gitkeep ├── index.js └── lib │ ├── json-utils.js │ ├── logger.js │ ├── logging.js │ └── responses.js ├── app └── .gitkeep ├── config ├── ember-try.js └── environment.js ├── ember-cli-build.js ├── index.js ├── package.json ├── testem.js ├── tests ├── dummy │ ├── app │ │ ├── app.js │ │ ├── components │ │ │ └── .gitkeep │ │ ├── controllers │ │ │ └── .gitkeep │ │ ├── helpers │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── models │ │ │ └── .gitkeep │ │ ├── resolver.js │ │ ├── router.js │ │ ├── routes │ │ │ └── .gitkeep │ │ ├── styles │ │ │ └── app.css │ │ ├── templates │ │ │ ├── application.hbs │ │ │ └── components │ │ │ │ └── .gitkeep │ │ └── views │ │ │ └── .gitkeep │ ├── config │ │ ├── environment.js │ │ └── targets.js │ └── public │ │ └── robots.txt ├── helpers │ ├── .gitkeep │ └── ajax.js ├── index.html ├── test-helper.js └── unit │ ├── .gitkeep │ ├── fake-server-test.js │ ├── passthrough-request-test.js │ └── stub-request │ └── requests-test.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | ecmaVersion: 2017, 5 | sourceType: 'module' 6 | }, 7 | plugins: [ 8 | 'ember' 9 | ], 10 | extends: [ 11 | 'eslint:recommended', 12 | 'plugin:ember/recommended' 13 | ], 14 | env: { 15 | browser: true 16 | }, 17 | rules: { 18 | }, 19 | overrides: [ 20 | // node files 21 | { 22 | files: [ 23 | 'index.js', 24 | 'testem.js', 25 | 'ember-cli-build.js', 26 | 'config/**/*.js', 27 | 'tests/dummy/config/**/*.js' 28 | ], 29 | excludedFiles: [ 30 | 'app/**', 31 | 'addon/**', 32 | 'tests/dummy/app/**' 33 | ], 34 | parserOptions: { 35 | sourceType: 'script', 36 | ecmaVersion: 2015 37 | }, 38 | env: { 39 | browser: false, 40 | node: true 41 | }, 42 | plugins: ['node'], 43 | rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { 44 | // add your custom rules and overrides for node files here 45 | }) 46 | } 47 | ] 48 | }; 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # misc 12 | /.sass-cache 13 | /connect.lock 14 | /coverage/* 15 | /libpeerconnection.log 16 | npm-debug.log* 17 | yarn-error.log 18 | testem.log 19 | 20 | # ember-try 21 | .node_modules.ember-try/ 22 | bower.json.ember-try 23 | package.json.ember-try 24 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /bower_components 2 | /config/ember-try.js 3 | /dist 4 | /tests 5 | /tmp 6 | **/.gitkeep 7 | .bowerrc 8 | .editorconfig 9 | .ember-cli 10 | .eslintrc.js 11 | .gitignore 12 | .watchmanconfig 13 | .travis.yml 14 | bower.json 15 | ember-cli-build.js 16 | testem.js 17 | 18 | # ember-try 19 | .node_modules.ember-try/ 20 | bower.json.ember-try 21 | package.json.ember-try 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | # we recommend testing addons with the same minimum supported node version as Ember CLI 5 | # so that your addon works for all apps 6 | - "4" 7 | 8 | sudo: false 9 | dist: trusty 10 | 11 | addons: 12 | chrome: stable 13 | firefox: latest 14 | 15 | cache: 16 | yarn: true 17 | 18 | env: 19 | global: 20 | # See https://git.io/vdao3 for details. 21 | - JOBS=1 22 | matrix: 23 | # we recommend new addons test the current and previous LTS 24 | # as well as latest stable release (bonus points to beta/canary) 25 | - EMBER_TRY_SCENARIO=ember-lts-2.12 26 | - EMBER_TRY_SCENARIO=ember-lts-2.16 27 | - EMBER_TRY_SCENARIO=ember-lts-2.18 28 | - EMBER_TRY_SCENARIO=ember-release 29 | - EMBER_TRY_SCENARIO=ember-beta 30 | - EMBER_TRY_SCENARIO=ember-canary 31 | - EMBER_TRY_SCENARIO=ember-default 32 | 33 | matrix: 34 | fast_finish: true 35 | allow_failures: 36 | - env: EMBER_TRY_SCENARIO=ember-canary 37 | 38 | before_install: 39 | - curl -o- -L https://yarnpkg.com/install.sh | bash 40 | - export PATH=$HOME/.yarn/bin:$PATH 41 | 42 | install: 43 | - yarn install --no-lockfile --non-interactive 44 | 45 | script: 46 | - yarn lint:js 47 | # Usually, it's ok to finish the test scenario without reverting 48 | # to the addon's original dependency state, skipping "cleanup". 49 | - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO --skip-cleanup 50 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/201-created/ember-cli-fake-server.svg?branch=master)](https://travis-ci.org/201-created/ember-cli-fake-server) 2 | [![Ember Observer Score](http://emberobserver.com/badges/ember-cli-fake-server.svg)](http://emberobserver.com/addons/ember-cli-fake-server) 3 | ![Dependencies](https://david-dm.org/201-created/ember-cli-fake-server.svg) 4 | [![Code Climate](https://codeclimate.com/github/201-created/ember-cli-fake-server/badges/gpa.svg)](https://codeclimate.com/github/201-created/ember-cli-fake-server) 5 | 6 | # ember-cli-fake-server 7 | 8 | ember-cli-fake-server is an ember-cli addon that makes it extremely simple to stub ajax requests in your ember app. It uses [Pretender](https://github.com/pretenderjs/pretender) internally. If you need a more comprehensive stubbing solution, consider [ember-cli-mirage](http://www.ember-cli-mirage.com/). 9 | 10 | ## Installation 11 | 12 | * `ember install ember-cli-fake-server` 13 | * Call `FakeServer.start()` to start stubbing, and `FakeServer.stop()` to stop stubbing or use `setupFakeServer(hooks)` when using "new test api". 14 | * In tests, use `stubRequest(verb, path, callback)` to stub ajax requests 15 | 16 | ## Usage 17 | 18 | This addon exposes a default `FakeServer` export and a named `stubRequest` export from `'ember-cli-fake-server'`. In your ember code, you must call `FakeServer.start()` to start it intercepting ajax requests, and `FakeServer.stop()` to turn it back off. This should be done in your test suite's setup and teardown methods. 19 | 20 | In your test, use `stubRequest` for each ajax request you would like to stub. 21 | 22 | Here's an example ember test: 23 | 24 | ```javascript 25 | import { module, test } from 'qunit'; 26 | import jQuery from 'jquery'; 27 | import { stubRequest, setupFakeServer } from 'ember-cli-fake-server'; 28 | 29 | module('using ember-cli-fake-server', function(hooks) { 30 | setupFakeServer(hooks); 31 | 32 | test('some ajax', function(assert) { 33 | const done = assert.async(); 34 | assert.expect(1); 35 | 36 | let didCallAjax = false; 37 | stubRequest('get', '/some-url', (request) => { 38 | didCallAjax = true; 39 | request.ok({}); // send empty response back 40 | }); 41 | 42 | jQuery.ajax('/some-url', { 43 | complete() { 44 | assert.ok(didCallAjax, 'called ajax'); 45 | done(); 46 | } 47 | }); 48 | }); 49 | }); 50 | ``` 51 | 52 | ## The `stubRequest` method 53 | 54 | The `stubRequest` method takes 3 parameters: `(verb, path, callback)`. 55 | 56 | * `verb` should be one of the verbs that Pretender understands: 'get', 'put', 'post', 'delete', 'path' and 'head' 57 | * `path` is the url (without the scheme, protocol or domain) that you are stubbing out, e.g. `'/api/users/1'` 58 | * For more details on the `callback` parameter, see "Responding To Requests" below 59 | 60 | ### Responding to Requests 61 | 62 | The callback that you pass to `stubRequest` will be called with a `request` parameter that you can use to respond to the request and also read information about the request. 63 | 64 | The `request` parameter has the following methods, corresponding to HTTP status codes: 65 | * `ok` — status code 200 66 | * `error` — 422 67 | * `notFound` — 404 68 | * `created` — 201 69 | * `accepted` - 202 70 | * `noContent` — 204 71 | * `unauthorized` — 401 72 | 73 | Call the appropriate method on `request` with your JSON payload to make `stubRequest` respond with that status code and payload. 74 | 75 | Examples: 76 | ```javascript 77 | stubRequest('post', '/users', (request) => { 78 | // sends a "201 Created" response with the JSON for a user: 79 | request.create({user: {id:1 , name: 'newly created user'}}); 80 | }); 81 | 82 | stubRequest('get', '/users/1', (request) => { 83 | // send a "200 Ok" response with the JSON for a user: 84 | request.ok({user: {id: 1, name: 'the user'}}); 85 | }); 86 | 87 | stubRequest('get', '/users/99', (request) => { 88 | // send an empty "404 Not Found" response 89 | request.notFound(); 90 | }); 91 | 92 | stubRequest('put', '/users/1', (request) => { 93 | // send a "422 Unprocessable Entity" response back with the given JSON payload 94 | request.error({error: {email: 'is invalid'}}); 95 | }); 96 | ``` 97 | 98 | ### Reading JSON and other data from Requests 99 | 100 | The `request` parameter passed to your callback also has a `json` method that returns the incoming JSON payload. 101 | 102 | Example: 103 | 104 | ```javascript 105 | stubRequest('post', '/users/1', (request) => { 106 | alert(request.json().user.name); // alerts "Cory" 107 | }); 108 | 109 | jQuery.ajax('/users/1', { 110 | type: 'POST', 111 | data: JSON.stringify({user: {id: 1, name: "Cory"}}), 112 | dataType: 'json', 113 | contentType: 'application/json; charset=utf-8' 114 | }); 115 | ``` 116 | 117 | ### Reading other request data 118 | 119 | The `request` parameter passed to your callback function is the same one (albeit with some additional methods added on) that Pretender uses, so you can use the same properties it exposes for reading data such as `request.params` and [`request.queryParams`](https://github.com/pretenderjs/pretender#query-parameters). 120 | 121 | ### Unexpected requests 122 | 123 | ember-cli-fake-server is configured to intercept *all* ajax requests after you call `FakeServer.start()`. Any ajax request that was not stubbed before it was made will [throw an error](https://github.com/201-created/ember-cli-fake-server/blob/master/addon/lib/logging.js#L4) explaining the method and path of the unhandled request. 124 | 125 | ### Request logging 126 | 127 | By default ember-cli-fake-server will log all requests that it handles. To enable/disable logging of successfully handled requests, provide an options object to `FakeServer.start()` that defines a `logging` attribute, for example: 128 | 129 | ```javascript 130 | FakeServer.start({ logging: false }); 131 | ``` 132 | 133 | or 134 | 135 | ```javascript 136 | setupFakeServer(hooks, { logging: false }); 137 | ``` 138 | 139 | Unhandled requests are always logged. 140 | 141 | ### Modifying responses 142 | 143 | Use `FakeServer.configure.afterResponse(fn)` to specify an afterResponse 144 | callback. This can be used to globally modify all requests in some specified 145 | way. The function you pass to `afterResponse` will be called with two arguments: 146 | `response` and `request`. It must return an array of `[statusCode, headers, json|string]`. 147 | 148 | Example: 149 | 150 | ```javascript 151 | FakeServer.configure.afterResponse(function(response /*, request */) { 152 | // response === [200, {"content-type": "application/json"}, {foo: 'bar'}] 153 | let [status, headers, json] = response; 154 | if (json.foo) { // optionally modify json 155 | json.foo = 'baz' 156 | } 157 | return [status, headers, json]; 158 | }); 159 | 160 | stubRequest('get', '/users/1', function(request) { 161 | let response = this.ok({foo: 'bar'}); 162 | 163 | // `response` is passed as 1st argument to afterResponse hook, 164 | // `request` is passed as 2nd argument. 165 | return response; 166 | }); 167 | ``` 168 | -------------------------------------------------------------------------------- /addon/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/addon/.gitkeep -------------------------------------------------------------------------------- /addon/index.js: -------------------------------------------------------------------------------- 1 | import Pretender from 'pretender'; 2 | import { assert } from '@ember/debug'; 3 | import * as Responses from './lib/responses'; 4 | import * as Logging from './lib/logging'; 5 | import * as JSONUtils from './lib/json-utils'; 6 | import { warn } from './lib/logger'; 7 | 8 | let currentServer; 9 | 10 | let _config = defaultConfig(); 11 | 12 | function defaultConfig() { 13 | return { 14 | preparePath: (path) => path, 15 | fixtureFactory: () => { 16 | warn('[FakeServer] `fixture` called but no fixture factory is registered'); 17 | }, 18 | afterResponse: (response) => response 19 | }; 20 | } 21 | 22 | function bindResponses(request, responseRef){ 23 | Object.keys(Responses.STATUS_CODES).forEach((key) => { 24 | request[key] = (...args) => { 25 | if (responseRef.response) { 26 | throw new Error(`[FakeServer] Stubbed Request responded with "${key}" after already responding`); 27 | } 28 | let response = Responses[key](...args); 29 | responseRef.response = response; 30 | return response; 31 | }; 32 | }); 33 | Object.keys(Responses.RESPONSE_ALIASES).forEach((key) => { 34 | let aliases = Responses.RESPONSE_ALIASES[key]; 35 | aliases.forEach((alias) => request[alias] = request[key]); 36 | }); 37 | } 38 | 39 | export function setupFakeServer(hooks, options = {}) { 40 | hooks.beforeEach(function() { 41 | FakeServer.start(options); 42 | }); 43 | 44 | hooks.afterEach(function() { 45 | FakeServer.stop(); 46 | }); 47 | } 48 | 49 | export function passthroughRequest(verb, path) { 50 | path = _config.preparePath(path); 51 | assert('[FakeServer] cannot passthrough request if FakeServer is not running', 52 | !!currentServer); 53 | 54 | currentServer[verb.toLowerCase()](path, currentServer.passthrough); 55 | } 56 | 57 | export function stubRequest(verb, path, callback){ 58 | path = _config.preparePath(path); 59 | assert('[FakeServer] cannot stub request if FakeServer is not running', 60 | !!currentServer); 61 | 62 | let boundCallback = (request) => { 63 | let responseRef = {}; 64 | 65 | bindResponses(request, responseRef); 66 | 67 | request.json = () => JSONUtils.jsonFromRequest(request); 68 | request.fixture = _config.fixtureFactory; 69 | 70 | let context = { 71 | json: JSONUtils.jsonFromRequest, 72 | fixture: _config.fixtureFactory 73 | }; 74 | Object.keys(Responses.STATUS_CODES).forEach(key => { 75 | context[key] = Responses[key]; 76 | }); 77 | Object.keys(Responses.RESPONSE_ALIASES).forEach(key => { 78 | let aliases = Responses.RESPONSE_ALIASES[key]; 79 | aliases.forEach(alias => context[alias] = context[key]); 80 | }); 81 | 82 | let returnValue = callback.call(context, request); 83 | returnValue = returnValue || responseRef.response; 84 | if (!returnValue) { 85 | throw new Error( 86 | `[FakeServer] No return value for stubbed request for ${verb} ${path}. 87 | Use \`request.ok(json)\` or similar`); 88 | } 89 | return _config.afterResponse(returnValue, request); 90 | }; 91 | 92 | currentServer[verb.toLowerCase()](path, boundCallback); 93 | } 94 | 95 | const FakeServer = { 96 | configure: { 97 | fixtureFactory(fixtureFactory) { 98 | _config.fixtureFactory = fixtureFactory; 99 | }, 100 | preparePath(fn) { 101 | _config.preparePath = fn; 102 | }, 103 | afterResponse(fn) { 104 | _config.afterResponse = fn; 105 | } 106 | }, 107 | 108 | 109 | start(options = {}) { 110 | assert('[FakeServer] Cannot start FakeServer while already started. ' + 111 | 'Ensure you call `FakeServer.stop()` first.', 112 | !FakeServer.isRunning()); 113 | 114 | let logging = typeof options.logging === 'undefined' ? true : options.logging; 115 | 116 | currentServer = this._currentServer = new Pretender(); 117 | currentServer.prepareBody = JSONUtils.stringifyJSON; 118 | currentServer.unhandledRequest = Logging.unhandledRequest; 119 | 120 | if (logging) { 121 | currentServer.handledRequest = Logging.handledRequest; 122 | } 123 | }, 124 | 125 | isRunning() { 126 | return !!currentServer; 127 | }, 128 | 129 | stop() { 130 | if (!FakeServer.isRunning()) { 131 | warn('[FakeServer] called `stop` without having started.'); 132 | return; 133 | } 134 | currentServer.shutdown(); 135 | currentServer = this._currentServer = null; 136 | 137 | _config = defaultConfig(); 138 | } 139 | }; 140 | 141 | export default FakeServer; 142 | -------------------------------------------------------------------------------- /addon/lib/json-utils.js: -------------------------------------------------------------------------------- 1 | import { warn } from './logger'; 2 | 3 | export function stringifyJSON(json={}){ 4 | return JSON.stringify(json); 5 | } 6 | 7 | export function jsonFromRequest(request){ 8 | let json = {}; 9 | if (request.requestBody) { 10 | try { 11 | json = JSON.parse(request.requestBody); 12 | } catch(e) { 13 | warn(`[FakeServer] Failed to parse json from request.requestBody "${request.requestBody}" (error: ${e})`); 14 | } 15 | } 16 | 17 | return json; 18 | } 19 | -------------------------------------------------------------------------------- /addon/lib/logger.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | export function warn() { 4 | if (typeof console !== 'undefined') { 5 | console.warn(...arguments); 6 | } 7 | } 8 | 9 | export function error() { 10 | if (typeof console !== 'undefined') { 11 | console.error(...arguments); 12 | } 13 | } 14 | 15 | export function log() { 16 | if (typeof console !== 'undefined') { 17 | console.log(...arguments); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /addon/lib/logging.js: -------------------------------------------------------------------------------- 1 | import { log, error } from './logger'; 2 | 3 | export function unhandledRequest(verb, path, request){ 4 | const msg = `[FakeServer] received unhandled request for ${verb} ${path}`; 5 | error(msg, request); 6 | throw new Error(msg); 7 | } 8 | 9 | export function handledRequest(verb, path) { 10 | log(`[FakeServer] handled: ${verb} ${path}`); 11 | } 12 | -------------------------------------------------------------------------------- /addon/lib/responses.js: -------------------------------------------------------------------------------- 1 | export const STATUS_CODES = { 2 | error: 422, 3 | notFound: 404, 4 | ok: 200, 5 | created: 201, 6 | accepted: 202, 7 | noContent: 204, 8 | unauthorized: 401 9 | }; 10 | 11 | export const RESPONSE_ALIASES = { 12 | ok: ['success'] 13 | }; 14 | 15 | const jsonMimeType = {"Content-Type": "application/json"}; 16 | 17 | export function error(status, errors){ 18 | if (!errors) { errors = status; status = STATUS_CODES.error; } 19 | 20 | return [status, jsonMimeType, errors]; 21 | } 22 | 23 | export function notFound(status, json){ 24 | if (!json) { json = status || {}; status = STATUS_CODES.notFound; } 25 | 26 | return [status, jsonMimeType, json]; 27 | } 28 | 29 | export function ok(status, json){ 30 | if (!json) { json = status; status = STATUS_CODES.ok; } 31 | 32 | return [status, jsonMimeType, json]; 33 | } 34 | 35 | export function created(status, json){ 36 | if (!json) { json = status; status = STATUS_CODES.created; } 37 | 38 | return [status, jsonMimeType, json]; 39 | } 40 | 41 | export function accepted(status, json){ 42 | if (!json) { json = status; status = STATUS_CODES.accepted; } 43 | 44 | return [status, jsonMimeType, json]; 45 | } 46 | 47 | export function noContent(status){ 48 | if (!status) { status = STATUS_CODES.noContent; } 49 | 50 | return [status, jsonMimeType, '']; 51 | } 52 | 53 | export function unauthorized(status){ 54 | if (!status) { status = STATUS_CODES.unauthorized; } 55 | 56 | return [status, jsonMimeType, '']; 57 | } 58 | -------------------------------------------------------------------------------- /app/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/app/.gitkeep -------------------------------------------------------------------------------- /config/ember-try.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const getChannelURL = require('ember-source-channel-url'); 4 | 5 | module.exports = function() { 6 | return Promise.all([ 7 | getChannelURL('release'), 8 | getChannelURL('beta'), 9 | getChannelURL('canary'), 10 | ]).then((urls) => { 11 | return { 12 | useYarn: true, 13 | scenarios: [ 14 | { 15 | name: 'ember-lts-2.12', 16 | npm: { 17 | devDependencies: { 18 | 'ember-source': '~2.12.0' 19 | } 20 | } 21 | }, 22 | { 23 | name: 'ember-lts-2.16', 24 | npm: { 25 | devDependencies: { 26 | 'ember-source': '~2.16.0' 27 | } 28 | } 29 | }, 30 | { 31 | name: 'ember-lts-2.18', 32 | npm: { 33 | devDependencies: { 34 | 'ember-source': '~2.18.0' 35 | } 36 | } 37 | }, 38 | { 39 | name: 'ember-release', 40 | npm: { 41 | devDependencies: { 42 | 'ember-source': urls[0] 43 | } 44 | } 45 | }, 46 | { 47 | name: 'ember-beta', 48 | npm: { 49 | devDependencies: { 50 | 'ember-source': urls[1] 51 | } 52 | } 53 | }, 54 | { 55 | name: 'ember-canary', 56 | npm: { 57 | devDependencies: { 58 | 'ember-source': urls[2] 59 | } 60 | } 61 | }, 62 | { 63 | name: 'ember-default', 64 | npm: { 65 | devDependencies: {} 66 | } 67 | } 68 | ] 69 | }; 70 | }); 71 | }; 72 | -------------------------------------------------------------------------------- /config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(/* environment, appConfig */) { 4 | return { }; 5 | }; 6 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); 4 | 5 | module.exports = function(defaults) { 6 | let app = new EmberAddon(defaults, { 7 | // Add options here 8 | }); 9 | 10 | /* 11 | This build file specifies the options for the dummy test app of this 12 | addon, located in `/tests/dummy` 13 | This build file does *not* influence how the addon or the app using it 14 | behave. You most likely want to be modifying `./index.js` or app's build file 15 | */ 16 | 17 | return app.toTree(); 18 | }; 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var lazyLoaded = {}; 4 | 5 | function lazyLoad(moduleName){ 6 | if (!lazyLoaded[moduleName]) { 7 | lazyLoaded[moduleName] = require(moduleName); 8 | } 9 | return lazyLoaded[moduleName]; 10 | } 11 | 12 | module.exports = { 13 | name: 'ember-cli-fake-server', 14 | 15 | treeFor: function() { 16 | if (this._shouldIncludeFiles()) { 17 | return this._super.treeFor.apply(this, arguments); 18 | } 19 | return this._emptyTree(); 20 | }, 21 | 22 | postprocessTree: function(type, tree) { 23 | if (type === 'js' && !this._shouldIncludeFiles()) { 24 | return this._excludeSelf(tree); 25 | } 26 | return tree; 27 | }, 28 | 29 | _excludeSelf: function(tree){ 30 | var modulePrefix = this.app.project.config(this.app.env)['modulePrefix']; 31 | var Funnel = lazyLoad('broccoli-funnel'); 32 | return new Funnel(tree, { 33 | exclude: [new RegExp('^' + modulePrefix + '/ember-cli-fake-server/')], 34 | description: 'Funnel: exclude ember-cli-fake-server' 35 | }); 36 | }, 37 | 38 | _emptyTree: function(){ 39 | var mergeTrees = lazyLoad('broccoli-merge-trees'); 40 | return mergeTrees([]); 41 | }, 42 | 43 | _shouldIncludeFiles: function(){ 44 | if (process.env.EMBER_CLI_FASTBOOT) { return false; } 45 | return this.app.env !== 'production'; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-cli-fake-server", 3 | "version": "0.6.0", 4 | "description": "An addon to simplify stubbing ajax requests and responses in ember tests.", 5 | "keywords": [ 6 | "ember-addon", 7 | "testing", 8 | "ajax", 9 | "pretender" 10 | ], 11 | "license": "MIT", 12 | "author": "Cory Forsyth", 13 | "directories": { 14 | "doc": "doc", 15 | "test": "tests" 16 | }, 17 | "repository": "http://github.com/201-created/ember-cli-fake-server", 18 | "scripts": { 19 | "build": "ember build", 20 | "lint:js": "eslint ./*.js addon addon-test-support app config lib server test-support tests", 21 | "start": "ember serve", 22 | "test": "ember try:each" 23 | }, 24 | "dependencies": { 25 | "ember-cli-babel": "^6.6.0", 26 | "ember-cli-pretender": "^1.0.1" 27 | }, 28 | "devDependencies": { 29 | "broccoli-asset-rev": "^2.4.5", 30 | "ember-cli": "~3.0.2", 31 | "ember-cli-dependency-checker": "^2.0.0", 32 | "ember-cli-eslint": "^4.2.1", 33 | "ember-cli-htmlbars": "^2.0.1", 34 | "ember-cli-htmlbars-inline-precompile": "^1.0.0", 35 | "ember-cli-inject-live-reload": "^1.4.1", 36 | "ember-cli-qunit": "^4.1.1", 37 | "ember-cli-shims": "^1.2.0", 38 | "ember-cli-sri": "^2.1.0", 39 | "ember-cli-uglify": "^2.0.0", 40 | "ember-disable-prototype-extensions": "^1.1.2", 41 | "ember-export-application-global": "^2.0.0", 42 | "ember-load-initializers": "^1.0.0", 43 | "ember-maybe-import-regenerator": "^0.1.6", 44 | "ember-resolver": "^4.0.0", 45 | "ember-source": "~3.0.0", 46 | "ember-source-channel-url": "^1.0.1", 47 | "ember-try": "^0.2.23", 48 | "eslint-plugin-ember": "^5.0.0", 49 | "eslint-plugin-node": "^5.2.1", 50 | "loader.js": "^4.2.3" 51 | }, 52 | "engines": { 53 | "node": "^4.5 || 6.* || >= 7.*" 54 | }, 55 | "ember-addon": { 56 | "configPath": "tests/dummy/config" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /testem.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test_page: 'tests/index.html?hidepassed', 3 | disable_watching: true, 4 | launch_in_ci: ['Chrome', 'Firefox'], 5 | launch_in_dev: ['Chrome'], 6 | browser_args: { 7 | Firefox: { 8 | mode: 'ci', 9 | args: ['-headless'] 10 | }, 11 | Chrome: { 12 | mode: 'ci', 13 | args: [ 14 | // --no-sandbox is needed when running Chrome inside a container 15 | process.env.TRAVIS ? '--no-sandbox' : null, 16 | 17 | '--disable-gpu', 18 | '--headless', 19 | '--remote-debugging-port=0', 20 | '--window-size=1440,900' 21 | ].filter(Boolean) 22 | } 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /tests/dummy/app/app.js: -------------------------------------------------------------------------------- 1 | import Application from '@ember/application'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | const App = Application.extend({ 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix, 9 | Resolver 10 | }); 11 | 12 | loadInitializers(App, config.modulePrefix); 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /tests/dummy/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/controllers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | 12 | 13 | 14 | 15 | {{content-for "head-footer"}} 16 | 17 | 18 | {{content-for "body"}} 19 | 20 | 21 | 22 | 23 | {{content-for "body-footer"}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/dummy/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/models/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /tests/dummy/app/router.js: -------------------------------------------------------------------------------- 1 | import EmberRouter from '@ember/routing/router'; 2 | import config from './config/environment'; 3 | 4 | const Router = EmberRouter.extend({ 5 | location: config.locationType, 6 | rootURL: config.rootURL 7 | }); 8 | 9 | Router.map(function() { 10 | }); 11 | 12 | export default Router; 13 | -------------------------------------------------------------------------------- /tests/dummy/app/routes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/routes/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/styles/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/styles/app.css -------------------------------------------------------------------------------- /tests/dummy/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 |

Welcome to Ember

2 | 3 | {{outlet}} 4 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/templates/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/views/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/dummy/app/views/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/config/environment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(environment) { 4 | let ENV = { 5 | modulePrefix: 'dummy', 6 | environment, 7 | rootURL: '/', 8 | locationType: 'auto', 9 | EmberENV: { 10 | FEATURES: { 11 | // Here you can enable experimental features on an ember canary build 12 | // e.g. 'with-controller': true 13 | }, 14 | EXTEND_PROTOTYPES: { 15 | // Prevent Ember Data from overriding Date.parse. 16 | Date: false 17 | } 18 | }, 19 | 20 | APP: { 21 | // Here you can pass flags/options to your application instance 22 | // when it is created 23 | } 24 | }; 25 | 26 | if (environment === 'development') { 27 | // ENV.APP.LOG_RESOLVER = true; 28 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 29 | // ENV.APP.LOG_TRANSITIONS = true; 30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 31 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 32 | } 33 | 34 | if (environment === 'test') { 35 | // Testem prefers this... 36 | ENV.locationType = 'none'; 37 | 38 | // keep test console output quieter 39 | ENV.APP.LOG_ACTIVE_GENERATION = false; 40 | ENV.APP.LOG_VIEW_LOOKUPS = false; 41 | 42 | ENV.APP.rootElement = '#ember-testing'; 43 | ENV.APP.autoboot = false; 44 | } 45 | 46 | if (environment === 'production') { 47 | // here you can enable a production-specific feature 48 | } 49 | 50 | return ENV; 51 | }; 52 | -------------------------------------------------------------------------------- /tests/dummy/config/targets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const browsers = [ 4 | 'last 1 Chrome versions', 5 | 'last 1 Firefox versions', 6 | 'last 1 Safari versions' 7 | ]; 8 | 9 | const isCI = !!process.env.CI; 10 | const isProduction = process.env.EMBER_ENV === 'production'; 11 | 12 | if (isCI || isProduction) { 13 | browsers.push('ie 11'); 14 | } 15 | 16 | module.exports = { 17 | browsers 18 | }; 19 | -------------------------------------------------------------------------------- /tests/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /tests/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/helpers/ajax.js: -------------------------------------------------------------------------------- 1 | import RSVP from 'rsvp'; 2 | import jQuery from "jquery"; 3 | 4 | export default function ajax(url, options) { 5 | return RSVP.cast(jQuery.ajax(url, options)).catch(() => null); 6 | } 7 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ember-cli-fake-server tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import Application from '../app'; 2 | import config from '../config/environment'; 3 | import { setApplication } from '@ember/test-helpers'; 4 | import { start } from 'ember-qunit'; 5 | 6 | setApplication(Application.create(config.APP)); 7 | 8 | start(); 9 | -------------------------------------------------------------------------------- /tests/unit/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/201-created/ember-cli-fake-server/279fd3d5076033074461fe6be04aa5c1b6f68563/tests/unit/.gitkeep -------------------------------------------------------------------------------- /tests/unit/fake-server-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from "qunit"; 2 | import FakeServer, { stubRequest, setupFakeServer } from "ember-cli-fake-server"; 3 | import ajax from "../helpers/ajax"; 4 | 5 | module("ember-cli-fake-server: FakeServer", function(hooks) { 6 | hooks.afterEach(function() { 7 | if (FakeServer.isRunning()) { 8 | FakeServer.stop(); 9 | } 10 | }); 11 | 12 | test("#start throws if called while already started", function(assert) { 13 | FakeServer.start(); 14 | 15 | assert.throws( 16 | FakeServer.start, 17 | /Cannot start FakeServer while already started/, 18 | "throws if FakeServer called while started" 19 | ); 20 | }); 21 | }); 22 | 23 | module("ember-cli-fake-server: stubRequest", function(hooks) { 24 | setupFakeServer(hooks); 25 | 26 | test("stubs ajax calls", function(assert) { 27 | assert.expect(1); 28 | 29 | stubRequest("get", "/blah", () => { 30 | assert.ok(true, "Handled request"); 31 | }); 32 | 33 | return ajax("/blah"); 34 | }); 35 | 36 | test("stubs ajax calls with upper-case verbs", function(assert) { 37 | assert.expect(1); 38 | 39 | stubRequest("GET", "/blah", () => { 40 | assert.ok(true, "Handled request"); 41 | }); 42 | 43 | return ajax("/blah"); 44 | }); 45 | 46 | test("responds to ajax", function(assert) { 47 | assert.expect(2); 48 | 49 | let payload = { foo: "bar" }; 50 | 51 | stubRequest("get", "/blah", request => { 52 | request.ok(payload); 53 | }); 54 | 55 | return ajax("/blah", { 56 | success(json, textStatus /*, jqXHR */) { 57 | assert.equal(textStatus, "success", "textStatus === success"); 58 | assert.deepEqual(json, payload, "has expected payload"); 59 | } 60 | }); 61 | }); 62 | 63 | test("#json reads JSON in request payload", function(assert) { 64 | assert.expect(1); 65 | 66 | let payload = { foo: "bar" }; 67 | 68 | stubRequest("post", "/blah", request => { 69 | assert.deepEqual(request.json(), payload, "posts payload"); 70 | request.noContent(); 71 | }); 72 | 73 | return ajax("/blah", { 74 | type: "POST", 75 | data: JSON.stringify(payload), 76 | dataType: "json", 77 | contentType: "application/json; charset=utf-8" 78 | }); 79 | }); 80 | 81 | test("FakeServer.config.afterResponse can modify responses", function(assert) { 82 | assert.expect(6); 83 | 84 | let originalResponse = [ 85 | 200, 86 | { "content-type": "application/json" }, 87 | { original: true } 88 | ]; 89 | 90 | let modifiedResponse = [ 91 | 201, 92 | { "content-type": "application/json", "x-fake-header": "foo" }, 93 | { original: false, modified: true } 94 | ]; 95 | 96 | FakeServer.configure.afterResponse((response, request) => { 97 | assert.ok(!!request, "passes request"); 98 | assert.deepEqual(response, originalResponse, "passes original response"); 99 | return modifiedResponse; 100 | }); 101 | 102 | stubRequest("get", "/blah", function() { 103 | return originalResponse; 104 | }); 105 | 106 | return ajax("/blah", { 107 | complete(jqXHR, textStatus) { 108 | assert.equal(textStatus, "success"); 109 | assert.equal(jqXHR.status, modifiedResponse[0]); 110 | assert.deepEqual( 111 | jqXHR.responseJSON, 112 | modifiedResponse[2], 113 | "uses JSON response from afterResponse handler" 114 | ); 115 | assert.ok( 116 | jqXHR.getAllResponseHeaders().indexOf("x-fake-header") !== -1, 117 | "includes headers from afterResponse handler" 118 | ); 119 | } 120 | }); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /tests/unit/passthrough-request-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from "qunit"; 2 | import FakeServer, { passthroughRequest } from "ember-cli-fake-server"; 3 | 4 | let passthrough, pretender; 5 | 6 | module("ember-cli-fake-server:stubRequest responses", function(hooks) { 7 | hooks.beforeEach(function() { 8 | FakeServer.start(); 9 | pretender = FakeServer._currentServer; 10 | passthrough = pretender.passthrough; 11 | }); 12 | 13 | hooks.afterEach(function() { 14 | if (FakeServer.isRunning()) { 15 | FakeServer.stop(); 16 | } 17 | }); 18 | 19 | test("passthroughRequest paths are passed to Pretender passthrough", function(assert) { 20 | let passedPath, passedHandler; 21 | 22 | pretender.get = function(path, handler) { 23 | passedPath = path; 24 | passedHandler = handler; 25 | }; 26 | 27 | passthroughRequest("get", "/abc/def"); 28 | 29 | assert.equal(passedPath, "/abc/def", "passes path to pretender"); 30 | assert.equal(passedHandler, passthrough, "handler is passthrough handler"); 31 | }); 32 | 33 | test("calling passthroughRequest when server is not started throws", function(assert) { 34 | FakeServer.stop(); 35 | 36 | assert.throws(() => { 37 | passthroughRequest("get", "/abc/def"); 38 | }, /cannot passthrough request if FakeServer is not running/); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/unit/stub-request/requests-test.js: -------------------------------------------------------------------------------- 1 | import { module, test } from "qunit"; 2 | import { stubRequest, setupFakeServer } from "ember-cli-fake-server"; 3 | import { 4 | STATUS_CODES, 5 | RESPONSE_ALIASES 6 | } from "ember-cli-fake-server/lib/responses"; 7 | import ajax from "../../helpers/ajax"; 8 | 9 | module("ember-cli-fake-server:stubRequest responses", function(hooks) { 10 | setupFakeServer(hooks); 11 | 12 | function testRequestMethod(methodName, code) { 13 | let message = `\`request#${methodName}\` returns status code ${code}`; 14 | 15 | test(message, function(assert) { 16 | assert.expect(1); 17 | 18 | stubRequest("get", "/", req => { 19 | req[methodName](); 20 | }); 21 | 22 | return ajax("/", { 23 | success(json, textStatus, jqXHR) { 24 | assert.equal(jqXHR.status, code, message); 25 | }, 26 | error(jqXHR /*, textStatus, errorThrown*/) { 27 | assert.equal(jqXHR.status, code, message); 28 | } 29 | }); 30 | }); 31 | } 32 | 33 | function testCallbackContext(methodName, code) { 34 | let message = `\`this#${methodName}\` returns status code ${code}`; 35 | 36 | test(message, function(assert) { 37 | assert.expect(1); 38 | 39 | stubRequest("get", "/", function() { 40 | return this[methodName](); 41 | }); 42 | 43 | return ajax("/", { 44 | success(json, textStatus, jqXHR) { 45 | assert.equal(jqXHR.status, code, message); 46 | }, 47 | error(jqXHR /*, textStatus, errorThrown*/) { 48 | assert.equal(jqXHR.status, code, message); 49 | } 50 | }); 51 | }); 52 | } 53 | 54 | Object.keys(STATUS_CODES).forEach(key => { 55 | let code = STATUS_CODES[key]; 56 | testRequestMethod(key, code); 57 | testCallbackContext(key, code); 58 | }); 59 | 60 | Object.keys(RESPONSE_ALIASES).forEach(aliasKey => { 61 | let aliases = RESPONSE_ALIASES[aliasKey]; 62 | let code = STATUS_CODES[aliasKey]; 63 | 64 | aliases.forEach(methodName => { 65 | testRequestMethod(methodName, code); 66 | testCallbackContext(methodName, code); 67 | }); 68 | }); 69 | }); 70 | --------------------------------------------------------------------------------