Skip to content

Commit b545564

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

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

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

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1+
import { withTransaction } from '../../../shared/domain/DomainTransaction.js';
12
import { NotFoundError } from '../../../shared/domain/errors.js';
23
import { ModuleDoesNotExistError } from '../errors.js';
4+
import { PassageStartedEvent } from '../models/passage-events/passage-events.js';
35

4-
const createPassage = async function ({ moduleId, userId, moduleRepository, passageRepository, userRepository }) {
5-
await _getModule({ moduleId, moduleRepository });
6+
const createPassage = withTransaction(async function ({
7+
moduleId,
8+
occurredAt,
9+
userId,
10+
moduleRepository,
11+
passageRepository,
12+
passageEventRepository,
13+
userRepository,
14+
}) {
15+
const module = await _getModule({ moduleId, moduleRepository });
616
if (userId !== null) {
717
await userRepository.get(userId);
818
}
9-
return passageRepository.save({ moduleId, userId });
10-
};
19+
20+
const passage = await passageRepository.save({ moduleId, userId });
21+
await _recordPassageEvent({ module, occurredAt, passage, passageEventRepository });
22+
23+
return passage;
24+
});
1125

1226
async function _getModule({ moduleId, moduleRepository }) {
1327
try {
@@ -20,4 +34,12 @@ async function _getModule({ moduleId, moduleRepository }) {
2034
}
2135
}
2236

37+
async function _recordPassageEvent({ module, occurredAt, passage, passageEventRepository }) {
38+
const { id: passageId } = passage;
39+
const contentHash = module.version;
40+
const passageStartedEvent = new PassageStartedEvent({ contentHash, passageId, occurredAt });
41+
42+
await passageEventRepository.record(passageStartedEvent);
43+
}
44+
2345
export { createPassage };

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

+44-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
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';
6+
import { DomainTransaction } from '../../../../../src/shared/domain/DomainTransaction.js';
37
import { UserNotFoundError } from '../../../../../src/shared/domain/errors.js';
48
import { NotFoundError } from '../../../../../src/shared/domain/errors.js';
59
import { catchErr, expect, sinon } from '../../../../test-helper.js';
610

711
describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
12+
beforeEach(function () {
13+
sinon.stub(DomainTransaction, 'execute').callsFake((lambda) => lambda());
14+
});
15+
816
describe('when module does not exist', function () {
917
it('should throw a ModuleDoesNotExist error', async function () {
1018
// given
@@ -48,11 +56,35 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
4856
});
4957
});
5058

51-
it('should call passage repository to save the passage', async function () {
59+
it('should save the passage and record passage started event', async function () {
5260
// given
5361
const moduleId = Symbol('moduleId');
62+
const passageId = Symbol('passageId');
5463
const userId = Symbol('userId');
55-
const repositoryResult = Symbol('repository-result');
64+
65+
const slug = 'les-adresses-email';
66+
const title = 'Les adresses email';
67+
const isBeta = false;
68+
const grains = [Symbol('text')];
69+
const transitionTexts = [];
70+
const details = Symbol('details');
71+
const version = Symbol('version');
72+
const module = new Module({ id: moduleId, slug, title, isBeta, grains, details, transitionTexts, version });
73+
74+
const occurredAt = new Date('2025-01-01');
75+
const passageCreatedAt = new Date('2025-03-05');
76+
const passage = new Passage({
77+
id: passageId,
78+
moduleId,
79+
userId,
80+
createdAt: passageCreatedAt,
81+
});
82+
83+
const passageStartedEvent = new PassageStartedEvent({
84+
contentHash: version,
85+
occurredAt,
86+
passageId,
87+
});
5688

5789
const userRepositoryStub = {
5890
get: sinon.stub(),
@@ -61,17 +93,23 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
6193
const moduleRepositoryStub = {
6294
getBySlug: sinon.stub(),
6395
};
64-
moduleRepositoryStub.getBySlug.withArgs({ slug: moduleId }).resolves();
96+
moduleRepositoryStub.getBySlug.withArgs({ slug: moduleId }).resolves(module);
6597
const passageRepositoryStub = {
6698
save: sinon.stub(),
6799
};
68-
passageRepositoryStub.save.resolves(repositoryResult);
100+
passageRepositoryStub.save.resolves(passage);
101+
102+
const passageEventRepositoryStub = {
103+
record: sinon.stub(),
104+
};
69105

70106
// when
71107
const result = await createPassage({
108+
occurredAt,
72109
moduleId,
73110
userId,
74111
passageRepository: passageRepositoryStub,
112+
passageEventRepository: passageEventRepositoryStub,
75113
moduleRepository: moduleRepositoryStub,
76114
userRepository: userRepositoryStub,
77115
});
@@ -81,6 +119,7 @@ describe('Unit | Devcomp | Domain | UseCases | create-passage', function () {
81119
moduleId,
82120
userId,
83121
});
84-
expect(result).to.equal(repositoryResult);
122+
expect(passageEventRepositoryStub.record).to.have.been.calledOnceWith(passageStartedEvent);
123+
expect(result).to.equal(passage);
85124
});
86125
});

0 commit comments

Comments
 (0)