mirror of
https://github.com/Cameri/nostream.git
synced 2025-04-08 20:08:07 +02:00
test: add unit test for factories
This commit is contained in:
parent
9cea3bec4e
commit
e50b4952b6
@ -1,6 +1,6 @@
|
||||
export enum EventKinds {
|
||||
SET_METADATA = 0,
|
||||
TEXT_NODE = 1,
|
||||
TEXT_NOTE = 1,
|
||||
RECOMMEND_SERVER = 2,
|
||||
CONTACT_LIST = 3,
|
||||
ENCRYPTED_DIRECT_MESSAGE = 4,
|
||||
@ -10,6 +10,8 @@ export enum EventKinds {
|
||||
REPLACEABLE_LAST = 19999,
|
||||
EPHEMERAL_FIRST = 20000,
|
||||
EPHEMERAL_LAST = 29999,
|
||||
PARAMETERIZED_REPLACEABLE_FIRST = 30000,
|
||||
PARAMETERIZED_REPLACEABLE_LAST = 39999,
|
||||
}
|
||||
|
||||
export enum EventTags {
|
||||
|
@ -31,6 +31,6 @@ export const messageHandlerFactory = (
|
||||
case MessageType.CLOSE:
|
||||
return new UnsubscribeMessageHandler(adapter,)
|
||||
default:
|
||||
throw new Error(`Unknown message type: ${String(message[0])}`)
|
||||
throw new Error(`Unknown message type: ${String(message[0]).substring(0, 64)}`)
|
||||
}
|
||||
}
|
||||
|
@ -222,11 +222,11 @@ export class EventRepository implements IEventRepository {
|
||||
.merge(omit(['event_pubkey', 'event_kind', 'event_deduplication'])(row))
|
||||
.where('events.event_created_at', '<', row.event_created_at)
|
||||
|
||||
const promise = query.then(prop('rowCount') as () => number)
|
||||
|
||||
promise.toString = () => query.toString()
|
||||
|
||||
return promise
|
||||
return {
|
||||
then: <T1, T2>(onfulfilled: (value: number) => T1 | PromiseLike<T1>, onrejected: (reason: any) => T2 | PromiseLike<T2>) => query.then(prop('rowCount') as () => number).then(onfulfilled, onrejected),
|
||||
catch: <T>(onrejected: (reason: any) => T | PromiseLike<T>) => query.catch(onrejected),
|
||||
toString: (): string => query.toString(),
|
||||
} as Promise<number>
|
||||
}
|
||||
|
||||
public deleteByPubkeyAndIds(pubkey: string, ids: EventId[]): Promise<number> {
|
||||
|
@ -167,15 +167,18 @@ export const isEventSignatureValid = async (event: Event): Promise<boolean> => {
|
||||
}
|
||||
|
||||
export const isReplaceableEvent = (event: Event): boolean => {
|
||||
return event.kind === 0 || event.kind === 3 || (event.kind >= 10000 && event.kind < 20000)
|
||||
return event.kind === EventKinds.SET_METADATA
|
||||
|| event.kind === EventKinds.CONTACT_LIST
|
||||
|| (event.kind >= EventKinds.REPLACEABLE_FIRST && event.kind <= EventKinds.REPLACEABLE_LAST)
|
||||
}
|
||||
|
||||
export const isEphemeralEvent = (event: Event): boolean => {
|
||||
return event.kind >= 20000 && event.kind < 30000
|
||||
return event.kind >= EventKinds.EPHEMERAL_FIRST && event.kind <= EventKinds.EPHEMERAL_LAST
|
||||
}
|
||||
|
||||
export const isParameterizedReplaceableEvent = (event: Event): boolean => {
|
||||
return event.kind >= 30000 && event.kind < 40000
|
||||
return event.kind >= EventKinds.PARAMETERIZED_REPLACEABLE_FIRST
|
||||
&& event.kind <= EventKinds.PARAMETERIZED_REPLACEABLE_LAST
|
||||
}
|
||||
|
||||
export const isDeleteEvent = (event: Event): boolean => {
|
||||
|
10
test/unit/factories/app-factory.spec.ts
Normal file
10
test/unit/factories/app-factory.spec.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
import { App } from '../../../src/app/app'
|
||||
import { appFactory } from '../../../src/factories/app-factory'
|
||||
|
||||
describe('appFactory', () => {
|
||||
it('returns an App', () => {
|
||||
expect(appFactory()).to.be.an.instanceOf(App)
|
||||
})
|
||||
})
|
46
test/unit/factories/delegated-event-strategy-factory.spec.ts
Normal file
46
test/unit/factories/delegated-event-strategy-factory.spec.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
import { DefaultEventStrategy } from '../../../src/handlers/event-strategies/default-event-strategy'
|
||||
import { delegatedEventStrategyFactory } from '../../../src/factories/delegated-event-strategy-factory'
|
||||
import { EphemeralEventStrategy } from '../../../src/handlers/event-strategies/ephemeral-event-strategy'
|
||||
import { Event } from '../../../src/@types/event'
|
||||
import { EventKinds } from '../../../src/constants/base'
|
||||
import { Factory } from '../../../src/@types/base'
|
||||
import { IEventRepository } from '../../../src/@types/repositories'
|
||||
import { IEventStrategy } from '../../../src/@types/message-handlers'
|
||||
import { IWebSocketAdapter } from '../../../src/@types/adapters'
|
||||
|
||||
describe('delegatedEventStrategyFactory', () => {
|
||||
let eventRepository: IEventRepository
|
||||
let event: Event
|
||||
let adapter: IWebSocketAdapter
|
||||
let factory: Factory<IEventStrategy<Event, Promise<void>>, [Event, IWebSocketAdapter]>
|
||||
|
||||
beforeEach(() => {
|
||||
eventRepository = {} as any
|
||||
event = {} as any
|
||||
adapter = {} as any
|
||||
|
||||
factory = delegatedEventStrategyFactory(eventRepository)
|
||||
})
|
||||
|
||||
it('returns EphemeralEventStrategy given a set_metadata event', () => {
|
||||
event.kind = EventKinds.EPHEMERAL_FIRST
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(EphemeralEventStrategy)
|
||||
})
|
||||
|
||||
it('returns DefaultEventStrategy given a text_note event', () => {
|
||||
event.kind = EventKinds.TEXT_NOTE
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(DefaultEventStrategy)
|
||||
})
|
||||
|
||||
it('returns undefined given a replaceable event', () => {
|
||||
event.kind = EventKinds.REPLACEABLE_FIRST
|
||||
expect(factory([event, adapter])).to.be.undefined
|
||||
})
|
||||
|
||||
it('returns undefined given a delete event', () => {
|
||||
event.kind = EventKinds.DELETE
|
||||
expect(factory([event, adapter])).to.be.undefined
|
||||
})
|
||||
})
|
64
test/unit/factories/event-strategy-factory.spec.ts
Normal file
64
test/unit/factories/event-strategy-factory.spec.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
import { DefaultEventStrategy } from '../../../src/handlers/event-strategies/default-event-strategy'
|
||||
import { DeleteEventStrategy } from '../../../src/handlers/event-strategies/delete-event-strategy'
|
||||
import { EphemeralEventStrategy } from '../../../src/handlers/event-strategies/ephemeral-event-strategy'
|
||||
import { Event } from '../../../src/@types/event'
|
||||
import { EventKinds } from '../../../src/constants/base'
|
||||
import { eventStrategyFactory } from '../../../src/factories/event-strategy-factory'
|
||||
import { Factory } from '../../../src/@types/base'
|
||||
import { IEventRepository } from '../../../src/@types/repositories'
|
||||
import { IEventStrategy } from '../../../src/@types/message-handlers'
|
||||
import { IWebSocketAdapter } from '../../../src/@types/adapters'
|
||||
import { ParameterizedReplaceableEventStrategy } from '../../../src/handlers/event-strategies/parameterized-replaceable-event-strategy'
|
||||
import { ReplaceableEventStrategy } from '../../../src/handlers/event-strategies/replaceable-event-strategy'
|
||||
|
||||
describe('eventStrategyFactory', () => {
|
||||
let eventRepository: IEventRepository
|
||||
let event: Event
|
||||
let adapter: IWebSocketAdapter
|
||||
let factory: Factory<IEventStrategy<Event, Promise<void>>, [Event, IWebSocketAdapter]>
|
||||
|
||||
beforeEach(() => {
|
||||
eventRepository = {} as any
|
||||
event = {} as any
|
||||
adapter = {} as any
|
||||
|
||||
factory = eventStrategyFactory(eventRepository)
|
||||
})
|
||||
|
||||
it('returns ReplaceableEvent given a set_metadata event', () => {
|
||||
event.kind = EventKinds.SET_METADATA
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(ReplaceableEventStrategy)
|
||||
})
|
||||
|
||||
it('returns ReplaceableEvent given a contact_list event', () => {
|
||||
event.kind = EventKinds.CONTACT_LIST
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(ReplaceableEventStrategy)
|
||||
})
|
||||
|
||||
it('returns ReplaceableEvent given a replaceable event', () => {
|
||||
event.kind = EventKinds.REPLACEABLE_FIRST
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(ReplaceableEventStrategy)
|
||||
})
|
||||
|
||||
it('returns EphemeralEventStrategy given an ephemeral event', () => {
|
||||
event.kind = EventKinds.EPHEMERAL_FIRST
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(EphemeralEventStrategy)
|
||||
})
|
||||
|
||||
it('returns DeleteEventStrategy given a delete event', () => {
|
||||
event.kind = EventKinds.DELETE
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(DeleteEventStrategy)
|
||||
})
|
||||
|
||||
it('returns ParameterizedReplaceableEventStrategy given a delete event', () => {
|
||||
event.kind = EventKinds.PARAMETERIZED_REPLACEABLE_FIRST
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(ParameterizedReplaceableEventStrategy)
|
||||
})
|
||||
|
||||
it('returns DefaultEventStrategy given a text_note event', () => {
|
||||
event.kind = EventKinds.TEXT_NOTE
|
||||
expect(factory([event, adapter])).to.be.an.instanceOf(DefaultEventStrategy)
|
||||
})
|
||||
})
|
77
test/unit/factories/message-handler-factory.spec.ts
Normal file
77
test/unit/factories/message-handler-factory.spec.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
import { IncomingMessage, MessageType } from '../../../src/@types/messages'
|
||||
import { DelegatedEventMessageHandler } from '../../../src/handlers/delegated-event-message-handler'
|
||||
import { Event } from '../../../src/@types/event'
|
||||
import { EventMessageHandler } from '../../../src/handlers/event-message-handler'
|
||||
import { EventTags } from '../../../src/constants/base'
|
||||
import { IEventRepository } from '../../../src/@types/repositories'
|
||||
import { IWebSocketAdapter } from '../../../src/@types/adapters'
|
||||
import { messageHandlerFactory } from '../../../src/factories/message-handler-factory'
|
||||
import { SubscribeMessageHandler } from '../../../src/handlers/subscribe-message-handler'
|
||||
import { UnsubscribeMessageHandler } from '../../../src/handlers/unsubscribe-message-handler'
|
||||
|
||||
describe('messageHandlerFactory', () => {
|
||||
let event: Event
|
||||
let eventRepository: IEventRepository
|
||||
let message: IncomingMessage
|
||||
let adapter: IWebSocketAdapter
|
||||
let factory
|
||||
|
||||
beforeEach(() => {
|
||||
eventRepository = {} as any
|
||||
adapter = {} as any
|
||||
event = {
|
||||
tags: [],
|
||||
} as any
|
||||
factory = messageHandlerFactory(eventRepository)
|
||||
})
|
||||
|
||||
it('returns EventMessageHandler when given an EVENT message', () => {
|
||||
message = [
|
||||
MessageType.EVENT,
|
||||
event,
|
||||
]
|
||||
|
||||
expect(factory([message, adapter])).to.be.an.instanceOf(EventMessageHandler)
|
||||
})
|
||||
|
||||
it('returns DelegatedEventMessageHandler when given an EVENT message with delegated event', () => {
|
||||
event.tags = [
|
||||
[EventTags.Delegation, '', '', ''],
|
||||
]
|
||||
message = [
|
||||
MessageType.EVENT,
|
||||
event,
|
||||
]
|
||||
|
||||
expect(factory([message, adapter])).to.be.an.instanceOf(DelegatedEventMessageHandler)
|
||||
})
|
||||
|
||||
it('returns SubscribeMessageHandler when given a REQ message', () => {
|
||||
message = [
|
||||
MessageType.REQ,
|
||||
'',
|
||||
{},
|
||||
] as any
|
||||
|
||||
expect(factory([message, adapter])).to.be.an.instanceOf(SubscribeMessageHandler)
|
||||
})
|
||||
|
||||
it('returns UnsubscribeMessageHandler when given a REQ message', () => {
|
||||
message = [
|
||||
MessageType.CLOSE,
|
||||
'',
|
||||
]
|
||||
|
||||
expect(factory([message, adapter])).to.be.an.instanceOf(UnsubscribeMessageHandler)
|
||||
})
|
||||
|
||||
it('throws when given an invalid message', () => {
|
||||
message = []
|
||||
|
||||
expect(() => factory([message, adapter])).to.throw(Error, 'Unknown message type: undefined')
|
||||
})
|
||||
|
||||
|
||||
})
|
40
test/unit/factories/websocket-adapter-factory.spec.ts
Normal file
40
test/unit/factories/websocket-adapter-factory.spec.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { expect } from 'chai'
|
||||
import { IncomingMessage } from 'http'
|
||||
import Sinon from 'sinon'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
import { IEventRepository } from '../../../src/@types/repositories'
|
||||
import { IWebSocketServerAdapter } from '../../../src/@types/adapters'
|
||||
import { WebSocketAdapter } from '../../../src/adapters/web-socket-adapter'
|
||||
import { webSocketAdapterFactory } from '../../../src/factories/websocket-adapter-factory'
|
||||
|
||||
describe('webSocketAdapterFactory', () => {
|
||||
let onStub: Sinon.SinonStub
|
||||
|
||||
beforeEach(() => {
|
||||
onStub = Sinon.stub()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
onStub.reset()
|
||||
})
|
||||
|
||||
it('returns a WebSocketAdapter', () => {
|
||||
const eventRepository: IEventRepository = {} as any
|
||||
|
||||
const client: WebSocket = {
|
||||
on: onStub,
|
||||
} as any
|
||||
onStub.returns(client)
|
||||
const request: IncomingMessage = {
|
||||
headers: {
|
||||
'sec-websocket-key': Buffer.from('key', 'utf-8').toString('base64'),
|
||||
},
|
||||
} as any
|
||||
const webSocketServerAdapter: IWebSocketServerAdapter = {} as any
|
||||
|
||||
expect(
|
||||
webSocketAdapterFactory(eventRepository)([client, request, webSocketServerAdapter])
|
||||
).to.be.an.instanceOf(WebSocketAdapter)
|
||||
})
|
||||
})
|
25
test/unit/factories/worker-factory.spec.ts
Normal file
25
test/unit/factories/worker-factory.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { expect } from 'chai'
|
||||
import Sinon from 'sinon'
|
||||
|
||||
import * as databaseClientModule from '../../../src/database/client'
|
||||
|
||||
import { AppWorker } from '../../../src/app/worker'
|
||||
import { workerFactory } from '../../../src/factories/worker-factory'
|
||||
|
||||
describe('workerFactory', () => {
|
||||
let getDbClientStub: Sinon.SinonStub
|
||||
|
||||
beforeEach(() => {
|
||||
getDbClientStub = Sinon.stub(databaseClientModule, 'getDbClient')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
getDbClientStub.restore()
|
||||
})
|
||||
|
||||
it('returns an AppWorker', () => {
|
||||
const worker = workerFactory()
|
||||
expect(worker).to.be.an.instanceOf(AppWorker)
|
||||
worker.close()
|
||||
})
|
||||
})
|
@ -21,7 +21,7 @@ describe('NIP-01', () => {
|
||||
const event: Partial<Event> = {
|
||||
pubkey: 'pubkey',
|
||||
created_at: 1000,
|
||||
kind: EventKinds.TEXT_NODE,
|
||||
kind: EventKinds.TEXT_NOTE,
|
||||
tags: [['tag name', 'tag content']],
|
||||
content: 'content',
|
||||
}
|
||||
@ -30,7 +30,7 @@ describe('NIP-01', () => {
|
||||
0,
|
||||
'pubkey',
|
||||
1000,
|
||||
EventKinds.TEXT_NODE,
|
||||
EventKinds.TEXT_NOTE,
|
||||
[['tag name', 'tag content']],
|
||||
'content',
|
||||
]
|
||||
|
Loading…
x
Reference in New Issue
Block a user