From 3c35c26df257a0c7878941b17e9fdd8f3a11d367 Mon Sep 17 00:00:00 2001 From: Mohammad Ataei Date: Mon, 17 Oct 2022 20:13:47 +0330 Subject: [PATCH] feat: add findFirstOrThrow --- src/DocumentCollection.ts | 14 ++++++++-- src/Store.ts | 9 ++++-- src/types.ts | 2 ++ tests/findFirstOrThrow.test.ts | 51 ++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 tests/findFirstOrThrow.test.ts diff --git a/src/DocumentCollection.ts b/src/DocumentCollection.ts index f0afaa8..bbffd62 100644 --- a/src/DocumentCollection.ts +++ b/src/DocumentCollection.ts @@ -1,4 +1,4 @@ -import { Document } from './types' +import { Document, PredicateFunction } from './types' import { DOCUMENT_KEY } from './constants' export class DocumentCollection { @@ -13,7 +13,17 @@ export class DocumentCollection { return document } - find(): DocumentType | undefined { + findFirst( + predicate?: PredicateFunction, + ): DocumentType | undefined { + if (predicate) { + for (const document of this.documents.values()) { + if (predicate(document)) { + return document + } + } + } + return this.documents.values().next().value } } diff --git a/src/Store.ts b/src/Store.ts index 547528c..09c2b7f 100644 --- a/src/Store.ts +++ b/src/Store.ts @@ -1,5 +1,5 @@ import { GraphQLSchema } from 'graphql' -import { Schema } from './types' +import { PredicateFunction, Schema } from './types' import { CollectionStorage } from './CollectionStorage' import { resolveGraphQLSchema } from './resolveGraphQLSchema' import { createDocument } from './createDocument' @@ -25,8 +25,11 @@ export class Store> { return this.collections.get(type).create(document) } - findFirstOrThrow(type: Type): TypesMap[Type] { - const document = this.collections.get(type).find() + findFirstOrThrow( + type: Type, + predicate?: PredicateFunction, + ): TypesMap[Type] { + const document = this.collections.get(type).findFirst(predicate) if (!document) { throw new Error('Document not found.') diff --git a/src/types.ts b/src/types.ts index aa69bec..44a0c35 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,3 +7,5 @@ export type Document = DocumentType & { [DOCUMENT_KEY]: string [DOCUMENT_TYPE]: string } + +export type PredicateFunction = (data: T) => boolean diff --git a/tests/findFirstOrThrow.test.ts b/tests/findFirstOrThrow.test.ts new file mode 100644 index 0000000..3317a69 --- /dev/null +++ b/tests/findFirstOrThrow.test.ts @@ -0,0 +1,51 @@ +import { Store } from '../src' +import { schema, TypesMap } from './fixtures' +import { postFactory, userFactory } from './utils/factories' + +const store = new Store({ + schema, +}) + +afterEach(() => store.reset()) + +it('should return the first document', () => { + const user = store.create('User', userFactory()) + store.create('User', userFactory()) + store.create('User', userFactory()) + + expect(store.findFirstOrThrow('User')).toEqual(user) + + const post = store.create('Post', postFactory()) + store.create('Post', postFactory()) + store.create('Post', postFactory()) + + expect(store.findFirstOrThrow('Post')).toEqual(post) +}) + +it('should throw error if first user is undefined', () => { + expect(() => { + store.findFirstOrThrow('User') + }).toThrowError('Document not found.') + + expect(() => { + store.findFirstOrThrow('Post') + }).toThrowError('Document not found.') +}) + +it('can find specific document with a predicate function', () => { + store.create('User', userFactory()) + store.create('User', userFactory()) + const user = store.create('User', userFactory({ username: 'john.doe' })) + + expect( + store.findFirstOrThrow('User', (user) => user.username === 'john.doe'), + ).toEqual(user) + + store.create('Post', postFactory()) + store.create('Post', postFactory()) + const post = store.create('Post', postFactory({ title: 'Hello World!' })) + + expect( + store.findFirstOrThrow('Post', (post) => post.title === 'Hello World!'), + ).toEqual(post) +})