Skip to content

Commit

Permalink
WIP: braaaaain draaaaain
Browse files Browse the repository at this point in the history
  • Loading branch information
bobholt committed Jun 12, 2015
1 parent b831a12 commit e989c4e
Show file tree
Hide file tree
Showing 7 changed files with 939 additions and 539 deletions.
147 changes: 94 additions & 53 deletions test/integration/json-api/v1/base-format/create/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,99 @@ describe('creatingResources', function() {
return Fixture.reset();
});

// NOTE: JSON-API does not require an error here.
// See https://github.com/json-api/json-api/issues/766
it('must require a single resource object as primary data', function() {
return Agent.request('POST', '/v1/books')
.send({ data: [bookData] })
.promise()
.then(function(res) {
expect(res.status).to.equal(400);
});
});

it('The resource object **MUST** contain at least a type member.');

it('If a relationship is provided in the `relationships` member of the resource object, its value **MUST** be a relationship object with a `data` member.');

describe('clientGeneratedIds', function() {

it('may accept a client-generated ID along with a request to create a resource.');

it('An ID **MUST** be specified with an `id` key, the value of which **MUST** be a universally unique identifier.');

it('The client **SHOULD** use a properly generated and formatted *UUID* as described in RFC 4122 [RFC4122].');

it('must return `403 Forbidden` in response to an unsupported request to create a resource with a client-generated ID.');
});

describe('responses', function() {

describe('201Created', function() {

it('If a `POST` request did not include a Client-Generated ID and the requested resource has been created successfully, the server **MUST** return a `201 Created` status code.');

it('The response **SHOULD** include a `Location` header identifying the location of the newly created resource.');

it('The response **MUST** also include a document that contains the primary resource created.');

it('If the resource object returned by the response contains a `self` key in its `links` member and a `Location` header is provided, the value of the `self` member **MUST** match the value of the `Location` header.');
});

describe('202Accepted', function() {

it('If a request to create a resource has been accepted for processing, but the processing has not been completed by the time the server responds, the server **MUST** return a `202 Accepted` status code.');
});

describe('204NoContent', function() {

it('If a `POST` request did include a Client-Generated ID and the requested resource has been created successfully, the server **MUST** return either a `201 Created` status code and response document (as described above) or a `204 No Content` status code with no response document.');
});

describe('403Forbidden', function() {

it('may return `403 Forbidden` in response to an unsupported request to create a resource.');
});

describe('409Conflict', function() {

it('must return `409 Conflict` when processing a `POST` request to create a resource with a client-generated ID that already exists.', function() {
bookData.id = 1;
return Agent.request('POST', '/v1/books')
.send({ data: bookData })
.promise()
.then(function(res) {
expect(res.status).to.equal(409);
});
});

it('must return `409 Conflict` when processing a `POST` request in which the resource object\'s type is not among the type(s) that constitute the collection represented by the endpoint.', function() {
bookData.type = 'authors';
return Agent.request('POST', '/v1/books')
.send({ data: bookData })
.promise()
.then(function(res) {
expect(res.status).to.equal(409);
});
});

it('should include error details and provide enough information to recognize the source of the conflict.');
});

describe('OtherResponses', function() {

it('may respond with other HTTP status codes.');

it('may include error details with error responses.');

it('must prepare responses, and a client **MUST** interpret responses, in accordance with HTTP semantics.');
});
});
});

/* OLD CREATE TESTS
describe('creatingResources', function() {
it('must respond to a successful request with an object', function() {
return Agent.request('POST', '/v1/books')
.send({ data: bookData })
Expand Down Expand Up @@ -55,18 +148,6 @@ describe('creatingResources', function() {
});
});
// TODO: Source/DB test: verify rollback on error
// it('must not allow partial updates');

it('must require a single resource object as primary data', function() {
return Agent.request('POST', '/v1/books')
.send({ data: [bookData] })
.promise()
.then(function(res) {
expect(res.status).to.equal(400);
});
});

it('must require primary data to have a type member', function() {
delete bookData.type;
return Agent.request('POST', '/v1/books')
Expand Down Expand Up @@ -169,46 +250,6 @@ describe('creatingResources', function() {
});
});
});

// Endpoints will respond with a 201 on all create requests
// Tested above.
// describe('204NoContent', function() {
// it('must respond with either 201 or 204 if the request included a client-generated ID');
// });

// API decision to not create the route - endpoints will always support creation
// describe('403Forbidden', function() {
// it('should return 403 Forbidden in response to an unsupported creation request');
// });

describe.skip('409Conflict', function() {
it('must return 409 Conflict when processing a request to create a resource with an existing client-generated ID', function() {
bookData.id = 1;
return Agent.request('POST', '/v1/books')
.send({ data: bookData })
.promise()
.then(function(res) {
expect(res.status).to.equal(409);
});
});

it('must return 409 Conflict when processing a request where the type does not match the endpoint', function() {
bookData.type = 'authors';
return Agent.request('POST', '/v1/books')
.send({ data: bookData })
.promise()
.then(function(res) {
expect(res.status).to.equal(409);
});
});
});

// Not testable as written. Each error handling branch should be
// unit-tested for proper HTTP semantics.
// describe('otherResponses', function() {
// it('should use other HTTP codes to represent errors');
// it('must interpret errors in accordance with HTTP semantics');
// it('should return error details');
// });
});
});
*/
71 changes: 40 additions & 31 deletions test/integration/json-api/v1/base-format/delete/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {expect} from 'chai';
import _ from 'lodash';
// import _ from 'lodash';

import Agent from '../../../../../app/agent';
import Fixture from '../../../../../app/fixture';
Expand All @@ -10,20 +10,49 @@ describe('deletingResources', function() {
return Fixture.reset();
});

it('must not require a content-type header of application/vnd.api+json', function() {
return Agent.request('DELETE', '/v1/chapters/1')
.promise()
.then(function(res) {
expect(res.status).to.equal(204);
describe('responses', function() {

describe('202Accepted', function() {

it('If a deletion request has been accepted for processing, but the processing has not been completed by the time the server responds, the server **MUST** return a `202 Accepted` status code.');
});

describe('204NoContent', function() {

it('A server **MUST** return a `204 No Content` status code if a deletion request is successful and no content is returned.', function() {
return Agent.request('DELETE', '/v1/chapters/1')
.promise()
.then(function (res) {
expect(res.status).to.equal(204);
expect(res.body).to.deep.equal({});
});
});
});

describe('200OK', function() {

it('A server **MUST** return a `200 OK` status code if a deletion request is successful and the server responds with only top-level meta data.');
});

describe('otherResponses', function() {

it('A server **MAY** respond with other HTTP status codes.');

it('A server **MAY** include error details with error responses.');

it('A server **MUST** prepare responses, and a client **MUST** interpret responses, in accordance with HTTP semantics.');
});
});
});

/* OLD DELETE TESTS
describe('deletingResources', function() {
it('must respond to a successful request with an empty body', function() {
it('must not require a content-type header of application/vnd.api+json', function() {
return Agent.request('DELETE', '/v1/chapters/1')
.promise()
.then(function (res) {
expect(res.status).to.be.within(200, 299);
expect(res.body).to.deep.equal({});
.then(function(res) {
expect(res.status).to.equal(204);
});
});
Expand All @@ -35,9 +64,6 @@ describe('deletingResources', function() {
});
});
// TODO: Source/DB test: verify rollback on error
it('must not allow partial updates');

it('should delete resources when a DELETE request is made to the resource URL', function() {
var first, second, deleteId;
Expand All @@ -60,16 +86,6 @@ describe('deletingResources', function() {
});
describe('responses', function() {

describe('204NoContent', function() {
it('must return 204 No Content on a successful DELETE request', function() {
return Agent.request('DELETE', '/v1/chapters/1')
.promise()
.then(function(res) {
expect(res.status).to.equal(204);
});
});

it('must return 204 No Content when processing a request to delete a resource that does not exist', function() {
return Agent.request('DELETE', '/v1/chapters/9999')
.promise()
Expand All @@ -78,13 +94,6 @@ describe('deletingResources', function() {
});
});
});

// Not testable as written. Each error handling branch should be
// unit-tested for proper HTTP semantics.
// describe('otherResponses', function() {
// it('should use other HTTP codes to represent errors');
// it('must interpret errors in accordance with HTTP semantics');
// it('should return error details');
// });
});
});
*/
18 changes: 8 additions & 10 deletions test/integration/json-api/v1/base-format/errors/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e989c4e

Please sign in to comment.