Skip to content

Commit 18bd956

Browse files
committed
feat(api): record passage started event
by using module content as content hash
1 parent d4e5589 commit 18bd956

File tree

2 files changed

+65
-8
lines changed

2 files changed

+65
-8
lines changed

api/src/devcomp/domain/usecases/create-passage.js

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
import { NotFoundError } from '../../../shared/domain/errors.js';
22
import { ModuleDoesNotExistError } from '../errors.js';
3+
import { PassageStartedEvent } from '../models/passage-events/passage-events.js';
34

4-
const createPassage = async function ({ moduleId, userId, moduleRepository, passageRepository, userRepository }) {
5-
await _getModule({ moduleId, moduleRepository });
5+
const createPassage = async function ({
6+
moduleId,
7+
userId,
8+
moduleRepository,
9+
passageRepository,
10+
passageEventRepository,
11+
userRepository,
12+
}) {
13+
const module = await _getModule({ moduleId, moduleRepository });
614
if (userId !== null) {
715
await userRepository.get(userId);
816
}
9-
return passageRepository.save({ moduleId, userId });
17+
18+
const passage = await passageRepository.save({ moduleId, userId });
19+
await _recordPassageEvent({ module, passage, passageEventRepository });
20+
21+
return passage;
1022
};
1123

1224
async function _getModule({ moduleId, moduleRepository }) {
@@ -20,4 +32,12 @@ async function _getModule({ moduleId, moduleRepository }) {
2032
}
2133
}
2234

35+
async function _recordPassageEvent({ module, passage, passageEventRepository }) {
36+
const { id: passageId, createdAt: occurredAt } = passage;
37+
const contentHash = module.hash();
38+
const passageStartedEvent = new PassageStartedEvent({ contentHash, passageId, occurredAt });
39+
40+
await passageEventRepository.record(passageStartedEvent);
41+
}
42+
2343
export { createPassage };

api/tests/devcomp/unit/domain/usecases/create-passage_test.js

+42-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { ModuleDoesNotExistError } from '../../../../../src/devcomp/domain/errors.js';
2+
import { Module } from '../../../../../src/devcomp/domain/models/module/Module.js';
3+
import { Passage } from '../../../../../src/devcomp/domain/models/Passage.js';
4+
import { PassageStartedEvent } from '../../../../../src/devcomp/domain/models/passage-events/passage-events.js';
25
import { createPassage } from '../../../../../src/devcomp/domain/usecases/create-passage.js';
36
import { UserNotFoundError } from '../../../../../src/shared/domain/errors.js';
47
import { NotFoundError } from '../../../../../src/shared/domain/errors.js';
@@ -48,11 +51,38 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
4851
});
4952
});
5053

51-
it('should call passage repository to save the passage', async function () {
54+
it('should save the passage and record passage started event', async function () {
5255
// given
5356
const moduleId = Symbol('moduleId');
57+
const passageId = Symbol('passageId');
5458
const userId = Symbol('userId');
55-
const repositoryResult = Symbol('repository-result');
59+
60+
const slug = 'les-adresses-email';
61+
const title = 'Les adresses email';
62+
const isBeta = false;
63+
const grains = [Symbol('text')];
64+
const transitionTexts = [];
65+
const details = Symbol('details');
66+
const hash = 'AZERTY123456';
67+
let module = new Module({ id: moduleId, slug, title, isBeta, grains, details, transitionTexts });
68+
module = {
69+
...module,
70+
hash: sinon.stub().returns(hash),
71+
};
72+
73+
const passageCreatedAt = new Date('2025-03-05');
74+
const passage = new Passage({
75+
id: passageId,
76+
moduleId,
77+
userId,
78+
createdAt: passageCreatedAt,
79+
});
80+
81+
const passageStartedEvent = new PassageStartedEvent({
82+
contentHash: hash,
83+
occurredAt: passageCreatedAt,
84+
passageId,
85+
});
5686

5787
const userRepositoryStub = {
5888
get: sinon.stub(),
@@ -61,17 +91,22 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
6191
const moduleRepositoryStub = {
6292
getBySlug: sinon.stub(),
6393
};
64-
moduleRepositoryStub.getBySlug.withArgs({ slug: moduleId }).resolves();
94+
moduleRepositoryStub.getBySlug.withArgs({ slug: moduleId }).resolves(module);
6595
const passageRepositoryStub = {
6696
save: sinon.stub(),
6797
};
68-
passageRepositoryStub.save.resolves(repositoryResult);
98+
passageRepositoryStub.save.resolves(passage);
99+
100+
const passageEventRepositoryStub = {
101+
record: sinon.stub(),
102+
};
69103

70104
// when
71105
const result = await createPassage({
72106
moduleId,
73107
userId,
74108
passageRepository: passageRepositoryStub,
109+
passageEventRepository: passageEventRepositoryStub,
75110
moduleRepository: moduleRepositoryStub,
76111
userRepository: userRepositoryStub,
77112
});
@@ -81,6 +116,8 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
81116
moduleId,
82117
userId,
83118
});
84-
expect(result).to.equal(repositoryResult);
119+
expect(module.hash).to.have.been.calledOnce;
120+
expect(passageEventRepositoryStub.record).to.have.been.calledOnceWith(passageStartedEvent);
121+
expect(result).to.equal(passage);
85122
});
86123
});

0 commit comments

Comments
 (0)