Ghost/ghost/collections/test/collections.test.ts
Naz 25e0cb12c0
Added "getBySlug" method to Collections Service
refs https://github.com/TryGhost/Team/issues/3423

- This is a convenience method that should allow fetching collections by their slug. It is a great developer experience for in case when fetching built-in collections like "featured" and "index", so can avoid an extra call to find the collection and it's ide one wants to use.
2023-06-16 16:31:50 +07:00

340 lines
15 KiB
TypeScript

import assert from 'assert';
import {CollectionsService, CollectionsRepositoryInMemory} from '../src/index';
import {PostsRepositoryInMemory} from './fixtures/PostsRepositoryInMemory';
import {posts} from './fixtures/posts';
const initPostsRepository = (): PostsRepositoryInMemory => {
const postsRepository = new PostsRepositoryInMemory();
for (const post of posts) {
const collectionPost = {
id: post.id,
title: post.title,
slug: post.slug,
featured: post.featured,
published_at: post.published_at,
deleted: false
};
postsRepository.save(collectionPost);
}
return postsRepository;
};
describe('CollectionsService', function () {
let collectionsService: CollectionsService;
beforeEach(async function () {
const collectionsRepository = new CollectionsRepositoryInMemory();
const postsRepository = initPostsRepository();
collectionsService = new CollectionsService({
collectionsRepository,
postsRepository
});
});
it('Instantiates a CollectionsService', function () {
assert.ok(collectionsService, 'CollectionsService should initialize');
});
it('Can do CRUD operations on a collection', async function () {
const savedCollection = await collectionsService.createCollection({
title: 'testing collections',
description: 'testing collections description',
type: 'manual',
filter: null
});
const createdCollection = await collectionsService.getById(savedCollection.id);
assert.ok(createdCollection, 'Collection should be saved');
assert.ok(createdCollection.id, 'Collection should have an id');
assert.equal(createdCollection.title, 'testing collections', 'Collection title should match');
const allCollections = await collectionsService.getAll();
assert.equal(allCollections.data.length, 1, 'There should be one collection');
await collectionsService.destroy(createdCollection.id);
const deletedCollection = await collectionsService.getById(savedCollection.id);
assert.equal(deletedCollection, null, 'Collection should be deleted');
});
it('Can retrieve a collection by slug', async function () {
const savedCollection = await collectionsService.createCollection({
title: 'slug test',
slug: 'get-me-by-slug',
type: 'manual',
filter: null
});
const retrievedCollection = await collectionsService.getBySlug('get-me-by-slug');
assert.ok(retrievedCollection, 'Collection should be saved');
assert.ok(retrievedCollection.slug, 'Collection should have a slug');
assert.equal(savedCollection.title, 'slug test', 'Collection title should match');
const nonExistingCollection = await collectionsService.getBySlug('i-do-not-exist');
assert.equal(nonExistingCollection, null, 'Collection should not exist');
});
it('Throws when built in collection is attempted to be deleted', async function () {
const collection = await collectionsService.createCollection({
title: 'Featured Posts',
slug: 'featured',
description: 'Collection of featured posts',
type: 'automatic',
deletable: false,
filter: 'featured:true'
});
await assert.rejects(async () => {
await collectionsService.destroy(collection.id);
}, (err: any) => {
assert.equal(err.message, 'Cannot delete builtin collection', 'Error message should match');
assert.equal(err.context, `The collection ${collection.id} is a builtin collection and cannot be deleted`, 'Error context should match');
return true;
});
});
describe('getCollectionsForPost', function () {
it('Can get collections for a post', async function () {
const collection = await collectionsService.createCollection({
title: 'testing collections',
type: 'manual'
});
await collectionsService.addPostToCollection(collection.id, posts[0]);
const collections = await collectionsService.getCollectionsForPost(posts[0].id);
assert.equal(collections.length, 1, 'There should be one collection');
assert.equal(collections[0].id, collection.id, 'Collection should be the correct one');
});
});
describe('getAllPosts', function () {
it('Can get paged posts of a collection', async function () {
const collection = await collectionsService.createCollection({
title: 'testing paging',
type: 'manual'
});
for (const post of posts) {
await collectionsService.addPostToCollection(collection.id, post);
}
const postsPage1 = await collectionsService.getAllPosts(collection.id, {page: 1, limit: 2});
assert.ok(postsPage1, 'Posts should be returned');
assert.equal(postsPage1.meta.pagination.page, 1, 'Page should be 1');
assert.equal(postsPage1.meta.pagination.limit, 2, 'Limit should be 2');
assert.equal(postsPage1.meta.pagination.pages, 2, 'Pages should be 2');
assert.equal(postsPage1.data.length, 2, 'There should be 2 posts');
assert.equal(postsPage1.data[0].id, posts[0].id, 'First post should be the correct one');
assert.equal(postsPage1.data[1].id, posts[1].id, 'Second post should be the correct one');
const postsPage2 = await collectionsService.getAllPosts(collection.id, {page: 2, limit: 2});
assert.ok(postsPage2, 'Posts should be returned');
assert.equal(postsPage2.meta.pagination.page, 2, 'Page should be 2');
assert.equal(postsPage2.meta.pagination.limit, 2, 'Limit should be 2');
assert.equal(postsPage2.meta.pagination.pages, 2, 'Pages should be 2');
assert.equal(postsPage2.data.length, 2, 'There should be 2 posts');
assert.equal(postsPage2.data[0].id, posts[2].id, 'First post should be the correct one');
assert.equal(postsPage2.data[1].id, posts[3].id, 'Second post should be the correct one');
});
it('Throws when trying to get posts of a collection that does not exist', async function () {
await assert.rejects(async () => {
await collectionsService.getAllPosts('fake id', {});
}, (err: any) => {
assert.equal(err.message, 'Collection not found', 'Error message should match');
assert.equal(err.context, 'Collection with id: fake id does not exist', 'Error context should match');
return true;
});
});
});
describe('addPostToCollection', function () {
it('Can add a Post to a Collection', async function () {
const collection = await collectionsService.createCollection({
title: 'testing collections',
description: 'testing collections description',
type: 'manual'
});
const editedCollection = await collectionsService.addPostToCollection(collection.id, posts[0]);
assert.equal(editedCollection?.posts.length, 1, 'Collection should have one post');
assert.equal(editedCollection?.posts[0].id, posts[0].id, 'Collection should have the correct post');
});
it('Does not error when trying to add a post to a collection that does not exist', async function () {
const editedCollection = await collectionsService.addPostToCollection('fake id', posts[0]);
assert(editedCollection === null);
});
});
describe('edit', function () {
it('Can edit existing collection', async function () {
const savedCollection = await collectionsService.createCollection({
title: 'testing collections',
description: 'testing collections description',
type: 'manual'
});
const editedCollection = await collectionsService.edit({
id: savedCollection.id,
title: 'Edited title',
description: 'Edited description',
feature_image: '/assets/images/edited.jpg'
});
assert.equal(editedCollection?.title, 'Edited title', 'Collection title should be edited');
assert.equal(editedCollection?.description, 'Edited description', 'Collection description should be edited');
assert.equal(editedCollection?.feature_image, '/assets/images/edited.jpg', 'Collection feature_image should be edited');
assert.equal(editedCollection?.type, 'manual', 'Collection type should not be edited');
});
it('Resolves to null when editing unexistend collection', async function () {
const editedCollection = await collectionsService.edit({
id: '12345'
});
assert.equal(editedCollection, null, 'Collection should be null');
});
it('Adds a Post to a Collection', async function () {
const collection = await collectionsService.createCollection({
title: 'testing collections',
description: 'testing collections description',
type: 'manual'
});
const editedCollection = await collectionsService.edit({
id: collection.id,
posts: [{
id: posts[0].id
}]
});
assert.equal(editedCollection?.posts.length, 1, 'Collection should have one post');
assert.equal(editedCollection?.posts[0].id, posts[0].id, 'Collection should have the correct post');
assert.equal(editedCollection?.posts[0].sort_order, 0, 'Collection should have the correct post sort order');
});
it('Removes a Post from a Collection', async function () {
const collection = await collectionsService.createCollection({
title: 'testing collections',
description: 'testing collections description',
type: 'manual'
});
let editedCollection = await collectionsService.edit({
id: collection.id,
posts: [{
id: posts[0].id
}, {
id: posts[1].id
}]
});
assert.equal(editedCollection?.posts.length, 2, 'Collection should have two posts');
editedCollection = await collectionsService.removePostFromCollection(collection.id, posts[0].id);
assert.equal(editedCollection?.posts.length, 1, 'Collection should have one posts');
});
it('Returns null when removing post from non existing collection', async function () {
const collection = await collectionsService.removePostFromCollection('i-do-not-exist', posts[0].id);
assert.equal(collection, null, 'Collection should be null');
});
});
describe('Automatic Collections', function () {
it('Can create an automatic collection', async function () {
const collection = await collectionsService.createCollection({
title: 'I am automatic',
description: 'testing automatic collection',
type: 'automatic',
filter: 'featured:true'
});
assert.equal(collection.type, 'automatic', 'Collection should be automatic');
assert.equal(collection.filter, 'featured:true', 'Collection should have the correct filter');
assert.equal(collection.posts.length, 2, 'Collection should have two posts');
});
it('Populates collection when the type is changed to automatic and filter is present', async function () {
const collection = await collectionsService.createCollection({
title: 'I am automatic',
description: 'testing automatic collection',
type: 'manual'
});
assert.equal(collection.type, 'manual', 'Collection should be manual');
assert.equal(collection.posts.length, 0, 'Collection should have no posts');
const automaticCollection = await collectionsService.edit({
id: collection.id,
type: 'automatic',
filter: 'featured:true'
});
assert.equal(automaticCollection?.posts.length, 2, 'Collection should have two featured post');
assert.equal(automaticCollection?.posts[0].id, 'post-3-featured', 'Collection should have the correct post');
});
it('Updates the automatic collection posts when the filter is changed', async function () {
let collection = await collectionsService.createCollection({
title: 'I am automatic',
description: 'testing automatic collection',
type: 'automatic',
filter: 'featured:true'
});
assert.equal(collection?.type, 'automatic', 'Collection should be automatic');
assert.equal(collection?.posts.length, 2, 'Collection should have two featured post');
assert.equal(collection?.posts[0].id, 'post-3-featured', 'Collection should have the correct post');
assert.equal(collection?.posts[1].id, 'post-4-featured', 'Collection should have the correct post');
let updatedCollection = await collectionsService.edit({
id: collection.id,
filter: 'slug:post-2'
});
assert.equal(updatedCollection?.posts.length, 1, 'Collection should have one post');
assert.equal(updatedCollection?.posts[0].id, 'post-2', 'Collection should have the correct post');
});
// @NOTE: add a more comprehensive test as this one is too basic
it('Updates all automatic collections', async function () {
let collection1 = await collectionsService.createCollection({
title: 'Featured Collection 1',
description: 'testing automatic collection',
type: 'automatic',
filter: 'featured:true'
});
let collection2 = await collectionsService.createCollection({
title: 'Featured Collection 2',
description: 'testing automatic collection',
type: 'automatic',
filter: 'featured:true'
});
assert.equal(collection1.posts.length, 2);
assert.equal(collection2.posts.length, 2);
await collectionsService.updateAutomaticCollections();
assert.equal(collection1.posts.length, 2);
assert.equal(collection2.posts.length, 2);
});
});
});