mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
Supported ?include=count.posts
for Collections API
Unfortuantely our framework is bookshelf centric so we have to refer to the `withRelated` property rather than a more generic `include` property. The collection entity already contains the list of post ids, so we can just return the length of that array.
This commit is contained in:
parent
431f0ed842
commit
3d0825ea2f
@ -17,8 +17,16 @@ module.exports = {
|
||||
'limit',
|
||||
'order',
|
||||
'page',
|
||||
'filter'
|
||||
'filter',
|
||||
'include'
|
||||
],
|
||||
validation: {
|
||||
options: {
|
||||
include: {
|
||||
values: ['count.posts']
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions: true,
|
||||
query(frame) {
|
||||
return collectionsService.api.getAll(frame.options);
|
||||
@ -29,10 +37,20 @@ module.exports = {
|
||||
headers: {
|
||||
cacheInvalidate: false
|
||||
},
|
||||
options: [
|
||||
'include'
|
||||
],
|
||||
data: [
|
||||
'id',
|
||||
'slug'
|
||||
],
|
||||
validation: {
|
||||
options: {
|
||||
include: {
|
||||
values: ['count.posts']
|
||||
}
|
||||
}
|
||||
},
|
||||
permissions: true,
|
||||
async query(frame) {
|
||||
let model;
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* @returns {SerializedCollection}
|
||||
*/
|
||||
const mapper = (collection) => {
|
||||
const mapper = (collection, frame) => {
|
||||
let json;
|
||||
if (collection.toJSON) {
|
||||
json = collection.toJSON();
|
||||
@ -24,6 +24,12 @@ const mapper = (collection) => {
|
||||
updated_at: (json.updated_at || json.updatedAt).toISOString().replace(/\d{3}Z$/, '000Z')
|
||||
};
|
||||
|
||||
if (frame?.options?.withRelated?.includes('count.posts')) {
|
||||
serialized.count = {
|
||||
posts: json.posts.length
|
||||
};
|
||||
}
|
||||
|
||||
return serialized;
|
||||
};
|
||||
|
||||
|
@ -1172,6 +1172,64 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Browse Can browse Collections and include the posts count 1: [body] 1`] = `
|
||||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"posts": 13,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "All posts",
|
||||
"feature_image": null,
|
||||
"filter": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"slug": "latest",
|
||||
"title": "Latest",
|
||||
"type": "automatic",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
Object {
|
||||
"count": Object {
|
||||
"posts": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Featured posts",
|
||||
"feature_image": null,
|
||||
"filter": "featured:true",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"slug": "featured",
|
||||
"title": "Featured",
|
||||
"type": "automatic",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
"meta": Object {
|
||||
"pagination": Object {
|
||||
"limit": 2,
|
||||
"next": null,
|
||||
"page": 1,
|
||||
"pages": 1,
|
||||
"prev": null,
|
||||
"total": 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Browse Can browse Collections and include the posts count 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": "619",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Can add a Collection 1: [body] 1`] = `
|
||||
Object {
|
||||
"collections": Array [
|
||||
@ -1378,6 +1436,74 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Can read a Collection by id and slug and include the post counts 1: [body] 1`] = `
|
||||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"posts": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Featured posts",
|
||||
"feature_image": null,
|
||||
"filter": "featured:true",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"slug": "featured",
|
||||
"title": "Featured",
|
||||
"type": "automatic",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Can read a Collection by id and slug and include the post counts 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": "284",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Can read a Collection by id and slug and include the post counts 3: [body] 1`] = `
|
||||
Object {
|
||||
"collections": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"posts": 2,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"description": "Featured posts",
|
||||
"feature_image": null,
|
||||
"filter": "featured:true",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"slug": "featured",
|
||||
"title": "Featured",
|
||||
"type": "automatic",
|
||||
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Can read a Collection by id and slug and include the post counts 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": "284",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Version, Origin, Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Collections API Cannot delete a built in collection 1: [body] 1`] = `
|
||||
Object {
|
||||
"errors": Array [
|
||||
|
@ -102,6 +102,22 @@ describe('Collections API', function () {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('Can browse Collections and include the posts count', async function () {
|
||||
await agent
|
||||
.get('/collections/?include=count.posts')
|
||||
.expectStatus(200)
|
||||
.matchHeaderSnapshot({
|
||||
'content-version': anyContentVersion,
|
||||
etag: anyEtag
|
||||
})
|
||||
.matchBodySnapshot({
|
||||
collections: [
|
||||
{...matchCollection, count: {posts: 13}},
|
||||
{...matchCollection, count: {posts: 2}}
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Can read a Collection by id and slug', async function () {
|
||||
@ -158,6 +174,38 @@ describe('Collections API', function () {
|
||||
.expectStatus(204);
|
||||
});
|
||||
|
||||
it('Can read a Collection by id and slug and include the post counts', async function () {
|
||||
const {body: {collections: [collection]}} = await agent.get(`/collections/slug/featured/?include=count.posts`)
|
||||
.expectStatus(200)
|
||||
.matchHeaderSnapshot({
|
||||
'content-version': anyContentVersion,
|
||||
etag: anyEtag
|
||||
})
|
||||
.matchBodySnapshot({
|
||||
collections: [{
|
||||
...matchCollection,
|
||||
count: {
|
||||
posts: 2
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
await agent.get(`/collections/${collection.id}/?include=count.posts`)
|
||||
.expectStatus(200)
|
||||
.matchHeaderSnapshot({
|
||||
'content-version': anyContentVersion,
|
||||
etag: anyEtag
|
||||
})
|
||||
.matchBodySnapshot({
|
||||
collections: [{
|
||||
...matchCollection,
|
||||
count: {
|
||||
posts: 2
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edit', function () {
|
||||
let collectionToEdit;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user