Skip to content

Commit 8e82b34

Browse files
committed
[O2B-1503] Processed feedback, added tests
1 parent fd055ca commit 8e82b34

4 files changed

Lines changed: 177 additions & 6 deletions

File tree

lib/usecases/lhcFill/GetAllLhcFillsUseCase.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class GetAllLhcFillsUseCase {
5858

5959
// Check that the final fill numbers list contains at least one valid fill number
6060
if (finalFillnumberList.length > 0) {
61-
queryBuilder.where('fillNumber').oneOf(...finalFillnumberList);
61+
finalFillnumberList.length === 1 ? queryBuilder.where('fillNumber').is(finalFillnumberList[0])
62+
: queryBuilder.where('fillNumber').oneOf(...finalFillnumberList);
6263
}
6364
}
6465
}

lib/utilities/rangeUtils.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ export const validateRange = (value, helpers) => {
2626

2727
for (const number of numbers) {
2828
if (number.includes('-')) {
29-
const [start, end] = number.split('-').map((n) => parseInt(n, 10));
29+
// Check if '-' occurs more than once in this part of the range
30+
if (number.lastIndexOf('-') !== number.indexOf('-')) {
31+
return helpers.error('any.invalid', { message: `Invalid range: ${number}` });
32+
}
33+
const [start, end] = number.split('-').map((n) => Number(n));
3034
if (Number.isNaN(start) || Number.isNaN(end) || start > end) {
3135
return helpers.error('any.invalid', { message: `Invalid range: ${number}` });
3236
}
@@ -35,6 +39,11 @@ export const validateRange = (value, helpers) => {
3539
if (rangeSize > MAX_RANGE_SIZE) {
3640
return helpers.error('any.invalid', { message: `Given range exceeds max size of ${MAX_RANGE_SIZE} range: ${number}` });
3741
}
42+
} else {
43+
// Prevent non-numeric input.
44+
if (isNaN(number)) {
45+
return helpers.error('any.invalid', { message: `Invalid number: ${number}` });
46+
}
3847
}
3948
}
4049

@@ -44,15 +53,15 @@ export const validateRange = (value, helpers) => {
4453
/**
4554
* Unpacks a given string containing number ranges.
4655
* E.G. input: 5,7-9 => output: 5,7,8,9
47-
* @param {string} numbersRange numbers that may or may not contain ranges.
56+
* @param {string[]} numbersRanges numbers that may or may not contain ranges.
4857
* @param {string} rangeSplitter string used to indicate and unpack a range.
4958
* @returns {Set<Number>} set containing the unpacked range.
5059
*/
51-
export function unpackNumberRange(numbersRange, rangeSplitter = '-') {
60+
export function unpackNumberRange(numbersRanges, rangeSplitter = '-') {
5261
// Set to prevent duplicate values.
5362
const resultNumbers = new Set();
5463

55-
numbersRange.forEach((number) => {
64+
numbersRanges.forEach((number) => {
5665
if (number.includes(rangeSplitter)) {
5766
const [start, end] = number.split(rangeSplitter).map((n) => parseInt(n, 10));
5867
if (!Number.isNaN(start) && !Number.isNaN(end)) {
@@ -61,7 +70,7 @@ export function unpackNumberRange(numbersRange, rangeSplitter = '-') {
6170
}
6271
}
6372
} else {
64-
if (!Number.isNaN(number)) {
73+
if (!isNaN(number)) {
6574
resultNumbers.add(Number(number));
6675
}
6776
}

test/lib/utilities/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
const cacheAsyncFunctionTest = require('./cacheAsyncFunction.test.js');
1515
const deepmerge = require('./deepmerge.test.js');
1616
const isPromise = require('./isPromise.test.js');
17+
const rangeUtilsTest = require('./rangeUtils.test.js');
1718
const stringUtilsTest = require('./stringUtils.test.js');
1819

1920
module.exports = () => {
2021
describe('cacheFunction', cacheAsyncFunctionTest);
2122
describe('deepmerge', deepmerge);
2223
describe('isPromise', isPromise);
2324
describe('stringUtils', stringUtilsTest);
25+
describe('rangeUtils', rangeUtilsTest)
2426
};
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
const Sinon = require('sinon');
15+
const { validateRange, unpackNumberRange } = require('../../../lib/utilities/rangeUtils.js');
16+
const { expect } = require('chai');
17+
18+
module.exports = () => {
19+
describe('validateRange()', () => {
20+
let helpers;
21+
22+
beforeEach(() => {
23+
helpers = {
24+
error: Sinon.stub()
25+
};
26+
});
27+
28+
it('returns the original value for a single valid number', () => {
29+
const input = '5';
30+
const result = validateRange(input, helpers);
31+
expect(result).to.equal(input);
32+
});
33+
34+
it('returns the original value, accepts 0', () => {
35+
const input = '0,1';
36+
const result = validateRange(input, helpers);
37+
expect(result).to.equal(input);
38+
});
39+
40+
it('returns the original value for multiple valid numbers', () => {
41+
const input = '1, 2,3, 10 ';
42+
const result = validateRange(input, helpers);
43+
expect(result).to.equal(input);
44+
});
45+
46+
it('accepts a valid range', () => {
47+
const input = '7-9';
48+
const result = validateRange(input, helpers);
49+
expect(result).to.equal(input);
50+
});
51+
52+
it('accepts numbers and ranges together', () => {
53+
const input = '5,7-9,12';
54+
const result = validateRange(input, helpers);
55+
expect(result).to.equal(input);
56+
});
57+
58+
it('accepts numbers and ranges overlap', () => {
59+
const input = '1-6,2,3,4,5,6';
60+
const result = validateRange(input, helpers);
61+
expect(result).to.equal(input);
62+
});
63+
64+
it('rejects non-numeric input', () => {
65+
const input = '5,a,7';
66+
validateRange(input, helpers);
67+
expect(helpers.error.calledOnce).to.be.true;
68+
expect(helpers.error.firstCall.args[0]).to.equal('any.invalid');
69+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Invalid number: a' });
70+
});
71+
72+
it('rejects range with non-numeric input', () => {
73+
const input = '3-a';
74+
validateRange(input, helpers);
75+
expect(helpers.error.calledOnce).to.be.true;
76+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Invalid range: 3-a' });
77+
});
78+
79+
it('rejects range where Start > End', () => {
80+
const input = '6-5';
81+
validateRange(input, helpers);
82+
expect(helpers.error.calledOnce).to.be.true;
83+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Invalid range: 6-5' });
84+
});
85+
86+
// Allowed, technically a valid range
87+
it('accepts range where Start === End', () => {
88+
const input = '5-5';
89+
const result = validateRange(input, helpers);
90+
expect(result).to.equal(input);
91+
});
92+
93+
it('rejects range containing more than one `-`', () => {
94+
const input = '1-2-3';
95+
validateRange(input, helpers);
96+
expect(helpers.error.calledOnce).to.be.true;
97+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Invalid range: 1-2-3' });
98+
});
99+
100+
it('rejects range containing more than one `-`, at end', () => {
101+
const input = '1-2-';
102+
validateRange(input, helpers);
103+
expect(helpers.error.calledOnce).to.be.true;
104+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Invalid range: 1-2-' });
105+
});
106+
107+
// MAX_RANGE_SIZE = 100, should this change, also change this test...
108+
it('rejects a range that exceeds MAX_RANGE_SIZE', () => {
109+
const input = '1-101';
110+
validateRange(input, helpers);
111+
expect(helpers.error.calledOnce).to.be.true;
112+
expect(helpers.error.firstCall.args[1]).to.deep.equal({ message: 'Given range exceeds max size of 100 range: 1-101' });
113+
});
114+
115+
it('handles whitespace around inputs', () => {
116+
const input = ' 2 , 4-6 , 9 ';
117+
const result = validateRange(input, helpers);
118+
expect(result).to.equal(input);
119+
});
120+
});
121+
122+
describe('unpackNumberRange()', () => {
123+
it('unpacks single numbers, duplicate', () => {
124+
const input = ['5', '10', '5'];
125+
const result = unpackNumberRange(input);
126+
expect(Array.from(result)).to.deep.equal([5, 10]);
127+
});
128+
129+
it('unpacks range', () => {
130+
const input = ['7-9'];
131+
const result = unpackNumberRange(input);
132+
expect(Array.from(result)).to.deep.equal([7, 8, 9]);
133+
});
134+
135+
it('unpacks mixed numbers and ranges', () => {
136+
const input = ['5', '7-9', '9', '3-4'];
137+
const result = unpackNumberRange(input);
138+
expect(Array.from(result)).to.deep.equal([5, 7, 8, 9, 3, 4]);
139+
});
140+
141+
it('ignores any non-numeric inputs', () => {
142+
const input = ['5', 'x', '2-3', 'a-b', '4-a'];
143+
const result = unpackNumberRange(input);
144+
expect(Array.from(result)).to.deep.equal([5, 2, 3]);
145+
});
146+
147+
it('accepts/uses a range splitter', () => {
148+
const input = ['8..10', '12'];
149+
const result = unpackNumberRange(input, '..');
150+
expect(Array.from(result)).to.deep.equal([8, 9, 10, 12]);
151+
});
152+
153+
// Also allowed right now...
154+
it('returns empty set if nothing is given', () => {
155+
const result = unpackNumberRange([]);
156+
expect(result.size).to.equal(0);
157+
});
158+
});
159+
};

0 commit comments

Comments
 (0)