Merge pull request #72 from hashicorp/fix-empty-list-responses
fix: 🐛 prenormalize findAll responses in application adapter
This commit is contained in:
7 files changed
+119
No files matched your search
@@ -6,6 +6,36 @@ import { dasherize } from '@ember/string';
|
||||
import { pluralize } from 'ember-inflector';
|
||||
import { isArray } from '@ember/array';
|
||||
|
||||
/**
|
||||
* Returns true if the payload is an empty object, false otherwise.
|
||||
* Taken from Ember Data fetch-manager and "positivized" the name.
|
||||
* @param {object} adapterPayload
|
||||
* @return {boolean}
|
||||
*/
|
||||
function payloadIsBlank(adapterPayload) {
|
||||
if (Array.isArray(adapterPayload)) {
|
||||
return false;
|
||||
} else {
|
||||
return Object.keys(adapterPayload || {}).length === 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the resonse is empty, returns a new payload containing an empty `items`
|
||||
* array, as expected by the serializer. Otherwise, returns the response.
|
||||
*
|
||||
* Normally this would be performed 100% inside the serializer.
|
||||
* However, the fetch manager, which we cannot easily override, glues the
|
||||
* adapter and serializers together. Before it forwards a response from the
|
||||
* adapter on to the serializer, it checks for an "empty" response. If the
|
||||
* response is empty, fetch manager throws and error and never forwards it on.
|
||||
* @param {object} response
|
||||
* @return {object}
|
||||
*/
|
||||
function prenormalizeArrayResponse(response) {
|
||||
return payloadIsBlank(response) ? {items: []} : response;
|
||||
}
|
||||
|
||||
export default class ApplicationAdapter extends RESTAdapter {
|
||||
// =attributes
|
||||
|
||||
@@ -36,6 +66,26 @@ export default class ApplicationAdapter extends RESTAdapter {
|
||||
return dasherize(pluralize(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts "empty" responses and adds an empty `items` array.
|
||||
* @override
|
||||
* @method findAll
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
findAll() {
|
||||
return super.findAll(...arguments).then(prenormalizeArrayResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts "empty" responses and adds an empty `items` array.
|
||||
* @override
|
||||
* @method query
|
||||
* @return {Promise} promise
|
||||
*/
|
||||
query() {
|
||||
return super.query(...arguments).then(prenormalizeArrayResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides default ajax method by rewritting PUT requests as PATCH.
|
||||
* PATCH is the request method used by our API for updates.
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-eslint": "^5.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.2",
|
||||
"ember-cli-mirage": "^1.1.7",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
export default function() {
|
||||
|
||||
// These comments are here to help you get started. Feel free to delete them.
|
||||
|
||||
/*
|
||||
Config (with defaults).
|
||||
|
||||
Note: these only affect routes defined *after* them!
|
||||
*/
|
||||
|
||||
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
|
||||
// this.namespace = ''; // make this `/api`, for example, if your API is namespaced
|
||||
// this.timing = 400; // delay for each request, automatically set to 0 during testing
|
||||
|
||||
/*
|
||||
Shorthand cheatsheet:
|
||||
|
||||
this.get('/posts');
|
||||
this.post('/posts');
|
||||
this.get('/posts/:id');
|
||||
this.put('/posts/:id'); // or this.patch
|
||||
this.del('/posts/:id');
|
||||
|
||||
https://www.ember-cli-mirage.com/docs/route-handlers/shorthands
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default function(/* server */) {
|
||||
|
||||
/*
|
||||
Seed your development database using your factories.
|
||||
This data will not be loaded in your tests.
|
||||
*/
|
||||
|
||||
// server.createList('post', 10);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { JSONAPISerializer } from 'ember-cli-mirage';
|
||||
|
||||
export default JSONAPISerializer.extend({
|
||||
});
|
||||
@@ -3,9 +3,12 @@ import { setupTest } from 'ember-qunit';
|
||||
import config from 'ember-get-config';
|
||||
import RESTAdapter from '@ember-data/adapter/rest';
|
||||
import { InvalidError } from '@ember-data/adapter/error';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import { Response } from 'miragejs';
|
||||
|
||||
module('Unit | Adapter | application', function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
test('its namespace is equal to the configured namespace', function (assert) {
|
||||
assert.expect(2);
|
||||
@@ -24,12 +27,23 @@ module('Unit | Adapter | application', function (hooks) {
|
||||
assert.expect(1);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
// TODO this is icky, should be changed to a spy or stub
|
||||
const originalAjax = RESTAdapter.prototype.ajax;
|
||||
RESTAdapter.prototype.ajax = (url, type) => {
|
||||
assert.equal(type, 'PATCH');
|
||||
RESTAdapter.prototype.ajax = originalAjax;
|
||||
};
|
||||
adapter.ajax('/', 'PUT');
|
||||
});
|
||||
|
||||
test('it prenormalizes "empty" responses into a form that the fetch-manager will not reject', async function (assert) {
|
||||
assert.expect(1);
|
||||
const adapter = this.owner.lookup('adapter:project');
|
||||
const store = this.owner.lookup('service:store');
|
||||
this.server.get('/v1/projects', () => new Response({}));
|
||||
const prenormalized = await adapter.findAll(store, {modelName: 'project'}, null, []);
|
||||
assert.deepEqual(prenormalized, {items: []});
|
||||
});
|
||||
|
||||
test('it correctly identifies 400 responses as invalid', function (assert) {
|
||||
assert.expect(2);
|
||||
const adapter = this.owner.lookup('adapter:application');
|
||||
|
||||
@@ -7330,6 +7330,21 @@ ember-cli-mirage@^1.1.6:
|
||||
lodash-es "^4.17.11"
|
||||
miragejs "^0.1.31"
|
||||
|
||||
ember-cli-mirage@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-mirage/-/ember-cli-mirage-1.1.7.tgz#846ec8e5199b15fa670da30dfa1708a8ee11e9dc"
|
||||
integrity sha512-4kVLXXvgHYlv30ChM47U4xYnUtphIoEj+BQwXX0QT7pvD3KQxYnmfZSwlevSEVUy2UhbsBUPw6merENb+dIQ0A==
|
||||
dependencies:
|
||||
broccoli-file-creator "^2.1.1"
|
||||
broccoli-funnel "^3.0.2"
|
||||
broccoli-merge-trees "^4.2.0"
|
||||
ember-auto-import "^1.2.19"
|
||||
ember-cli-babel "^7.5.0"
|
||||
ember-get-config "^0.2.2"
|
||||
ember-inflector "^2.0.0 || ^3.0.0"
|
||||
lodash-es "^4.17.11"
|
||||
miragejs "^0.1.31"
|
||||
|
||||
ember-cli-normalize-entity-name@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz#0b14f7bcbc599aa117b5fddc81e4fd03c4bad5b7"
|
||||
|
||||
Reference in new issue
Block a user