From d45c735ee06a1f926f1af75232043acc03fdb755 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:10:51 +0200 Subject: [PATCH 01/11] Extract detectors functionality in parent class --- .../views/Runs/Overview/RunsWithQcModel.js | 49 ++++++++++++++++++- .../RunsPerDataPassOverviewModel.js | 26 +++------- .../RunsPerLhcPeriodOverviewModel.js | 15 ++---- .../RunsPerSimulationPassOverviewModel.js | 12 ----- 4 files changed, 58 insertions(+), 44 deletions(-) diff --git a/lib/public/views/Runs/Overview/RunsWithQcModel.js b/lib/public/views/Runs/Overview/RunsWithQcModel.js index e9ec4f36c5..9ccfd05ac2 100644 --- a/lib/public/views/Runs/Overview/RunsWithQcModel.js +++ b/lib/public/views/Runs/Overview/RunsWithQcModel.js @@ -45,6 +45,7 @@ import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { mergeRemoteData } from '../../../utilities/mergeRemoteData.js'; import { ToggleFilterModel } from '../../../components/Filters/common/filters/ToggleFilterModel.js'; import { MultiCompositionFilterModel } from '../../../components/Filters/RunsFilter/MultiCompositionFilterModel.js'; +import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js'; /** * Merge QC summaries @@ -86,6 +87,8 @@ export class RunsWithQcModel extends RunsOverviewModel { this._qcSummary$ = new ObservableData(RemoteData.notAsked()); this._qcSummary$.bubbleTo(this); + this._setDetectorsObservable(); + this.patchDisplayOptions({ horizontalScrollEnabled: true, verticalScrollEnabled: true, @@ -133,6 +136,48 @@ export class RunsWithQcModel extends RunsOverviewModel { super.load(); } + /** + * Build and register a detectors observable with optional filtering logic. + * + * @param {ObservableData|ObservableData[]} [sourceOrSources=rctDetectorsProvider.qc$] detector source(s) + * @param {function} [filterDetectors=(detectors) => detectors] callback used to filter detectors on success + * @return {ObservableData>} detector observable + */ + _setDetectorsObservable(sourceOrSources = rctDetectorsProvider.qc$, filterDetectors = (detectors) => detectors) { + this._detectors$ = this._buildDetectorsObservable(sourceOrSources, filterDetectors); + this._detectors$.bubbleTo(this); + return this._detectors$; + } + + /** + * Create a detectors observable from one or multiple sources. + * + * @param {ObservableData|ObservableData[]} sourceOrSources detector source(s) + * @param {function} filterDetectors callback used to filter detectors on success + * @return {ObservableData>} detector observable + */ + _buildDetectorsObservable(sourceOrSources, filterDetectors) { + const builder = ObservableData.builder(); + + if (Array.isArray(sourceOrSources)) { + builder.sources(sourceOrSources); + } else { + builder.source(sourceOrSources); + } + + return builder + .apply((remoteDataList) => { + const mergedRemoteData = Array.isArray(remoteDataList) + ? mergeRemoteData(remoteDataList) + : remoteDataList; + + return mergedRemoteData.apply({ + Success: (payload) => filterDetectors(payload), + }); + }) + .build(); + } + /** * Register not-bad fraction detectors filtering model and update it when detectors are loaded * Also, trigger an immediate update if detectors are already loaded at the moment of registration @@ -216,12 +261,12 @@ export class RunsWithQcModel extends RunsOverviewModel { } /** - * Return detectors which a model uses + * Return detectors which a model uses. * * @returns {RemoteData} remote data list of detectors */ get detectors() { - throw Error('Method not implemented'); + return this._detectors$.getCurrent(); } /** diff --git a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js index 5bceeeeeb4..057064c7f8 100644 --- a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js +++ b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js @@ -20,7 +20,6 @@ import { jsonPatch } from '../../../utilities/fetch/jsonPatch.js'; import { jsonPut } from '../../../utilities/fetch/jsonPut.js'; import { SkimmingStage } from '../../../domain/enums/SkimmingStage.js'; import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js'; -import { mergeRemoteData } from '../../../utilities/mergeRemoteData.js'; import { RemoteDataSource } from '../../../utilities/fetch/RemoteDataSource.js'; import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { GaqFilterModel } from '../../../components/Filters/RunsFilter/GaqFilterModel.js'; @@ -42,19 +41,14 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo this._dataPass$ = new ObservableData(RemoteData.notAsked()); this._dataPass$.bubbleTo(this); - this._detectors$ = ObservableData - .builder() - .sources([rctDetectorsProvider.qc$, this._dataPass$]) - .apply((remoteDataList) => mergeRemoteData(remoteDataList) - .apply({ Success: ([detectors, dataPass]) => ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name) - ? detectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name)) - : detectors, - })) - .build(); - this._filteringModel.put('gaq', new GaqFilterModel(this._mcReproducibleAsNotBad)); - this._detectors$.bubbleTo(this); + this._setDetectorsObservable( + [rctDetectorsProvider.qc$, this._dataPass$], + ([detectors, dataPass]) => ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name) + ? detectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name)) + : detectors, + ); this._markAsSkimmableRequestResult$ = new ObservableData(RemoteData.notAsked()); this._markAsSkimmableRequestResult$.bubbleTo(this); @@ -285,14 +279,6 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo return this._dataPass$.getCurrent(); } - /** - * Get all detectors - * @return {RemoteData} detectors - */ - get detectors() { - return this._detectors$.getCurrent(); - } - /** * GAQ summary getter * @return {RemoteData} GAQ summary diff --git a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js index c009f2acd8..8a6505b33d 100644 --- a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js +++ b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js @@ -33,16 +33,11 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM this._lhcPeriodId = null; this._lhcPeriodStatistics$ = new ObservableData(RemoteData.notAsked()); - this._syncDetectors$ = ObservableData - .builder() - .source(rctDetectorsProvider.qc$) - .apply((remoteDetectors) => - remoteDetectors.apply({ - Success: (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)), - })) - .build(); - - this._syncDetectors$.bubbleTo(this); + this._syncDetectors$ = this._setDetectorsObservable( + rctDetectorsProvider.qc$, + (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)), + ); + this._detectors$ = this._syncDetectors$; this._lhcPeriodStatistics$.bubbleTo(this); } diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js index 084b57d130..0179d6a2c1 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js @@ -13,7 +13,6 @@ import { buildUrl, RemoteData } from '/js/src/index.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; -import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js'; import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js'; /** @@ -30,9 +29,6 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver this._simulationPass$ = new ObservableData(RemoteData.notAsked()); - this._detectors$ = rctDetectorsProvider.qc$; - - this._detectors$.bubbleTo(this); this._simulationPass$.bubbleTo(this); } @@ -106,14 +102,6 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver return this._simulationPass$.getCurrent(); } - /** - * Get all detectors - * @return {RemoteData} detectors - */ - get detectors() { - return this._detectors$.getCurrent(); - } - /** * @inheritdoc */ From ac38591fbbb123f0d0427c93714539c52b94da76 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:24:30 +0200 Subject: [PATCH 02/11] Add util function to filter out old detectors if needed --- lib/utilities/index.js | 2 ++ lib/utilities/stringUtils.js | 16 ++++++++++++++++ test/lib/utilities/stringUtils.test.js | 19 ++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/utilities/index.js b/lib/utilities/index.js index 6f69ed84b0..76733376a7 100644 --- a/lib/utilities/index.js +++ b/lib/utilities/index.js @@ -13,8 +13,10 @@ const deepmerge = require('./deepmerge'); const isPromise = require('./isPromise'); +const { filterOutLegacyDetectorsForNewerPeriods } = require('./stringUtils'); module.exports = { deepmerge, isPromise, + filterOutLegacyDetectorsForNewerPeriods, }; diff --git a/lib/utilities/stringUtils.js b/lib/utilities/stringUtils.js index 9f22effee2..1017c44ab6 100644 --- a/lib/utilities/stringUtils.js +++ b/lib/utilities/stringUtils.js @@ -72,6 +72,20 @@ const splitStringToStringsTrimmed = (stringCollection, stringSeparator = ',') => .map((string) => string.trim()) .filter(Boolean); +/** + * Remove legacy detectors for newer LHC periods. + * + * @param {Detector[]} detectors detectors to filter + * @param {string} [label=''] name of the period or data pass + * @param {string[]} [legacyDetectorNames=['CPV', 'PHS']] detectors to remove for newer periods after LHC25 + * @return {Detector[]} filtered detectors + */ +const filterOutLegacyDetectorsForNewerPeriods = (detectors, label = '', legacyDetectorNames = ['CPV', 'PHS']) => { + const shouldFilterOutLegacyDetectors = /LHC(2[5-9]|[3-9]\d)/.test(label ?? ''); + + return detectors.filter(({ name }) => !shouldFilterOutLegacyDetectors || !legacyDetectorNames.includes(name)); +}; + exports.ucFirst = ucFirst; exports.lcFirst = lcFirst; @@ -85,3 +99,5 @@ exports.snakeToCamel = snakeToCamel; exports.snakeToPascal = snakeToPascal; exports.splitStringToStringsTrimmed = splitStringToStringsTrimmed; + +exports.filterOutLegacyDetectorsForNewerPeriods = filterOutLegacyDetectorsForNewerPeriods; diff --git a/test/lib/utilities/stringUtils.test.js b/test/lib/utilities/stringUtils.test.js index fb06df6d4c..df82d0a73b 100644 --- a/test/lib/utilities/stringUtils.test.js +++ b/test/lib/utilities/stringUtils.test.js @@ -11,7 +11,15 @@ * or submit itself to any jurisdiction. */ -const { snakeToCamel, pascalToSnake, ucFirst, lcFirst, snakeToPascal, splitStringToStringsTrimmed } = require('../../../lib/utilities/stringUtils.js'); +const { + snakeToCamel, + pascalToSnake, + ucFirst, + lcFirst, + snakeToPascal, + splitStringToStringsTrimmed, + filterOutLegacyDetectorsForNewerPeriods, +} = require('../../../lib/utilities/stringUtils.js'); const { expect } = require('chai'); module.exports = () => { @@ -79,4 +87,13 @@ module.exports = () => { expect(snakeToPascal('_THIS_IS_SNAKE_CASE_')).to.equal('ThisIsSnakeCase'); expect(snakeToPascal('SNAKE')).to.equal('Snake'); }); + + it('should filter legacy detectors for newer periods', () => { + const detectors = [{ name: 'CPV' }, { name: 'PHS' }, { name: 'ITS' }]; + + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC25ab')).to.deep.equal([{ name: 'ITS' }]); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC26ad_cpass1_residuals')).to.deep.equal([{ name: 'ITS' }]); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC24')).to.deep.equal(detectors); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, '')).to.deep.equal(detectors); + }); }; From a6c21a7a2ed6b354db7c888a4623e7711d9faeee Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:25:01 +0200 Subject: [PATCH 03/11] Use the new function to filter out detectors depending on the pass or period --- .../RunPerDataPass/RunsPerDataPassOverviewModel.js | 11 ++++++++--- .../RunPerPeriod/RunsPerLhcPeriodOverviewModel.js | 9 +++++++-- .../RunsPerSimulationPassOverviewModel.js | 8 ++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js index 057064c7f8..49ad47de77 100644 --- a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js +++ b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js @@ -23,6 +23,7 @@ import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js'; import { RemoteDataSource } from '../../../utilities/fetch/RemoteDataSource.js'; import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { GaqFilterModel } from '../../../components/Filters/RunsFilter/GaqFilterModel.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; const ALL_CPASS_PRODUCTIONS_REGEX = /cpass\d+/; const DETECTOR_NAMES_NOT_IN_CPASSES = ['EVS']; @@ -45,9 +46,13 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo this._setDetectorsObservable( [rctDetectorsProvider.qc$, this._dataPass$], - ([detectors, dataPass]) => ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name) - ? detectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name)) - : detectors, + ([detectors, dataPass]) => { + const filteredDetectors = filterOutLegacyDetectorsForNewerPeriods(detectors, dataPass.name); + + return ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name) + ? filteredDetectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name)) + : filteredDetectors; + }, ); this._markAsSkimmableRequestResult$ = new ObservableData(RemoteData.notAsked()); diff --git a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js index 8a6505b33d..bac9b71781 100644 --- a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js +++ b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js @@ -16,6 +16,7 @@ import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js'; import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; /** * Runs Per LHC Period overview model @@ -34,8 +35,12 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM this._lhcPeriodStatistics$ = new ObservableData(RemoteData.notAsked()); this._syncDetectors$ = this._setDetectorsObservable( - rctDetectorsProvider.qc$, - (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)), + [rctDetectorsProvider.qc$, this._lhcPeriodStatistics$], + ([detectors, lhcPeriodStatistics]) => { + const filteredDetectors = filterOutLegacyDetectorsForNewerPeriods(detectors, lhcPeriodStatistics.lhcPeriod.name); + + return filteredDetectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)); + }, ); this._detectors$ = this._syncDetectors$; this._lhcPeriodStatistics$.bubbleTo(this); diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js index 0179d6a2c1..d2fc41ad20 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js @@ -14,6 +14,8 @@ import { buildUrl, RemoteData } from '/js/src/index.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js'; +import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; /** * Runs Per Simulation Pass overview model @@ -30,6 +32,12 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver this._simulationPass$ = new ObservableData(RemoteData.notAsked()); this._simulationPass$.bubbleTo(this); + this._detectors$ = this._setDetectorsObservable( + [rctDetectorsProvider.qc$, this._simulationPass$], + ([detectors, simulationPass]) => { + return filterOutLegacyDetectorsForNewerPeriods(detectors, simulationPass.name); + }, + ); } /** From 253b46c5ca9e59abe3b535720354ad21e5ca9662 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:28:38 +0200 Subject: [PATCH 04/11] Fix eslint issue --- .../RunsPerSimulationPassOverviewModel.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js index d2fc41ad20..9417020e1a 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js @@ -34,9 +34,7 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver this._simulationPass$.bubbleTo(this); this._detectors$ = this._setDetectorsObservable( [rctDetectorsProvider.qc$, this._simulationPass$], - ([detectors, simulationPass]) => { - return filterOutLegacyDetectorsForNewerPeriods(detectors, simulationPass.name); - }, + ([detectors, simulationPass]) => filterOutLegacyDetectorsForNewerPeriods(detectors, simulationPass.name), ); } From b3820d456a5982c846e25959d685755d36430484 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:37:04 +0200 Subject: [PATCH 05/11] Move util function in utilities of front-end rather than back-end --- ...filterOutLegacyDetectorsForNewerPeriods.js | 29 +++++++++++++++++++ .../RunsPerDataPassOverviewModel.js | 2 +- .../RunsPerLhcPeriodOverviewModel.js | 2 +- .../RunsPerSimulationPassOverviewModel.js | 2 +- lib/utilities/index.js | 2 -- lib/utilities/stringUtils.js | 16 ---------- ...rOutLegacyDetectorsForNewerPeriods.test.js | 26 +++++++++++++++++ test/lib/public/utilities/index.js | 2 ++ test/lib/utilities/stringUtils.test.js | 18 +----------- 9 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js create mode 100644 test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js diff --git a/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js new file mode 100644 index 0000000000..6a9024113c --- /dev/null +++ b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js @@ -0,0 +1,29 @@ +/** + * @license + * Copyright CERN and copyright holders of ALICE O2. This software is + * distributed under the terms of the GNU General Public License v3 (GPL + * Version 3), copied verbatim in the file "COPYING". + * + * See http://alice-o2.web.cern.ch/license for full licensing information. + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +const LEGACY_DETECTOR_NAMES_FOR_AFTER_25 = ['CPV', 'PHS']; +/** + * Remove legacy detectors for newer LHC periods/passes (after LHC25) from the list of detectors. + * + * @param {Detector[]} detectors detectors to filter + * @param {string} [label=''] name of the period or data pass + * @param {string[]} [legacyDetectorNames=['CPV', 'PHS']] detectors to remove for newer periods after LHC25 + * @return {Detector[]} filtered detectors + */ +const filterOutLegacyDetectorsForNewerPeriods = (detectors = [], label = '') => { + const shouldFilterOutLegacyDetectors = /LHC(2[5-9]|[3-9]\d)/.test(label ?? ''); + + return detectors.filter(({ name }) => !shouldFilterOutLegacyDetectors || !LEGACY_DETECTOR_NAMES_FOR_AFTER_25.includes(name)); +}; + +export { filterOutLegacyDetectorsForNewerPeriods }; diff --git a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js index 49ad47de77..f532b13bd2 100644 --- a/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js +++ b/lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js @@ -23,7 +23,7 @@ import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js'; import { RemoteDataSource } from '../../../utilities/fetch/RemoteDataSource.js'; import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { GaqFilterModel } from '../../../components/Filters/RunsFilter/GaqFilterModel.js'; -import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js'; const ALL_CPASS_PRODUCTIONS_REGEX = /cpass\d+/; const DETECTOR_NAMES_NOT_IN_CPASSES = ['EVS']; diff --git a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js index bac9b71781..cd61bc63a9 100644 --- a/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js +++ b/lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js @@ -16,7 +16,7 @@ import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js'; import { DetectorType } from '../../../domain/enums/DetectorTypes.js'; import { ObservableData } from '../../../utilities/ObservableData.js'; import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js'; -import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js'; /** * Runs Per LHC Period overview model diff --git a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js index 9417020e1a..663b5139c9 100644 --- a/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js +++ b/lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js @@ -15,7 +15,7 @@ import { ObservableData } from '../../../utilities/ObservableData.js'; import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js'; import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js'; import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js'; -import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/stringUtils.js'; +import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js'; /** * Runs Per Simulation Pass overview model diff --git a/lib/utilities/index.js b/lib/utilities/index.js index 76733376a7..6f69ed84b0 100644 --- a/lib/utilities/index.js +++ b/lib/utilities/index.js @@ -13,10 +13,8 @@ const deepmerge = require('./deepmerge'); const isPromise = require('./isPromise'); -const { filterOutLegacyDetectorsForNewerPeriods } = require('./stringUtils'); module.exports = { deepmerge, isPromise, - filterOutLegacyDetectorsForNewerPeriods, }; diff --git a/lib/utilities/stringUtils.js b/lib/utilities/stringUtils.js index 1017c44ab6..9f22effee2 100644 --- a/lib/utilities/stringUtils.js +++ b/lib/utilities/stringUtils.js @@ -72,20 +72,6 @@ const splitStringToStringsTrimmed = (stringCollection, stringSeparator = ',') => .map((string) => string.trim()) .filter(Boolean); -/** - * Remove legacy detectors for newer LHC periods. - * - * @param {Detector[]} detectors detectors to filter - * @param {string} [label=''] name of the period or data pass - * @param {string[]} [legacyDetectorNames=['CPV', 'PHS']] detectors to remove for newer periods after LHC25 - * @return {Detector[]} filtered detectors - */ -const filterOutLegacyDetectorsForNewerPeriods = (detectors, label = '', legacyDetectorNames = ['CPV', 'PHS']) => { - const shouldFilterOutLegacyDetectors = /LHC(2[5-9]|[3-9]\d)/.test(label ?? ''); - - return detectors.filter(({ name }) => !shouldFilterOutLegacyDetectors || !legacyDetectorNames.includes(name)); -}; - exports.ucFirst = ucFirst; exports.lcFirst = lcFirst; @@ -99,5 +85,3 @@ exports.snakeToCamel = snakeToCamel; exports.snakeToPascal = snakeToPascal; exports.splitStringToStringsTrimmed = splitStringToStringsTrimmed; - -exports.filterOutLegacyDetectorsForNewerPeriods = filterOutLegacyDetectorsForNewerPeriods; diff --git a/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js b/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js new file mode 100644 index 0000000000..ba3ae95f8e --- /dev/null +++ b/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js @@ -0,0 +1,26 @@ +/** + * @license + * Copyright CERN and copyright holders of ALICE O2. This software is + * distributed under the terms of the GNU General Public License v3 (GPL + * Version 3), copied verbatim in the file "COPYING". + * + * See http://alice-o2.web.cern.ch/license for full licensing information. + * + * In applying this license CERN does not waive the privileges and immunities + * granted to it by virtue of its status as an Intergovernmental Organization + * or submit itself to any jurisdiction. + */ + +const { expect } = require('chai'); +const { filterOutLegacyDetectorsForNewerPeriods } = require('../../../../lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js'); + +module.exports = () => { + it('should filter legacy detectors for newer periods', () => { + const detectors = [{ name: 'CPV' }, { name: 'PHS' }, { name: 'ITS' }]; + + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC25ab')).to.deep.equal([{ name: 'ITS' }]); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC26ad_cpass1_residuals')).to.deep.equal([{ name: 'ITS' }]); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC24')).to.deep.equal(detectors); + expect(filterOutLegacyDetectorsForNewerPeriods(detectors, '')).to.deep.equal(detectors); + }); +}; diff --git a/test/lib/public/utilities/index.js b/test/lib/public/utilities/index.js index 5d2771b5e0..b7163daa0f 100644 --- a/test/lib/public/utilities/index.js +++ b/test/lib/public/utilities/index.js @@ -12,7 +12,9 @@ */ const FormattingSuite = require('./formatting/index.js'); +const FilterOutLegacyDetectorsForNewerPeriodsSuite = require('./filterOutLegacyDetectorsForNewerPeriods.test.js'); module.exports = () => { describe('FormattingSuite', FormattingSuite); + describe('FilterOutLegacyDetectorsForNewerPeriods', FilterOutLegacyDetectorsForNewerPeriodsSuite); }; diff --git a/test/lib/utilities/stringUtils.test.js b/test/lib/utilities/stringUtils.test.js index df82d0a73b..7f385a0fa6 100644 --- a/test/lib/utilities/stringUtils.test.js +++ b/test/lib/utilities/stringUtils.test.js @@ -11,15 +11,7 @@ * or submit itself to any jurisdiction. */ -const { - snakeToCamel, - pascalToSnake, - ucFirst, - lcFirst, - snakeToPascal, - splitStringToStringsTrimmed, - filterOutLegacyDetectorsForNewerPeriods, -} = require('../../../lib/utilities/stringUtils.js'); +const { snakeToCamel, pascalToSnake, ucFirst, lcFirst, snakeToPascal, splitStringToStringsTrimmed } = require('../../../lib/utilities/stringUtils.js'); const { expect } = require('chai'); module.exports = () => { @@ -88,12 +80,4 @@ module.exports = () => { expect(snakeToPascal('SNAKE')).to.equal('Snake'); }); - it('should filter legacy detectors for newer periods', () => { - const detectors = [{ name: 'CPV' }, { name: 'PHS' }, { name: 'ITS' }]; - - expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC25ab')).to.deep.equal([{ name: 'ITS' }]); - expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC26ad_cpass1_residuals')).to.deep.equal([{ name: 'ITS' }]); - expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC24')).to.deep.equal(detectors); - expect(filterOutLegacyDetectorsForNewerPeriods(detectors, '')).to.deep.equal(detectors); - }); }; From eee38a280adf60bd6d62753c970cbc6a7d0922e4 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:44:14 +0200 Subject: [PATCH 06/11] Fix lint issue --- lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js index 6a9024113c..0da05d3555 100644 --- a/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js +++ b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js @@ -12,6 +12,7 @@ */ const LEGACY_DETECTOR_NAMES_FOR_AFTER_25 = ['CPV', 'PHS']; + /** * Remove legacy detectors for newer LHC periods/passes (after LHC25) from the list of detectors. * From 885851180a05b1cf8905e9353c2f6a78fad463a9 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 14:49:47 +0200 Subject: [PATCH 07/11] Do not early trigger the loading and instead wait for child class --- lib/public/views/Runs/Overview/RunsWithQcModel.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/public/views/Runs/Overview/RunsWithQcModel.js b/lib/public/views/Runs/Overview/RunsWithQcModel.js index 9ccfd05ac2..5b77d1325e 100644 --- a/lib/public/views/Runs/Overview/RunsWithQcModel.js +++ b/lib/public/views/Runs/Overview/RunsWithQcModel.js @@ -87,8 +87,6 @@ export class RunsWithQcModel extends RunsOverviewModel { this._qcSummary$ = new ObservableData(RemoteData.notAsked()); this._qcSummary$.bubbleTo(this); - this._setDetectorsObservable(); - this.patchDisplayOptions({ horizontalScrollEnabled: true, verticalScrollEnabled: true, @@ -266,6 +264,11 @@ export class RunsWithQcModel extends RunsOverviewModel { * @returns {RemoteData} remote data list of detectors */ get detectors() { + if (!this._detectors$) { + this._detectors$ = new ObservableData(RemoteData.notAsked()); + this._detectors$.bubbleTo(this); + } + return this._detectors$.getCurrent(); } From 711a4519db067a17ef39fd5c62309ee9f59e0bce Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 15:06:16 +0200 Subject: [PATCH 08/11] Fix way of importing test --- .../utilities/filterOutLegacyDetectorsForNewerPeriods.js | 1 - .../utilities/filterOutLegacyDetectorsForNewerPeriods.test.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js index 0da05d3555..4c95138c1f 100644 --- a/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js +++ b/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js @@ -18,7 +18,6 @@ const LEGACY_DETECTOR_NAMES_FOR_AFTER_25 = ['CPV', 'PHS']; * * @param {Detector[]} detectors detectors to filter * @param {string} [label=''] name of the period or data pass - * @param {string[]} [legacyDetectorNames=['CPV', 'PHS']] detectors to remove for newer periods after LHC25 * @return {Detector[]} filtered detectors */ const filterOutLegacyDetectorsForNewerPeriods = (detectors = [], label = '') => { diff --git a/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js b/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js index ba3ae95f8e..015f37363b 100644 --- a/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js +++ b/test/lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.test.js @@ -12,10 +12,10 @@ */ const { expect } = require('chai'); -const { filterOutLegacyDetectorsForNewerPeriods } = require('../../../../lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js'); module.exports = () => { - it('should filter legacy detectors for newer periods', () => { + it('should filter legacy detectors for newer periods', async () => { + const { filterOutLegacyDetectorsForNewerPeriods } = await import('../../../../lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js'); const detectors = [{ name: 'CPV' }, { name: 'PHS' }, { name: 'ITS' }]; expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC25ab')).to.deep.equal([{ name: 'ITS' }]); From 2e72c2d0a918ca640223ca9b13fbee347bf08739 Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 15:28:12 +0200 Subject: [PATCH 09/11] Use window.model reference instead of direct model --- test/public/runs/overview.test.js | 17 ++++++----------- .../runs/runsPerDataPass.overview.test.js | 14 +++++--------- .../runs/runsPerLhcPeriod.overview.test.js | 10 ++++------ .../runs/runsPerSimulationPass.overview.test.js | 10 ++++------ 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/test/public/runs/overview.test.js b/test/public/runs/overview.test.js index e67cecaee1..ef5586d119 100644 --- a/test/public/runs/overview.test.js +++ b/test/public/runs/overview.test.js @@ -219,8 +219,7 @@ module.exports = () => { // Override the amount of runs visible per page manually await navigateToRunsOverview(page); await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.overviewModel.pagination.itemsPerPage = 1; + window.model.runs.overviewModel.pagination.itemsPerPage = 1; }); await waitForTableLength(page, 1); @@ -238,7 +237,7 @@ module.exports = () => { it('notifies if table loading returned an error', async () => { await navigateToRunsOverview(page); // eslint-disable-next-line no-return-assign, no-undef - await page.evaluate(() => model.runs.overviewModel.pagination.itemsPerPage = 200); + await page.evaluate(() => window.model.runs.overviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); // We expect there to be a fitting error message @@ -247,8 +246,7 @@ module.exports = () => { // Revert changes for next test await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.overviewModel.pagination.itemsPerPage = 10; + window.model.runs.overviewModel.pagination.itemsPerPage = 10; }); await waitForTableLength(page, 10); }); @@ -436,8 +434,7 @@ module.exports = () => { }; await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.overviewModel.pagination.itemsPerPage = 20; + window.model.runs.overviewModel.pagination.itemsPerPage = 20; }); await pressElement(page, physicsFilterSelector, true); @@ -473,8 +470,7 @@ module.exports = () => { await pressElement(page, cosmicsFilterSelector, true); await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.overviewModel.pagination.itemsPerPage = 20; + window.model.runs.overviewModel.pagination.itemsPerPage = 20; }); await checkTableSizeAndDefinition( @@ -597,8 +593,7 @@ module.exports = () => { const ltuFilterSelector = `${filterInputSelectorPrefix}LTU`; await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.overviewModel.pagination.itemsPerPage = 10; + window.model.runs.overviewModel.pagination.itemsPerPage = 10; }); await waitForTableLength(page, 10); diff --git a/test/public/runs/runsPerDataPass.overview.test.js b/test/public/runs/runsPerDataPass.overview.test.js index 4d1edbb4d6..be22de36af 100644 --- a/test/public/runs/runsPerDataPass.overview.test.js +++ b/test/public/runs/runsPerDataPass.overview.test.js @@ -306,17 +306,15 @@ module.exports = () => { }); await page.waitForSelector(`${amountSelectorId} input:invalid`); await page.evaluate(() => { - // eslint-disable-next-line no-return-assign, no-undef - model.runs.perDataPassOverviewModel.pagination.reset(); - // eslint-disable-next-line no-return-assign, no-undef - model.runs.perDataPassOverviewModel.notify(); + window.model.runs.perDataPassOverviewModel.pagination.reset(); + window.model.runs.perDataPassOverviewModel.notify(); }); }); it('notifies if table loading returned an error', async () => { await navigateToRunsPerDataPass(page, 1, 3, 4); // eslint-disable-next-line no-return-assign, no-undef - await page.evaluate(() => model.runs.perDataPassOverviewModel.pagination.itemsPerPage = 200); + await page.evaluate(() => window.model.runs.perDataPassOverviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); // We expect there to be a fitting error message @@ -325,10 +323,8 @@ module.exports = () => { // Revert changes for next test await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.perDataPassOverviewModel.pagination.reset(); - // eslint-disable-next-line no-undef - model.runs.perDataPassOverviewModel.notify(); + window.model.runs.perDataPassOverviewModel.pagination.reset(); + window.model.runs.perDataPassOverviewModel.notify(); }); await waitForTableLength(page, 4); }); diff --git a/test/public/runs/runsPerLhcPeriod.overview.test.js b/test/public/runs/runsPerLhcPeriod.overview.test.js index f52e2b8086..fcd7de671e 100644 --- a/test/public/runs/runsPerLhcPeriod.overview.test.js +++ b/test/public/runs/runsPerLhcPeriod.overview.test.js @@ -181,8 +181,8 @@ module.exports = () => { }); it('notifies if table loading returned an error', async () => { - // eslint-disable-next-line no-return-assign, no-undef - await page.evaluate(() => model.runs.perLhcPeriodOverviewModel.pagination.itemsPerPage = 200); + // eslint-disable-next-line no-return-assign + await page.evaluate(() => window.model.runs.perLhcPeriodOverviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); // We expect there to be a fitting error message @@ -191,8 +191,7 @@ module.exports = () => { // Revert changes for next test await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.perLhcPeriodOverviewModel.pagination.itemsPerPage = 2; + window.model.runs.perLhcPeriodOverviewModel.pagination.itemsPerPage = 2; }); await waitForTableLength(page, 2); }); @@ -244,8 +243,7 @@ module.exports = () => { fs.unlinkSync(path.resolve(downloadPath, targetFileName)); await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.perLhcPeriodOverviewModel.reset(); + window.model.runs.perLhcPeriodOverviewModel.reset(); }); }); diff --git a/test/public/runs/runsPerSimulationPass.overview.test.js b/test/public/runs/runsPerSimulationPass.overview.test.js index f3c2d47316..b4103f47cb 100644 --- a/test/public/runs/runsPerSimulationPass.overview.test.js +++ b/test/public/runs/runsPerSimulationPass.overview.test.js @@ -186,17 +186,15 @@ module.exports = () => { }); it('notifies if table loading returned an error', async () => { - // eslint-disable-next-line no-return-assign, no-undef - await page.evaluate(() => model.runs.perSimulationPassOverviewModel.pagination.itemsPerPage = 200); + // eslint-disable-next-line no-return-assign + await page.evaluate(() => window.model.runs.perSimulationPassOverviewModel.pagination.itemsPerPage = 200); // We expect there to be a fitting error message const expectedMessage = 'Invalid Attribute: "query.page.limit" must be less than or equal to 100'; await expectInnerText(page, '.alert-danger', expectedMessage); await page.evaluate(() => { - // eslint-disable-next-line no-undef - model.runs.perSimulationPassOverviewModel.pagination.reset(); - // eslint-disable-next-line no-undef - model.runs.perSimulationPassOverviewModel.pagination.notify(); + window.model.runs.perSimulationPassOverviewModel.pagination.reset(); + window.model.runs.perSimulationPassOverviewModel.pagination.notify(); }); await waitForTableLength(page, 3); }); From f634769c2e619632448f12cc483d16216305c7ab Mon Sep 17 00:00:00 2001 From: George Raduta Date: Mon, 10 Aug 2026 15:36:28 +0200 Subject: [PATCH 10/11] Add safe-check function for test --- test/public/runs/overview.test.js | 3 ++- test/public/runs/runsPerDataPass.overview.test.js | 3 ++- test/public/runs/runsPerLhcPeriod.overview.test.js | 1 + test/public/runs/runsPerSimulationPass.overview.test.js | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/public/runs/overview.test.js b/test/public/runs/overview.test.js index ef5586d119..16feb209db 100644 --- a/test/public/runs/overview.test.js +++ b/test/public/runs/overview.test.js @@ -236,7 +236,8 @@ module.exports = () => { it('notifies if table loading returned an error', async () => { await navigateToRunsOverview(page); - // eslint-disable-next-line no-return-assign, no-undef + await page.waitForFunction(() => window.model?.runs?.overviewModel?.pagination); + // eslint-disable-next-line no-return-assign await page.evaluate(() => window.model.runs.overviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); diff --git a/test/public/runs/runsPerDataPass.overview.test.js b/test/public/runs/runsPerDataPass.overview.test.js index be22de36af..6a9ecf34ca 100644 --- a/test/public/runs/runsPerDataPass.overview.test.js +++ b/test/public/runs/runsPerDataPass.overview.test.js @@ -313,7 +313,8 @@ module.exports = () => { it('notifies if table loading returned an error', async () => { await navigateToRunsPerDataPass(page, 1, 3, 4); - // eslint-disable-next-line no-return-assign, no-undef + await page.waitForFunction(() => window.model?.runs?.perDataPassOverviewModel?.pagination); + // eslint-disable-next-line no-return-assign await page.evaluate(() => window.model.runs.perDataPassOverviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); diff --git a/test/public/runs/runsPerLhcPeriod.overview.test.js b/test/public/runs/runsPerLhcPeriod.overview.test.js index fcd7de671e..98f6e955ed 100644 --- a/test/public/runs/runsPerLhcPeriod.overview.test.js +++ b/test/public/runs/runsPerLhcPeriod.overview.test.js @@ -181,6 +181,7 @@ module.exports = () => { }); it('notifies if table loading returned an error', async () => { + await page.waitForFunction(() => window.model?.runs?.perLhcPeriodOverviewModel?.pagination); // eslint-disable-next-line no-return-assign await page.evaluate(() => window.model.runs.perLhcPeriodOverviewModel.pagination.itemsPerPage = 200); await page.waitForSelector('.alert-danger'); diff --git a/test/public/runs/runsPerSimulationPass.overview.test.js b/test/public/runs/runsPerSimulationPass.overview.test.js index b4103f47cb..c9e93a8730 100644 --- a/test/public/runs/runsPerSimulationPass.overview.test.js +++ b/test/public/runs/runsPerSimulationPass.overview.test.js @@ -186,6 +186,7 @@ module.exports = () => { }); it('notifies if table loading returned an error', async () => { + await page.waitForFunction(() => window.model?.runs?.perSimulationPassOverviewModel?.pagination); // eslint-disable-next-line no-return-assign await page.evaluate(() => window.model.runs.perSimulationPassOverviewModel.pagination.itemsPerPage = 200); From fa5f6d5b1c099e406e4371fb82a55bd8797071ee Mon Sep 17 00:00:00 2001 From: George Raduta Date: Tue, 11 Aug 2026 09:30:46 +0200 Subject: [PATCH 11/11] Improve reliability of the test --- .../runsPerSimulationPass.overview.test.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/public/runs/runsPerSimulationPass.overview.test.js b/test/public/runs/runsPerSimulationPass.overview.test.js index c9e93a8730..d4c4413a5b 100644 --- a/test/public/runs/runsPerSimulationPass.overview.test.js +++ b/test/public/runs/runsPerSimulationPass.overview.test.js @@ -182,21 +182,23 @@ module.exports = () => { await page.waitForSelector(`${amountSelectorId} .dropup-menu`); await fillInput(page, `${amountSelectorId} input[type=number]`, 1111); - await page.waitForSelector(amountSelectorId); + await page.waitForSelector(`${amountSelectorId} input:invalid`); + await fillInput(page, `${amountSelectorId} input[type=number]`, ''); + await page.waitForSelector(`${amountSelectorId} input:not(:invalid)`); }); it('notifies if table loading returned an error', async () => { - await page.waitForFunction(() => window.model?.runs?.perSimulationPassOverviewModel?.pagination); - // eslint-disable-next-line no-return-assign - await page.evaluate(() => window.model.runs.perSimulationPassOverviewModel.pagination.itemsPerPage = 200); + const amountSelectorId = '#amountSelector'; + await pressElement(page, `${amountSelectorId} button`); + await page.waitForSelector(`${amountSelectorId} .dropup-menu`); + // 200 exceeds the API query limit (100), but is within the UI input range (1–1000) + // This is set via the docker-compose test variable + await fillInput(page, `${amountSelectorId} input[type=number]`, '200', ['input', 'change']); - // We expect there to be a fitting error message const expectedMessage = 'Invalid Attribute: "query.page.limit" must be less than or equal to 100'; await expectInnerText(page, '.alert-danger', expectedMessage); - await page.evaluate(() => { - window.model.runs.perSimulationPassOverviewModel.pagination.reset(); - window.model.runs.perSimulationPassOverviewModel.pagination.notify(); - }); + + await goToPage(page, 'runs-per-simulation-pass', { queryParameters: { simulationPassId: 2 } }); await waitForTableLength(page, 3); });