Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: braaaaain draaaaain #125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 102 additions & 56 deletions test/integration/json-api/v1/base-format/create/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,121 @@ describe('creatingResources', function() {
return Fixture.reset();
});

it('must respond to a successful request with an object', function() {
// 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 })
.send({ data: [bookData] })
.promise()
.then(function(res) {
expect(res.status).to.be.within(200, 299);

// document structure tests
expect(res.body).to.be.an('object');

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) {

// document structure tests
expect(res.body).to.be.an('object');

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) {

// document structure tests
expect(res.body).to.be.an('object');

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 an unsuccessful request with a JSON object containing a collection keyed by "errors" in the top level', function() {
return Agent.request('POST', '/v1/books')
.send({})
.promise()
.then(function(res) {
expect(res.status).to.be.within(400, 499); // any error

// document structure tests
expect(res.body).to.be.an('object');

expect(res.body.errors).to.be.an('array');
});
});
Expand All @@ -55,18 +153,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 +255,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.

Loading