|
1 | | -import { CourseCreator } from '../../../../../src/Contexts/Mooc/Courses/application/CourseCreator'; |
2 | 1 | import { CourseMother } from '../domain/CourseMother'; |
3 | 2 | import { CreateCourseRequestMother } from './CreateCourseRequestMother'; |
| 3 | +import { CourseCreatedDomainEventMother } from '../domain/CourseCreatedDomainEventMother'; |
4 | 4 | import { CourseRepository } from '../../../../../src/Contexts/Mooc/Courses/domain/CourseRepository'; |
5 | | -import { Course } from '../../../../../src/Contexts/Mooc/Courses/domain/Course'; |
6 | 5 | import { EventBus } from '../../../../../src/Contexts/Shared/domain/EventBus'; |
| 6 | +import { CourseCreator } from '../../../../../src/Contexts/Mooc/Courses/application/CourseCreator'; |
| 7 | +import { Course } from '../../../../../src/Contexts/Mooc/Courses/domain/Course'; |
| 8 | +import { CourseCreatedDomainEvent } from '../../../../../src/Contexts/Mooc/Courses/domain/CourseCreatedDomainEvent'; |
| 9 | +import { AssertionError } from 'assert'; |
| 10 | +import { DomainEvent } from '../../../../../src/Contexts/Shared/domain/DomainEvent'; |
| 11 | +import { Domain } from 'domain'; |
7 | 12 |
|
8 | 13 | let repository: CourseRepository; |
| 14 | +let bus: EventBus; |
9 | 15 | let creator: CourseCreator; |
| 16 | +declare global { |
| 17 | + namespace jest { |
| 18 | + interface Matchers<R> { |
| 19 | + toPublish(a: DomainEvent, b: DomainEvent): R; |
| 20 | + } |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +expect.extend({ |
| 25 | + toPublish(receivedEvent, expectedEvent) { |
| 26 | + const comparator = new DomainEventComparator() |
| 27 | + const pass = comparator.isSimilar(receivedEvent, expectedEvent); |
| 28 | + if (pass) { |
| 29 | + return { |
| 30 | + message: () => |
| 31 | + `todo bien`, |
| 32 | + pass: true, |
| 33 | + }; |
| 34 | + } else { |
| 35 | + return { |
| 36 | + message: () => |
| 37 | + `expected ${receivedEvent} to be within range ${expectedEvent}`, |
| 38 | + pass: false, |
| 39 | + }; |
| 40 | + } |
| 41 | + }, |
| 42 | +}); |
10 | 43 |
|
11 | 44 | const createRepository = (): CourseRepository => ({ save: jest.fn(), search: jest.fn() }); |
12 | | -const eventBus = (): EventBus => ({ publish: jest.fn()}); |
| 45 | +const eventBus = (): EventBusMock => (new EventBusMock()); |
13 | 46 | const shouldSave = (course: Course) => expect(repository.save).toHaveBeenCalledWith(course); |
| 47 | +const shouldPublishDomainEvent = (event: CourseCreatedDomainEvent) => expect((bus.publish as jest.Mock); |
14 | 48 |
|
15 | 49 | beforeEach(() => { |
16 | 50 | repository = createRepository(); |
17 | | - creator = new CourseCreator(repository, eventBus()); |
| 51 | + bus = eventBus(); |
| 52 | + creator = new CourseCreator(repository, bus); |
18 | 53 | }); |
19 | 54 |
|
20 | | -it('should create a valid course', async () => { |
21 | | - const request = CreateCourseRequestMother.random(); |
| 55 | +describe('Course Creator', () => { |
| 56 | + it('should create a valid course', async () => { |
| 57 | + const request = CreateCourseRequestMother.random(); |
22 | 58 |
|
23 | | - const course = CourseMother.fromRequest(request); |
| 59 | + const course = CourseMother.fromRequest(request); |
| 60 | + const event = CourseCreatedDomainEventMother.fromCourse(course); |
24 | 61 |
|
25 | | - await creator.run(request); |
| 62 | + await creator.run(request); |
26 | 63 |
|
27 | | - shouldSave(course); |
| 64 | + //shouldSave(course); |
| 65 | + shouldPublishDomainEvent(event); |
| 66 | + }); |
28 | 67 | }); |
| 68 | +class EventBusMock implements EventBus { |
| 69 | + private spy = jest.fn(); |
| 70 | + publish(events: DomainEvent[]): void { |
| 71 | + this.spy(events); |
| 72 | + } |
| 73 | + |
| 74 | + toHaveBeenCalledWith(event: DomainEvent) { |
| 75 | + this.spy.toPublish(event); |
| 76 | + const eventArg: DomainEvent[] = this.spy.mock.calls[0][0]; |
| 77 | + return this.isSimilarTo(event, eventArg[0]); |
| 78 | + } |
| 79 | + |
| 80 | + private isSimilarTo(event1: DomainEvent, event2: DomainEvent) { |
| 81 | + const event1Data = this.getDomainAttributes(event1); |
| 82 | + const event2Data = this.getDomainAttributes(event2); |
| 83 | + |
| 84 | + return expect(event1Data).toMatchObject(event2Data); |
| 85 | + } |
| 86 | + |
| 87 | + private getDomainAttributes(event: DomainEvent) { |
| 88 | + const { eventId, occurredOn, ...data } = event; |
| 89 | + |
| 90 | + return data; |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +class Mock { |
| 95 | + toHaveBeenCalledWith(event: DomainEvent) { |
| 96 | + const eventArg: DomainEvent[] = this.spy.mock.calls[0][0]; |
| 97 | + return this.isSimilarTo(event, eventArg[0]); |
| 98 | + } |
| 99 | + |
| 100 | + private isSimilarTo(event1: DomainEvent, event2: DomainEvent) { |
| 101 | + const event1Data = this.getDomainAttributes(event1); |
| 102 | + const event2Data = this.getDomainAttributes(event2); |
| 103 | + |
| 104 | + return expect(event1Data).toMatchObject(event2Data); |
| 105 | + } |
| 106 | + |
| 107 | + private getDomainAttributes(event: DomainEvent) { |
| 108 | + const { eventId, occurredOn, ...data } = event; |
| 109 | + |
| 110 | + return data; |
| 111 | + } |
| 112 | +} |
| 113 | + |
| 114 | +interface Comparator<T> { |
| 115 | + isSimilar(t1: T, t2: T): void; |
| 116 | +} |
| 117 | + |
| 118 | +class DomainEventComparator implements Comparator<DomainEvent> { |
| 119 | + isSimilar(event1: DomainEvent, event2: DomainEvent) { |
| 120 | + const event1Data = this.getDomainAttributes(event1); |
| 121 | + const event2Data = this.getDomainAttributes(event2); |
| 122 | + |
| 123 | + return expect(event1Data).toMatchObject(event2Data); |
| 124 | + } |
| 125 | + |
| 126 | + private getDomainAttributes(event: DomainEvent) { |
| 127 | + const { eventId, occurredOn, ...data } = event; |
| 128 | + |
| 129 | + return data; |
| 130 | + } |
| 131 | +} |
| 132 | +class DefaultComparator implements Comparator<any> { |
| 133 | + isSimilar(event1: any, event2: any) { |
| 134 | + return expect(event1).toMatchObject(event1); |
| 135 | + } |
| 136 | + |
| 137 | +} |
| 138 | +class ComparatorFactory { |
| 139 | + static comparators = new Map<string, Comparator<any>>(); |
| 140 | + |
| 141 | + static getComparatorFor(object: Object): Comparator<any> { |
| 142 | + const name: any = object.constructor.name; |
| 143 | + |
| 144 | + if (ComparatorFactory.comparators.has(name)) { |
| 145 | + return ComparatorFactory.comparators.get(name)!; |
| 146 | + } |
| 147 | + |
| 148 | + return new DefaultComparator(); |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +// function areSimilar(obj1: Object, obj2: Object, excludingFields: Array<string>) { |
| 153 | +// const obj1WithoutExcludingFields = {}; |
| 154 | +// const obj2WithoutExcludingFields = {}; |
| 155 | + |
| 156 | +// return expect(obj1WithoutExcludingFields).toMatchObject(obj2WithoutExcludingFields); |
| 157 | +// } |
| 158 | + |
| 159 | +// function pickProperties(obj: Object, excludingFields: Array<string>) { |
| 160 | +// return obj.keys.reduce(function(keyName, value) { |
| 161 | +// if (excludingFields.includes(keyName)) { |
| 162 | +// } |
| 163 | +// }, {}); |
| 164 | +// } |
0 commit comments