Skip to content

Commit e946e72

Browse files
[O2B-1498] Update api endpoint to filter runs by beam mode (#2078)
- beamModes has been added to the getAllRunsDTO and is considered valid if: - Array entries consist of strings made up of uppercase words with single spaces between them
1 parent b74f0fa commit e946e72

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

lib/domain/dtos/filters/RunFilterDto.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ const EorReasonFilterDto = Joi.object({
3232
});
3333

3434
exports.RunFilterDto = Joi.object({
35+
beamModes: CustomJoi.stringArray().items(Joi.string()
36+
.trim()
37+
.pattern(/^[A-Z]{1,15}( [A-Z]{1,15}){0,2}/)
38+
.messages({
39+
'string.pattern.base':
40+
'Beam modes "{{#value}}" must contain only uppercase letters and single spaces between words.',
41+
})),
3542
runNumbers: Joi.string().trim().custom(validateRange).messages({
3643
[RANGE_INVALID]: '{{#message}}',
3744
'string.base': 'Run numbers must be comma-separated numbers or ranges (e.g. 12,15-18)',

lib/usecases/run/GetAllRunsUseCase.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class GetAllRunsUseCase {
8282
inelasticInteractionRateAtEnd,
8383
gaq,
8484
detectorsQc,
85+
beamModes,
8586
} = filter;
8687

8788
if (runNumbers) {
@@ -113,6 +114,10 @@ class GetAllRunsUseCase {
113114
filteringQueryBuilder.where('definition').oneOf(...definitions);
114115
}
115116

117+
if (beamModes) {
118+
filteringQueryBuilder.where('lhcBeamMode').oneOf(...beamModes);
119+
}
120+
116121
if (eorReason) {
117122
const eorReasonTypeWhere = {};
118123
if (eorReason.category) {

test/api/runs.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,37 @@ module.exports = () => {
142142
expect(runs).to.lengthOf(20);
143143
});
144144

145+
it('should successfully filter with single beamMode', async () => {
146+
const response = await request(server).get('/api/runs?filter[beamModes]=STABLE BEAMS');
147+
148+
expect(response.status).to.equal(200);
149+
const { data: runs } = response.body;
150+
151+
expect(runs).to.lengthOf(5);
152+
});
153+
154+
it('should successfully filter with multiple beamModes', async () => {
155+
const response = await request(server).get('/api/runs?filter[beamModes]=STABLE BEAMS,NO BEAM');
156+
157+
expect(response.status).to.equal(200);
158+
const { data: runs } = response.body;
159+
160+
expect(runs).to.lengthOf(6);
161+
});
162+
163+
it('should return 400 if beamModes filter has the incorrect format', async () => {
164+
const beamModeString = '*THERE\'S NON LETTERS IN HERE';
165+
const response = await request(server).get(`/api/runs?filter[beamModes]=${beamModeString}`);
166+
167+
168+
expect(response.status).to.equal(400);
169+
170+
const { errors: [error] } = response.body;
171+
172+
expect(error.title).to.equal('Invalid Attribute');
173+
expect(error.detail).to.equal(`Beam modes "${beamModeString}" must contain only uppercase letters and single spaces between words.`);
174+
});
175+
145176
it('should successfully filter on multiple specified run numbers', async () => {
146177
const response = await request(server).get('/api/runs?filter[runNumbers]=17,18');
147178

test/lib/usecases/run/GetAllRunsUseCase.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,32 @@ module.exports = () => {
183183
}
184184
});
185185

186+
it('should successfully filter on beamModes', async () => {
187+
const singleBeamMode = ['STABLE BEAMS'];
188+
const multipleBeamMode = ['STABLE BEAMS', 'NO BEAM'];
189+
const nonExistentBeamMode = ['DOES NOT EXIST'];
190+
191+
getAllRunsDto.query = { filter: { beamModes: singleBeamMode } };
192+
{
193+
const { runs } = await new GetAllRunsUseCase().execute(getAllRunsDto);
194+
expect(runs).to.have.lengthOf(5);
195+
expect(runs.every(({ lhcBeamMode }) => singleBeamMode.includes(lhcBeamMode))).to.be.true;
196+
}
197+
198+
getAllRunsDto.query = { filter: { beamModes: multipleBeamMode } };
199+
{
200+
const { runs } = await new GetAllRunsUseCase().execute(getAllRunsDto);
201+
expect(runs).to.have.lengthOf(6);
202+
expect(runs.every(({ lhcBeamMode }) => multipleBeamMode.includes(lhcBeamMode))).to.be.true;
203+
}
204+
205+
getAllRunsDto.query = { filter: { beamModes: nonExistentBeamMode } };
206+
{
207+
const { runs } = await new GetAllRunsUseCase().execute(getAllRunsDto);
208+
expect(runs).to.have.lengthOf(0);
209+
}
210+
});
211+
186212
it('should successfully filter on run definition', async () => {
187213
const PHYSICS_COUNT = 7;
188214
const COSMICS_COUNT = 2;

0 commit comments

Comments
 (0)