mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added property mapper to collections responses
closes https://github.com/TryGhost/Team/issues/3259 - API output mappers (soon to be serializers) are meant to work based on allowlist set of output properties. Having the allowlist early on will allow to track the API evolution consistently.
This commit is contained in:
parent
fdd73d01b7
commit
b52ec948b0
7 changed files with 108 additions and 17 deletions
|
@ -35,6 +35,20 @@ export class Collection {
|
|||
this.deleted = data.deleted;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
title: this.title,
|
||||
slug: this.slug,
|
||||
description: this.description,
|
||||
type: this.type,
|
||||
filter: this.filter,
|
||||
featureImage: this.featureImage,
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt
|
||||
};
|
||||
}
|
||||
|
||||
static validateDateField(date: any, fieldName: string): Date {
|
||||
if (!date) {
|
||||
return new Date();
|
||||
|
|
|
@ -52,12 +52,14 @@ export class CollectionsService {
|
|||
};
|
||||
}
|
||||
|
||||
async destroy(id: string): Promise<void> {
|
||||
async destroy(id: string): Promise<Collection | null> {
|
||||
const collection = await this.getById(id);
|
||||
|
||||
if (collection) {
|
||||
collection.deleted = true;
|
||||
await this.save(collection);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,32 @@ describe('Collection', function () {
|
|||
assert.ok((collection.deleted === false), 'deleted should be false');
|
||||
});
|
||||
|
||||
it('Can serialize Collection to JSON', async function () {
|
||||
const collection = await Collection.create({
|
||||
title: 'Serialize me'
|
||||
});
|
||||
|
||||
const json = collection.toJSON();
|
||||
|
||||
assert.ok(json);
|
||||
assert.equal(json.id, collection.id);
|
||||
assert.equal(json.title, 'Serialize me');
|
||||
assert.ok(collection.createdAt instanceof Date);
|
||||
assert.ok(collection.updatedAt instanceof Date);
|
||||
assert.equal(Object.keys(json).length, 9, 'should only have 9 keys');
|
||||
assert.deepEqual(Object.keys(json), [
|
||||
'id',
|
||||
'title',
|
||||
'slug',
|
||||
'description',
|
||||
'type',
|
||||
'filter',
|
||||
'featureImage',
|
||||
'createdAt',
|
||||
'updatedAt'
|
||||
]);
|
||||
});
|
||||
|
||||
it('Can create a Collection with predefined ID', async function () {
|
||||
const id = new ObjectID();
|
||||
const savedCollection = await Collection.create({
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* @param {import('@tryghost/collections').Collection} collection
|
||||
*
|
||||
* @returns {SerializedCollection}
|
||||
*/
|
||||
const mapper = (collection) => {
|
||||
const json = collection.toJSON();
|
||||
|
||||
const serialized = {
|
||||
id: json.id,
|
||||
title: json.title,
|
||||
slug: json.slug,
|
||||
description: json.description,
|
||||
type: json.type,
|
||||
filter: json.filter,
|
||||
feature_image: json.featureImage,
|
||||
created_at: json.createdAt.toISOString().replace(/\d{3}Z$/, '000Z'),
|
||||
updated_at: json.updatedAt.toISOString().replace(/\d{3}Z$/, '000Z')
|
||||
};
|
||||
|
||||
return serialized;
|
||||
};
|
||||
|
||||
module.exports = mapper;
|
||||
|
||||
/**
|
||||
* @typedef {Object} SerializedCollection
|
||||
* @prop {string} id
|
||||
* @prop {string} title
|
||||
* @prop {string} slug
|
||||
* @prop {string} description
|
||||
* @prop {string} type
|
||||
* @prop {string} filter
|
||||
* @prop {string} feature_image
|
||||
* @prop {string} created_at
|
||||
* @prop {string} updated_at
|
||||
*/
|
|
@ -3,6 +3,7 @@ module.exports = {
|
|||
activityFeedEvents: require('./activity-feed-events'),
|
||||
authors: require('./authors'),
|
||||
comments: require('./comments'),
|
||||
collections: require('./collections'),
|
||||
emails: require('./emails'),
|
||||
emailBatches: require('./email-batches'),
|
||||
emailFailures: require('./email-failures'),
|
||||
|
|
|
@ -4,10 +4,11 @@ exports[`Collections API Can add a Collection 1: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Test Collection Description",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -17,7 +18,7 @@ exports[`Collections API Can add a Collection 2: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "137",
|
||||
"content-length": "201",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -32,10 +33,11 @@ exports[`Collections API Can browse Collections 1: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Test Collection Description",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
"meta": Object {
|
||||
|
@ -55,7 +57,7 @@ exports[`Collections API Can browse Collections 2: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "224",
|
||||
"content-length": "288",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -68,9 +70,10 @@ exports[`Collections API Can delete a Collection 1: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection to Delete",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -80,7 +83,7 @@ exports[`Collections API Can delete a Collection 2: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "103",
|
||||
"content-length": "167",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -140,9 +143,10 @@ exports[`Collections API Can edit a Collection 1: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection to Edit",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -152,7 +156,7 @@ exports[`Collections API Can edit a Collection 2: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "101",
|
||||
"content-length": "165",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -167,9 +171,10 @@ exports[`Collections API Can edit a Collection 3: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection Edited",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -179,7 +184,7 @@ exports[`Collections API Can edit a Collection 4: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "100",
|
||||
"content-length": "164",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -193,9 +198,10 @@ exports[`Collections API Can read a Collection 1: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection to Read",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -205,7 +211,7 @@ exports[`Collections API Can read a Collection 2: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "101",
|
||||
"content-length": "165",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
@ -220,9 +226,10 @@ exports[`Collections API Can read a Collection 3: [body] 1`] = `
|
|||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"deleted": false,
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"title": "Test Collection to Read",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -232,7 +239,7 @@ exports[`Collections API Can read a Collection 4: [headers] 1`] = `
|
|||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "101",
|
||||
"content-length": "165",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
|
|
@ -10,11 +10,14 @@ const {
|
|||
anyEtag,
|
||||
anyErrorId,
|
||||
anyLocationFor,
|
||||
anyObjectId
|
||||
anyObjectId,
|
||||
anyISODateTime
|
||||
} = matchers;
|
||||
|
||||
const matchCollection = {
|
||||
id: anyObjectId
|
||||
id: anyObjectId,
|
||||
created_at: anyISODateTime,
|
||||
updated_at: anyISODateTime
|
||||
};
|
||||
|
||||
describe('Collections API', function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue