Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions lib/database/repositories/LogRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* or submit itself to any jurisdiction.
*/

const { models: { Log }, sequelize, utilities: { QueryBuilder } } = require('../');
const { models: { Log }, sequelize } = require('../');
const Repository = require('./Repository');
const { timestampToMysql } = require('../../server/utilities/timestampToMysql.js');

Expand Down Expand Up @@ -93,23 +93,6 @@ class LogRepository extends Repository {
return rows;
}

/**
* Returns all entities.
*
* @param {Object} runId The QueryBuilder to use.
* @param {QueryBuilder} queryBuilder The QueryBuilder to use.
* @returns {Promise} Promise object representing the full mock data
*/
async findAllByRunId(runId, queryBuilder = new QueryBuilder()) {
queryBuilder
.setModel(Log)
.include('user')
.include('tags')
.whereAssociation('runs', 'id').is(runId);

return this.findAll(queryBuilder);
}

/**
* Returns the list of tags and their occurrences in the logs created in the given period
*
Expand Down
26 changes: 23 additions & 3 deletions lib/server/services/log/LogService.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
const { createLog } = require('./createLog.js');
const { getLog } = require('./getLog.js');
const { logAdapter, attachmentAdapter, tagAdapter } = require('../../../database/adapters/index.js');
const { repositories: { LogRepository, LogLhcFillsRepository } } = require('../../../database');
const { repositories: { LogRepository, LogLhcFillsRepository, LogRunsRepository } } = require('../../../database');
const { dataSource } = require('../../../database/DataSource.js');
const { LogEnvironmentsRepository } = require('../../../database/repositories/index.js');
const { getLogsByTagsInPeriod } = require('./getLogsByTagsInPeriod.js');
Expand Down Expand Up @@ -119,7 +119,26 @@ class LogService {
}

/**
* Returns all the logs related to a given LHC fill
* Returns all the logs related to a given run, with all their relations (and not only the given run)
*
* @param {number} runId the id of the run for which logs must be returned
* @return {Promise<Log[]>} the resulting logs
*/
async getAllByRun(runId) {
const logRunQueryBuilder = dataSource.createQueryBuilder()
.include({
association: 'run',
where: { id: runId },
});

const logRuns = await LogRunsRepository.findAll(logRunQueryBuilder);

const logIds = logRuns.map((logRun) => logRun.logId);
return this._getAllByIds(logIds);
}

/**
* Returns all the logs related to a given environment
*
* @param {string} environmentId the id of the environment for which logs must be returned
* @return {Promise<Log[]>} the resulting logs
Expand Down Expand Up @@ -189,7 +208,8 @@ class LogService {
.include({ association: 'dataPasses', attributes: ['id', 'name'] })
.include({ association: 'environments', attributes: ['id'] })
.include({ association: 'user', attributes: ['name'] })
.include({ association: 'tags', attributes: ['text'] });
.include('tags')
.include('attachments');
}

/**
Expand Down
16 changes: 4 additions & 12 deletions lib/usecases/run/GetLogsByRunUseCase.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@

const {
repositories: {
LogRepository,
RunRepository,
},
utilities: {
QueryBuilder,
TransactionHelper,
},
} = require('../../database');
const { logAdapter } = require('../../database/adapters/index.js');
const { logService } = require('../../server/services/log/LogService.js');

/**
* GetLogsByRunUseCase
Expand All @@ -31,25 +30,18 @@ class GetLogsByRunUseCase {
* Executes this use case.
*
* @param {Object} dto The GetRunDto containing all data.
* @returns {Promise} Promise object represents the result of this use case.
* @returns {Promise<Log[]|null>} Promise object represents the logs of the run, or null if the run does not exist.
*/
async execute(dto) {
const queryBuilder = new QueryBuilder();
const { params: { runNumber } } = dto;

queryBuilder.where('runNumber').is(runNumber);

const logs = await TransactionHelper.provide(async () => {
return TransactionHelper.provide(async () => {
const run = await RunRepository.findOne(queryBuilder);
return run ? LogRepository.findAllByRunId(run.id) : null;
return run ? logService.getAllByRun(run.id) : null;
});

if (logs) {
const logsWithReplies = await LogRepository.addChildrenCountByLog(logs);
return logsWithReplies.map(logAdapter.toEntity);
} else {
return null;
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/api/environments.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ module.exports = () => {
const response = await request(server).get('/api/environments/8E4aZTjY/logs');
expect(response.status).to.equal(200);
expect(response.body.data).to.lengthOf(3);

// Log 1 is linked to all kind of entities, which must be returned for logs displayed in embedded tables
const log = response.body.data.find(({ id }) => id === 1);
expect(log.runs).to.deep.equal([{ id: 1, runNumber: 1 }]);
expect(log.lhcFills.map(({ fillNumber }) => fillNumber)).to.have.members([5, 6]);
expect(log.environments.map(({ id }) => id)).to.have.members(['8E4aZTjY', 'eZF99lH6']);
expect(log.dataPasses.map(({ name }) => name)).to.have.members(['LHC22b_apass1', 'LHC22b_skimming']);
expect(log.attachments).to.be.an('array');
});
});
};
8 changes: 8 additions & 0 deletions test/api/lhcFills.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,14 @@ module.exports = () => {
const response = await request(server).get('/api/lhcFills/6/logs');
expect(response.status).to.equal(200);
expect(response.body.data).to.lengthOf(2);

// Log 1 is linked to all kind of entities, which must be returned for logs displayed in embedded tables
const log = response.body.data.find(({ id }) => id === 1);
expect(log.runs).to.deep.equal([{ id: 1, runNumber: 1 }]);
expect(log.lhcFills.map(({ fillNumber }) => fillNumber)).to.have.members([5, 6]);
expect(log.environments.map(({ id }) => id)).to.have.members(['8E4aZTjY', 'eZF99lH6']);
expect(log.dataPasses.map(({ name }) => name)).to.have.members(['LHC22b_apass1', 'LHC22b_skimming']);
expect(log.attachments).to.be.an('array');
});
});

Expand Down
9 changes: 9 additions & 0 deletions test/api/runs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,15 @@ module.exports = () => {
runNumber: 1,
},
]);
// Relations used by the embedded logs table of the run details page must be returned too
const log = res.body.data[0];
expect(log.lhcFills.map(({ fillNumber }) => fillNumber)).to.have.members([5, 6]);
expect(log.environments.map(({ id }) => id)).to.have.members(['8E4aZTjY', 'eZF99lH6']);
expect(log.dataPasses.map(({ name }) => name)).to.have.members(['LHC22b_apass1', 'LHC22b_skimming']);
expect(log.attachments).to.be.an('array');
// Tags must be complete to be displayed with their color and archived state
expect(log.tags).to.not.be.empty;
expect(log.tags.every(({ archived }) => typeof archived === 'boolean')).to.be.true;
done();
});
});
Expand Down
15 changes: 15 additions & 0 deletions test/api/tags.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,21 @@ module.exports = () => {
});
});
});
describe('GET /api/tags/:tagId/logs relations', () => {
it('should return the relations displayed in the embedded logs table', async () => {
const response = await request(server).get('/api/tags/3/logs');
expect(response.status).to.equal(200);

// Log 1 is linked to all kind of entities, which must be returned for logs displayed in embedded tables
const log = response.body.data.find(({ id }) => id === 1);
expect(log.runs).to.deep.equal([{ id: 1, runNumber: 1 }]);
expect(log.lhcFills.map(({ fillNumber }) => fillNumber)).to.have.members([5, 6]);
expect(log.environments.map(({ id }) => id)).to.have.members(['8E4aZTjY', 'eZF99lH6']);
expect(log.dataPasses.map(({ name }) => name)).to.have.members(['LHC22b_apass1', 'LHC22b_skimming']);
expect(log.attachments).to.be.an('array');
});
});

describe('GET /api/tags/name', () => {
it('should return 200 if a valid query is given', (done) => {
request(server)
Expand Down
42 changes: 42 additions & 0 deletions test/lib/server/services/log/LogService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,46 @@ module.exports = () => {

expect(childLogs.length).to.equal(expectedAmountOfChildren);
});

it('Should successfully return all the logs of a run, with all their relations', async () => {
const logs = await logService.getAllByRun(1);

expect(logs.map(({ id }) => id)).to.include(1);
const log = logs.find(({ id }) => id === 1);
expect(log.runs).to.deep.equal([{ id: 1, runNumber: 1 }]);
expect(log.lhcFills.map(({ fillNumber }) => fillNumber)).to.have.members([5, 6]);
expect(log.environments.map(({ id }) => id)).to.have.members(['8E4aZTjY', 'eZF99lH6']);
expect(log.dataPasses.map(({ name }) => name)).to.have.members(['LHC22b_apass1', 'LHC22b_skimming']);
// Complete tags (with their color and archived state) are required to display the logs, the author is only exposed by name
expect(log.tags).to.not.be.empty;
expect(log.tags.every(({ archived, updatedAt }) => typeof archived === 'boolean' && typeof updatedAt === 'number')).to.be.true;
expect(log.author.name).to.be.a('string');
});

it('Should successfully return the attachments of logs linked to a run, an LHC fill or an environment', async () => {
const { id: logId } = await logService.create(
logMock,
[1],
[],
['8E4aZTjY'],
[6],
[{
size: 10,
path: '/tmp/attachment.txt',
filename: 'attachment.txt',
originalname: 'attachment.txt',
mimetype: 'text/plain',
encoding: '7bit',
}],
);

for (const logs of [
await logService.getAllByRun(1),
await logService.getAllByLhcFill(6),
await logService.getAllByEnvironment('8E4aZTjY'),
]) {
const log = logs.find(({ id }) => id === logId);
expect(log.attachments.map(({ originalName }) => originalName)).to.deep.equal(['attachment.txt']);
}
});
};
Loading