Improved type definitions
The PostRepository type was using `any` (an anti pattern) rather than `PostCollection`, and we had optional properties, which are not really optional. This cleans up the types and updates the tests alongside them.
This commit is contained in:
parent
2e4a483518
commit
9288f56649
@ -1,7 +1,7 @@
|
||||
// eslint-disable-next-line ghost/filenames/match-regex
|
||||
export type CollectionPost = {
|
||||
id: string;
|
||||
featured?: boolean;
|
||||
published_at?: Date;
|
||||
tags?: Array<{slug: string}>;
|
||||
featured: boolean;
|
||||
published_at: Date;
|
||||
tags: Array<{slug: string}>;
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ type CollectionPostListItemDTO = {
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
published_at: Date,
|
||||
tags?: Array<{slug: string}>;
|
||||
tags: Array<{slug: string}>;
|
||||
}
|
||||
|
||||
type ManualCollection = {
|
||||
@ -95,8 +95,7 @@ type QueryOptions = {
|
||||
}
|
||||
|
||||
interface PostsRepository {
|
||||
getAll(options: QueryOptions): Promise<any[]>;
|
||||
getBulk(ids: string[]): Promise<any[]>;
|
||||
getAll(options: QueryOptions): Promise<CollectionPost[]>;
|
||||
}
|
||||
|
||||
export class CollectionsService {
|
||||
|
@ -237,13 +237,25 @@ describe('Collection', function () {
|
||||
assert(collection.posts.length === 0);
|
||||
|
||||
const posts = [{
|
||||
id: '0'
|
||||
id: '0',
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
}, {
|
||||
id: '1'
|
||||
id: '1',
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
}, {
|
||||
id: '2'
|
||||
id: '2',
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
}, {
|
||||
id: '3'
|
||||
id: '3',
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
}];
|
||||
|
||||
collection.addPost(posts[0]);
|
||||
@ -270,7 +282,9 @@ describe('Collection', function () {
|
||||
|
||||
const added = await collection.addPost({
|
||||
id: '0',
|
||||
featured: false
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
});
|
||||
|
||||
assert.equal(added, false);
|
||||
@ -278,7 +292,9 @@ describe('Collection', function () {
|
||||
|
||||
const featuredAdded = await collection.addPost({
|
||||
id: '1',
|
||||
featured: true
|
||||
featured: true,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
});
|
||||
|
||||
assert.equal(featuredAdded, true);
|
||||
@ -293,7 +309,11 @@ describe('Collection', function () {
|
||||
assert.equal(collection.posts.length, 0);
|
||||
|
||||
collection.addPost({
|
||||
id: '0'
|
||||
id: '0',
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
|
||||
});
|
||||
|
||||
assert.equal(collection.posts.length, 1);
|
||||
@ -352,12 +372,16 @@ describe('Collection', function () {
|
||||
|
||||
const featuredPost = {
|
||||
id: '0',
|
||||
featured: true
|
||||
featured: true,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
};
|
||||
|
||||
const nonFeaturedPost = {
|
||||
id: '1',
|
||||
featured: false
|
||||
featured: false,
|
||||
published_at: new Date(),
|
||||
tags: []
|
||||
};
|
||||
|
||||
assert.ok(collection.postMatchesFilter(featuredPost), 'Post should match the filter');
|
||||
@ -373,15 +397,19 @@ describe('Collection', function () {
|
||||
|
||||
const avocadoPost = {
|
||||
id: '0',
|
||||
featured: false,
|
||||
tags: [{
|
||||
slug: 'avocado'
|
||||
}]
|
||||
}],
|
||||
published_at: new Date()
|
||||
};
|
||||
const nonAvocadoPost = {
|
||||
id: '1',
|
||||
featured: false,
|
||||
tags: [{
|
||||
slug: 'not-avocado'
|
||||
}]
|
||||
}],
|
||||
published_at: new Date()
|
||||
};
|
||||
|
||||
assert.ok(collection.postMatchesFilter(avocadoPost), 'Post should match the filter');
|
||||
@ -397,15 +425,19 @@ describe('Collection', function () {
|
||||
|
||||
const avocadoPost = {
|
||||
id: '0',
|
||||
featured: false,
|
||||
tags: [{
|
||||
slug: 'avocado'
|
||||
}]
|
||||
}],
|
||||
published_at: new Date()
|
||||
};
|
||||
const nonAvocadoPost = {
|
||||
id: '1',
|
||||
featured: false,
|
||||
tags: [{
|
||||
slug: 'not-avocado'
|
||||
}]
|
||||
}],
|
||||
published_at: new Date()
|
||||
};
|
||||
|
||||
assert.ok(collection.postMatchesFilter(avocadoPost), 'Post should match the filter');
|
||||
|
@ -8,9 +8,10 @@ import {
|
||||
PostEditedEvent
|
||||
} from '../src/index';
|
||||
import {PostsRepositoryInMemory} from './fixtures/PostsRepositoryInMemory';
|
||||
import {posts} from './fixtures/posts';
|
||||
import {posts as postFixtures} from './fixtures/posts';
|
||||
import {CollectionPost} from '../src/CollectionPost';
|
||||
|
||||
const initPostsRepository = (): PostsRepositoryInMemory => {
|
||||
const initPostsRepository = (posts: any): PostsRepositoryInMemory => {
|
||||
const postsRepository = new PostsRepositoryInMemory();
|
||||
|
||||
for (const post of posts) {
|
||||
@ -20,9 +21,10 @@ const initPostsRepository = (): PostsRepositoryInMemory => {
|
||||
slug: post.slug,
|
||||
featured: post.featured,
|
||||
published_at: post.published_at,
|
||||
tags: post.tags,
|
||||
deleted: false
|
||||
};
|
||||
postsRepository.save(collectionPost);
|
||||
postsRepository.save(collectionPost as CollectionPost & {deleted: false});
|
||||
}
|
||||
|
||||
return postsRepository;
|
||||
@ -34,7 +36,7 @@ describe('CollectionsService', function () {
|
||||
|
||||
beforeEach(async function () {
|
||||
const collectionsRepository = new CollectionsRepositoryInMemory();
|
||||
postsRepository = initPostsRepository();
|
||||
postsRepository = initPostsRepository(postFixtures);
|
||||
|
||||
collectionsService = new CollectionsService({
|
||||
collectionsRepository,
|
||||
@ -125,10 +127,10 @@ describe('CollectionsService', function () {
|
||||
type: 'manual'
|
||||
});
|
||||
|
||||
await collectionsService.addPostToCollection(collection.id, posts[0]);
|
||||
await collectionsService.addPostToCollection(collection2.id, posts[0]);
|
||||
await collectionsService.addPostToCollection(collection.id, postFixtures[0]);
|
||||
await collectionsService.addPostToCollection(collection2.id, postFixtures[0]);
|
||||
|
||||
const collections = await collectionsService.getCollectionsForPost(posts[0].id);
|
||||
const collections = await collectionsService.getCollectionsForPost(postFixtures[0].id);
|
||||
|
||||
assert.equal(collections.length, 2, 'There should be one collection');
|
||||
assert.equal(collections[0].id, collection2.id, 'Collections should be sorted by slug');
|
||||
@ -144,14 +146,14 @@ describe('CollectionsService', function () {
|
||||
type: 'manual'
|
||||
});
|
||||
|
||||
const editedCollection = await collectionsService.addPostToCollection(collection.id, posts[0]);
|
||||
const editedCollection = await collectionsService.addPostToCollection(collection.id, postFixtures[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');
|
||||
assert.equal(editedCollection?.posts[0].id, postFixtures[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]);
|
||||
const editedCollection = await collectionsService.addPostToCollection('fake id', postFixtures[0]);
|
||||
assert(editedCollection === null);
|
||||
});
|
||||
});
|
||||
@ -197,12 +199,12 @@ describe('CollectionsService', function () {
|
||||
const editedCollection = await collectionsService.edit({
|
||||
id: collection.id,
|
||||
posts: [{
|
||||
id: posts[0].id
|
||||
id: postFixtures[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].id, postFixtures[0].id, 'Collection should have the correct post');
|
||||
assert.equal(editedCollection?.posts[0].sort_order, 0, 'Collection should have the correct post sort order');
|
||||
});
|
||||
|
||||
@ -216,21 +218,21 @@ describe('CollectionsService', function () {
|
||||
let editedCollection = await collectionsService.edit({
|
||||
id: collection.id,
|
||||
posts: [{
|
||||
id: posts[0].id
|
||||
id: postFixtures[0].id
|
||||
}, {
|
||||
id: posts[1].id
|
||||
id: postFixtures[1].id
|
||||
}]
|
||||
});
|
||||
|
||||
assert.equal(editedCollection?.posts.length, 2, 'Collection should have two posts');
|
||||
|
||||
editedCollection = await collectionsService.removePostFromCollection(collection.id, posts[0].id);
|
||||
editedCollection = await collectionsService.removePostFromCollection(collection.id, postFixtures[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);
|
||||
const collection = await collectionsService.removePostFromCollection('i-do-not-exist', postFixtures[0].id);
|
||||
|
||||
assert.equal(collection, null, 'Collection should be null');
|
||||
});
|
||||
@ -266,11 +268,11 @@ describe('CollectionsService', function () {
|
||||
|
||||
let updatedCollection = await collectionsService.edit({
|
||||
id: collection.id,
|
||||
filter: 'slug:post-2'
|
||||
filter: 'id:post-3-featured'
|
||||
});
|
||||
|
||||
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');
|
||||
assert.equal(updatedCollection?.posts[0].id, 'post-3-featured', 'Collection should have the correct post');
|
||||
});
|
||||
|
||||
describe('updateCollections', function () {
|
||||
@ -299,8 +301,8 @@ describe('CollectionsService', function () {
|
||||
type: 'manual'
|
||||
});
|
||||
|
||||
await collectionsService.addPostToCollection(manualCollection.id, posts[0]);
|
||||
await collectionsService.addPostToCollection(manualCollection.id, posts[1]);
|
||||
await collectionsService.addPostToCollection(manualCollection.id, postFixtures[0]);
|
||||
await collectionsService.addPostToCollection(manualCollection.id, postFixtures[1]);
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
@ -316,7 +318,7 @@ describe('CollectionsService', function () {
|
||||
|
||||
collectionsService.subscribeToEvents();
|
||||
const postDeletedEvent = PostDeletedEvent.create({
|
||||
id: posts[0].id
|
||||
id: postFixtures[0].id
|
||||
});
|
||||
|
||||
DomainEvents.dispatch(postDeletedEvent);
|
||||
@ -348,12 +350,11 @@ describe('CollectionsService', function () {
|
||||
|
||||
it('Moves post form featured to non featured collection when the featured attribute is changed', async function () {
|
||||
collectionsService.subscribeToEvents();
|
||||
const newFeaturedPost = {
|
||||
const newFeaturedPost: CollectionPost & {deleted: false} = {
|
||||
id: 'post-featured',
|
||||
title: 'Post Featured',
|
||||
slug: 'post-featured',
|
||||
featured: false,
|
||||
published_at: new Date('2023-03-16T07:19:07.447Z'),
|
||||
tags: [],
|
||||
deleted: false
|
||||
};
|
||||
await postsRepository.save(newFeaturedPost);
|
||||
|
@ -1,26 +1,13 @@
|
||||
import {InMemoryRepository} from '@tryghost/in-memory-repository';
|
||||
import {CollectionPost} from '../../src/CollectionPost';
|
||||
|
||||
type CollectionPost = {
|
||||
id: string;
|
||||
slug: string;
|
||||
featured: boolean;
|
||||
published_at: Date;
|
||||
deleted: boolean;
|
||||
};
|
||||
|
||||
export class PostsRepositoryInMemory extends InMemoryRepository<string, CollectionPost> {
|
||||
export class PostsRepositoryInMemory extends InMemoryRepository<string, CollectionPost & {deleted: false}> {
|
||||
protected toPrimitive(entity: CollectionPost): object {
|
||||
return {
|
||||
id: entity.id,
|
||||
slug: entity.slug,
|
||||
featured: entity.featured,
|
||||
published_at: entity.published_at
|
||||
published_at: entity.published_at,
|
||||
tags: entity.tags.map(tag => tag.slug)
|
||||
};
|
||||
}
|
||||
|
||||
getBulk(ids: string[]): Promise<CollectionPost[]> {
|
||||
return this.getAll({
|
||||
filter: `id:[${ids.join(',')}]`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
4
ghost/collections/test/fixtures/posts.ts
vendored
4
ghost/collections/test/fixtures/posts.ts
vendored
@ -3,6 +3,7 @@ export const posts = [{
|
||||
url: 'http://localhost:2368/post-1/',
|
||||
title: 'Post 1',
|
||||
slug: 'post-1',
|
||||
tags: [],
|
||||
featured: false,
|
||||
created_at: new Date('2023-03-15T07:19:07.447Z'),
|
||||
updated_at: new Date('2023-03-15T07:19:07.447Z'),
|
||||
@ -12,6 +13,7 @@ export const posts = [{
|
||||
url: 'http://localhost:2368/post-2/',
|
||||
title: 'Post 2',
|
||||
slug: 'post-2',
|
||||
tags: [],
|
||||
featured: false,
|
||||
created_at: new Date('2023-04-05T07:20:07.447Z'),
|
||||
updated_at: new Date('2023-04-05T07:20:07.447Z'),
|
||||
@ -21,6 +23,7 @@ export const posts = [{
|
||||
url: 'http://localhost:2368/featured-post-3/',
|
||||
title: 'Featured Post 3',
|
||||
slug: 'featured-post-3',
|
||||
tags: [],
|
||||
featured: true,
|
||||
created_at: new Date('2023-05-25T07:21:07.447Z'),
|
||||
updated_at: new Date('2023-05-25T07:21:07.447Z'),
|
||||
@ -30,6 +33,7 @@ export const posts = [{
|
||||
url: 'http://localhost:2368/featured-post-4/',
|
||||
title: 'Featured Post 4',
|
||||
slug: 'featured-post-4',
|
||||
tags: [],
|
||||
featured: true,
|
||||
created_at: new Date('2023-05-15T07:21:07.447Z'),
|
||||
updated_at: new Date('2023-05-15T07:21:07.447Z'),
|
||||
|
Loading…
Reference in New Issue
Block a user