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:
Fabien "egg" O'Carroll 2023-07-27 14:03:14 +01:00 committed by Fabien 'egg' O'Carroll
parent 2e4a483518
commit 9288f56649
6 changed files with 83 additions and 60 deletions

View File

@ -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}>;
};

View File

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

View File

@ -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');

View File

@ -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);

View File

@ -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(',')}]`
});
}
}

View File

@ -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'),