diff --git a/InfoLogger/public/Model.js b/InfoLogger/public/Model.js index 1c933c7b7..9006e916b 100644 --- a/InfoLogger/public/Model.js +++ b/InfoLogger/public/Model.js @@ -15,13 +15,14 @@ // Import frontend framework import { Observable, WebSocketClient, QueryRouter, - Loader, RemoteData, sessionService, Notification, + Loader, RemoteData, sessionService, Notification, iconMediaPlay, iconMediaStop, } from '/js/src/index.js'; import Log from './log/Log.js'; import Timezone from './common/Timezone.js'; -import { callRateLimiter, setBrowserTabTitle } from './common/utils.js'; +import { setBrowserTabTitle } from './common/utils.js'; import Table from './table/Table.js'; import { MODE } from './constants/mode.const.js'; +import { BUTTON } from './constants/button-states.const.js'; /** * Main model of InfoLoggerGui, contains sub-models modules @@ -33,6 +34,7 @@ export default class Model extends Observable { constructor() { super(); + this.guiReadyToUse = RemoteData.loading(); this.session = sessionService.get(); this.session.personid = parseInt(this.session.personid, 10); // cast, sessionService has only strings @@ -48,6 +50,10 @@ export default class Model extends Observable { this.timezone = new Timezone(); this.timezone.bubbleTo(this); + this.queryButtonType = BUTTON.PRIMARY; + this.liveButtonType = BUTTON.DEFAULT; + this.liveButtonIcon = iconMediaPlay(); + this.notification = new Notification(this); this.notification.bubbleTo(this); @@ -62,6 +68,9 @@ export default class Model extends Observable { this.router = new QueryRouter(); this.router.observe(this.handleLocationChange.bind(this)); this.router.bubbleTo(this); + this.log.filter.observe(() => { + this.router.go(`?q=${JSON.stringify(this.log.filter.toObject())}`, true, true); + }); this.handleLocationChange(); // Init first page // Setup keyboard dispatcher @@ -72,11 +81,6 @@ export default class Model extends Observable { this.ws.addListener('command', this.handleWSCommand.bind(this)); this.ws.addListener('authed', this.handleWSAuthed.bind(this)); this.ws.addListener('close', this.handleWSClose.bind(this)); - - // update router on model change - // Model can change very often we protect router with callRateLimiter - // Router limit: 100 calls per 30 seconds max = 30ms, 2 FPS is enough (500ms) - this.observe(callRateLimiter(this.updateRouteOnModelChange.bind(this), 500)); } /** @@ -84,7 +88,9 @@ export default class Model extends Observable { */ handleWSAuthed() { // Tell server not to stream by default + this.guiReadyToUse = RemoteData.success(); this.ws.setFilter(() => false); + this.notify(); } /** @@ -319,7 +325,7 @@ export default class Model extends Observable { * Delegates sub-model actions depending if location is filters or profile * @param {object} params - URL parameters */ - parseLocation(params) { + async parseLocation(params) { if (params.profile && params.q) { this.log.filter.resetCriteria(); this.notification.show('URL can contain only filters or profile, not both', 'warning'); @@ -330,17 +336,59 @@ export default class Model extends Observable { } else if (params.q) { this.getUserProfile(); this.log.filter.fromObject(JSON.parse(params.q.replaceAll('\n', '\\n'))); + if (params.live == 'true') { + await this.loadLiveMode(); + } + } else if (!params.q) { + this.getUserProfile(); + this.log.filter.resetCriteria(); + if (params.live == 'true') { + await this.loadLiveMode(); + } } else { this.getUserProfile(); } } /** - * When model change (filters), update address bar with the filter - * do it silently to avoid infinite loop + * Attempt to load into the live mode of the ILG + */ + async loadLiveMode() { + while (this.guiReadyToUse.isLoading() + || !this.frameworkInfo.isSuccess() + || !this.frameworkInfo.payload.infoLoggerServer.status.ok) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + try { + this.log.liveStart(); + this.setLiveButton(BUTTON.SUCCESS_ACTIVE, iconMediaStop()); + this.setQueryButton(BUTTON.DEFAULT); + this.log.enableAutoScroll(); + setBrowserTabTitle(`${window.ILG.name} LIVE`); + this.notify(); + } catch (error) { + this.notification.show(error.toString(), 'danger', 3000); + } + } + + /** + * Method to change the icon and type of the liveButton + * @param {string} liveType - Type of the Live Button + * @param {Icon} liveIcon - Icon of the Live Button + */ + setLiveButton(liveType, liveIcon) { + this.liveButtonType = liveType; + this.liveButtonIcon = liveIcon; + this.notify(); + } + + /** + * Method to change the type of the queryButton + * @param {string} queryType - Type of the queryButton */ - updateRouteOnModelChange() { - this.router.go(`?q=${JSON.stringify(this.log.filter.toObject())}`, true, true); + setQueryButton(queryType) { + this.queryButtonType = queryType; + this.notify(); } /** diff --git a/InfoLogger/public/log/commandLogs.js b/InfoLogger/public/log/commandLogs.js index 231ff2f6f..ab4c91ca8 100644 --- a/InfoLogger/public/log/commandLogs.js +++ b/InfoLogger/public/log/commandLogs.js @@ -17,10 +17,6 @@ import { BUTTON } from '../constants/button-states.const.js'; import { MODE } from '../constants/mode.const.js'; import { setBrowserTabTitle } from '../common/utils.js'; -let queryButtonType = BUTTON.PRIMARY; -let liveButtonType = BUTTON.DEFAULT; -let liveButtonIcon = iconMediaPlay(); - export default (model) => [ userActionsDropdown(model), h('div.btn-group.mh3', [ @@ -111,7 +107,7 @@ const queryButton = (model) => h('button.btn', model.frameworkInfo.match({ title: frameworkInfo.mysql && frameworkInfo.mysql.status.ok ? 'Query database with filters (Enter)' : 'Query service not configured', disabled: !frameworkInfo.mysql || !frameworkInfo.mysql.status.ok || model.log.queryResult.isLoading(), - className: model.log.queryResult.isLoading() ? 'loading' : queryButtonType, + className: model.log.queryResult.isLoading() ? 'loading' : model.queryButtonType, style: 'font-weight: bold', onclick: () => toggleButtonStates(model, false), }), @@ -165,12 +161,12 @@ const liveButton = (model) => h('button.btn', model.frameworkInfo.match({ Success: (frameworkInfo) => ({ title: frameworkInfo.infoLoggerServer.status.ok ? 'Stream logs with filtering' : 'Live service not configured', disabled: !frameworkInfo.infoLoggerServer.status.ok || model.log.queryResult.isLoading(), - className: !model.ws.authed ? 'loading' : liveButtonType, + className: model.guiReadyToUse.isLoading() ? 'loading' : model.liveButtonType, style: 'font-weight: bold', onclick: () => toggleButtonStates(model, true), }), Failure: () => ({ disabled: true, className: 'danger' }), -}), 'Live', ' ', liveButtonIcon); +}), 'Live', ' ', model.liveButtonIcon); /** * Method to toggle states of the buttons(Query/Live) depending on the mode the tool is running on @@ -185,7 +181,7 @@ function toggleButtonStates(model, wasLivePressed) { case MODE.LIVE.PAUSED: try { model.log.liveStart(); - setButtonsType(BUTTON.DEFAULT, BUTTON.SUCCESS_ACTIVE, iconMediaStop()); + setButtonsType(BUTTON.DEFAULT, BUTTON.SUCCESS_ACTIVE, iconMediaStop(), model); model.log.enableAutoScroll(); setBrowserTabTitle(`${window.ILG.name} LIVE`); } catch (error) { @@ -195,13 +191,13 @@ function toggleButtonStates(model, wasLivePressed) { default: // MODE.LIVE.RUNNING model.log.liveStop(MODE.LIVE.PAUSED); setBrowserTabTitle(`${window.ILG.name} LIVE PAUSED`); - setButtonsType(BUTTON.DEFAULT, BUTTON.PRIMARY, iconMediaPlay()); + setButtonsType(BUTTON.DEFAULT, BUTTON.PRIMARY, iconMediaPlay(), model); model.log.disableAutoScroll(); } } else { model.log.query(); setBrowserTabTitle(`${window.ILG.name} QUERY`); - setButtonsType(BUTTON.PRIMARY, BUTTON.DEFAULT, iconMediaPlay()); + setButtonsType(BUTTON.PRIMARY, BUTTON.DEFAULT, iconMediaPlay(), model); } /** @@ -209,10 +205,10 @@ function toggleButtonStates(model, wasLivePressed) { * @param {string} queryType Type of the Query Button * @param {string} liveType Type of the Live Button * @param {Icon} liveIcon Icon of the Live Button + * @param {Model} model - Model, stores liveButton type and icon state */ - function setButtonsType(queryType, liveType, liveIcon) { - queryButtonType = queryType; - liveButtonType = liveType; - liveButtonIcon = liveIcon; + function setButtonsType(queryType, liveType, liveIcon, model) { + model.setQueryButton(queryType); + model.setLiveButton(liveType, liveIcon); } } diff --git a/InfoLogger/public/logFilter/LogFilter.js b/InfoLogger/public/logFilter/LogFilter.js index 502b10def..415e37661 100644 --- a/InfoLogger/public/logFilter/LogFilter.js +++ b/InfoLogger/public/logFilter/LogFilter.js @@ -41,7 +41,6 @@ export default class LogFilter extends Observable { super(); this.model = model; - this.resetCriteria(); } diff --git a/InfoLogger/public/view.js b/InfoLogger/public/view.js index 8f744afce..8a59c04fd 100644 --- a/InfoLogger/public/view.js +++ b/InfoLogger/public/view.js @@ -48,7 +48,7 @@ export default (model) => [ ]), h('div.flex-grow.flex-row.shadow-level0.logs-container', [ aboutComponent(model), - logsTable(model), + model.guiReadyToUse.isSuccess() ? logsTable(model) : 'waiting for WebSocket connection', inspectorSide(model), ]), h('footer.f7.ph1', [statusBar(model)]), diff --git a/InfoLogger/test/mocha-index.js b/InfoLogger/test/mocha-index.js index 2f6a246ae..82d111112 100644 --- a/InfoLogger/test/mocha-index.js +++ b/InfoLogger/test/mocha-index.js @@ -10,15 +10,15 @@ * 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. -*/ + */ /* eslint-disable no-console */ const puppeteer = require('puppeteer'); const assert = require('assert'); -const {spawn} = require('child_process'); +const { spawn } = require('child_process'); const config = require('./test-config.js'); -const {createServer, closeServer} = require('./live-simulator/infoLoggerServer.js'); +const { createServer, closeServer } = require('./live-simulator/infoLoggerServer.js'); // APIs: // https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md @@ -28,16 +28,16 @@ const {createServer, closeServer} = require('./live-simulator/infoLoggerServer.j // Network and rendering can have delays this can leads to random failures // if they are tested just after their initialization. -describe('InfoLogger', function() { +describe('InfoLogger', function () { let browser; let page; let subprocess; // web-server runs into a subprocess let subprocessOutput = ''; let ilgServer; - + this.timeout(30000); this.slow(1000); - + const baseUrl = `http://${config.http.hostname}:${config.http.port}/`; before(async () => { @@ -45,25 +45,26 @@ describe('InfoLogger', function() { ilgServer = createServer(); // Start web-server in background - subprocess = spawn('node', ['index.js', 'test/test-config.js'], {stdio: 'pipe'}); + subprocess = spawn('node', ['index.js', 'test/test-config.js'], { stdio: 'pipe' }); subprocess.stdout.on('data', (chunk) => subprocessOutput += chunk.toString()); subprocess.stderr.on('data', (chunk) => subprocessOutput += chunk.toString()); - subprocess.on('error', (error) => console.error(`Server failed due to: ${error}`)) + subprocess.on('error', (error) => console.error(`Server failed due to: ${error}`)); // Start browser to test UI - browser = await puppeteer.launch({headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox']}); + browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); page = await browser.newPage(); // Export page and configurations for the other mocha files exports.page = page; - exports.helpers = {baseUrl, jwt: config.jwt}; + + exports.helpers = { baseUrl, jwt: config.jwt }; }); it('should load first page "/"', async () => { // try many times until backend server is ready for (let i = 0; i < 10; i++) { try { - await page.goto(baseUrl, {waitUntil: 'networkidle0'}); + await page.goto(baseUrl, { waitUntil: 'networkidle0' }); break; // connection ok, this test passed } catch (e) { if (e.message.includes('net::ERR_CONNECTION_REFUSED')) { @@ -75,8 +76,8 @@ describe('InfoLogger', function() { } }); - it('should have redirected to default page "/?q={"severity":{"in":"I W E F"}}"', async function() { - await page.goto(baseUrl, {waitUntil: 'networkidle0'}); + it('should have redirected to default page "/?q={"severity":{"in":"I W E F"}}"', async () => { + await page.goto(baseUrl, { waitUntil: 'networkidle0' }); const location = await page.evaluate(() => window.location); const search = decodeURIComponent(location.search); @@ -97,7 +98,5 @@ describe('InfoLogger', function() { console.log('---------------------------------------------'); subprocess.kill(); closeServer(ilgServer); - }); }); - diff --git a/InfoLogger/test/public/live-mode-mocha.js b/InfoLogger/test/public/live-mode-mocha.js index a74d9cecc..484708f96 100644 --- a/InfoLogger/test/public/live-mode-mocha.js +++ b/InfoLogger/test/public/live-mode-mocha.js @@ -1,3 +1,4 @@ +/* eslint-disable @stylistic/js/max-len */ /** * @license * Copyright 2019-2020 CERN and copyright holders of ALICE O2. @@ -10,9 +11,7 @@ * 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. -*/ - -/* eslint-disable max-len */ + */ const assert = require('assert'); const test = require('../mocha-index'); @@ -23,11 +22,10 @@ describe('Live Mode test-suite', async () => { before(async () => { baseUrl = test.helpers.baseUrl; page = test.page; - }); - it('should successfully go to homepage with predefined filters', async function() { - await page.goto(baseUrl, {waitUntil: 'networkidle0'}); + it('should successfully go to homepage with predefined filters', async () => { + await page.goto(baseUrl, { waitUntil: 'networkidle0' }); const location = await page.evaluate(() => window.location); const search = decodeURIComponent(location.search); @@ -55,9 +53,9 @@ describe('Live Mode test-suite', async () => { assert.strictEqual(criterias.level.$max, 21); // Wait for logs and count them (2-3 maybe, it's random) - await page.waitForFunction(`window.model.log.list.length > 0`, {timeout: 5000}); + await page.waitForFunction('window.model.log.list.length > 0', { timeout: 5000 }); const list = await page.evaluate(() => window.model.log.list); - assert.ok(!!list.length); + assert.ok(Boolean(list.length)); }); it('should filter messages based on `hostname` matching `aldaqecs01-v1` from live -> paused -> live', async () => { @@ -67,7 +65,7 @@ describe('Live Mode test-suite', async () => { window.model.log.filter.setCriteria('hostname', 'match', 'aldaqecs01-v1'); }); await page.evaluate(() => window.model.log.liveStart()); - await page.waitForFunction(`window.model.log.list.length > 5`, {timeout: 5000}); + await page.waitForFunction('window.model.log.list.length > 5', { timeout: 5000 }); const list = await page.evaluate(() => window.model.log.list); const isHostNameMatching = list.map((element) => element.hostname).every((hostname) => hostname === 'aldaqecs01-v1'); assert.ok(list.length > 0); @@ -81,7 +79,7 @@ describe('Live Mode test-suite', async () => { window.model.log.filter.setCriteria('hostname', 'exclude', 'aldaqdip01'); }); await page.evaluate(() => window.model.log.liveStart()); - await page.waitForFunction(`window.model.log.list.length > 5`, {timeout: 5000}); + await page.waitForFunction('window.model.log.list.length > 5', { timeout: 5000 }); const list = await page.evaluate(() => window.model.log.list); const isHostNameMatching = list.map((element) => element.hostname).every((hostname) => hostname !== 'aldaqdip01'); @@ -97,7 +95,7 @@ describe('Live Mode test-suite', async () => { window.model.log.setCriteria('username', 'match', 'a_iceda_'); window.model.log.empty(); }); - await page.waitForFunction(`window.model.log.list.length > 5`, {timeout: 5000}); + await page.waitForFunction('window.model.log.list.length > 5', { timeout: 5000 }); const list = await page.evaluate(() => window.model.log.list); const isHostNameMatching = list.map((element) => element.hostname).every((hostname) => !new RegExp('.*ldaqdip.*').test(hostname)); @@ -108,6 +106,28 @@ describe('Live Mode test-suite', async () => { assert.ok(isUserNameMatching); }); + it('should successfully enable LIVE mode from url parameter with defined filter', async () => { + await page.goto(`${baseUrl}?q={"severity":{"in":"I W E F"}}&live=true`, { waitUntil: 'networkidle0' }); + const liveButtonClasses = await page.evaluate(() => window.model.liveButtonType); + const search = decodeURIComponent(await page.evaluate(() => window.location.search)); + + // Check if live mode is active. + assert.strictEqual(liveButtonClasses, 'btn-success active'); + // Check if filter is applied + assert.strictEqual(search, '?q={"severity":{"in":"I W E F"}}'); + }); + + it('should successfully enable LIVE mode from url parameter with default filter', async () => { + await page.goto(`${baseUrl}?live=true`, { waitUntil: 'networkidle0' }); + const liveButtonClasses = await page.evaluate(() => window.model.liveButtonType); + const search = decodeURIComponent(await page.evaluate(() => window.location.search)); + + // Check if live mode is active. + assert.strictEqual(liveButtonClasses, 'btn-success active'); + // Check if redirected to default page + assert.strictEqual(search, '?q={"severity":{"in":"I W E F"}}'); + }); + it('should successfully go to mode LIVE in paused state', async () => { const activeMode = await page.evaluate(() => { window.model.log.liveStop('Paused'); @@ -118,10 +138,10 @@ describe('Live Mode test-suite', async () => { }); it('successfully show indicator when user double pressed the log row', async () => { - await page.waitForSelector('body > div:nth-child(2) > div:nth-child(2) > main > div > div > div > table > tbody > tr', {timeout: 5000}); + await page.waitForSelector('body > div:nth-child(2) > div:nth-child(2) > main > div > div > div > table > tbody > tr', { timeout: 5000 }); const tableRow = await page.$('body > div:nth-child(2) > div:nth-child(2) > main > div > div > div > table > tbody > tr'); - await tableRow.click({clickCount: 2}); - await page.waitForSelector('#inspector-sidebar', {timeout: 1000}) + await tableRow.click({ clickCount: 2 }); + await page.waitForSelector('#inspector-sidebar', { timeout: 1000 }); const indicatorOpen = await page.evaluate(() => window.model.inspectorEnabled); assert.ok(indicatorOpen); @@ -147,8 +167,3 @@ describe('Live Mode test-suite', async () => { assert.deepStrictEqual(activeMode, 'Query'); }); }); - - - - - diff --git a/InfoLogger/test/public/log-filter-actions-mocha.js b/InfoLogger/test/public/log-filter-actions-mocha.js index 4b67ebe56..4d8d33f5e 100644 --- a/InfoLogger/test/public/log-filter-actions-mocha.js +++ b/InfoLogger/test/public/log-filter-actions-mocha.js @@ -10,9 +10,8 @@ * 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. -*/ + */ -/* eslint-disable max-len */ const assert = require('assert'); const test = require('../mocha-index'); @@ -25,8 +24,8 @@ describe('Filter actions test-suite', async () => { page = test.page; }); - it('should succesfully load a page with profile in the URI', async function() { - await page.goto(baseUrl + "?profile=physicist", {waitUntil: 'networkidle0'}); + it('should succesfully load a page with profile in the URI', async () => { + await page.goto(`${baseUrl}?profile=physicist`, { waitUntil: 'networkidle0' }); const location = await page.evaluate(() => window.location); const search = decodeURIComponent(location.search); @@ -36,70 +35,66 @@ describe('Filter actions test-suite', async () => { it('should update column headers based on profile when passed in the URI', async () => { const expectedColumns = { - date: {size: 'cell-m', visible: false}, - time: {size: 'cell-m', visible: true}, - hostname: {size: 'cell-m', visible: true}, - rolename: {size: 'cell-m', visible: false}, - pid: {size: 'cell-s', visible: false}, - username: {size: 'cell-m', visible: false}, - system: {size: 'cell-s', visible: true}, - facility: {size: 'cell-m', visible: true}, - detector: {size: 'cell-s', visible: true}, - partition: {size: 'cell-m', visible: true}, - run: {size: 'cell-s', visible: true}, - errcode: {size: 'cell-s', visible: false}, - errline: {size: 'cell-s', visible: false}, - errsource: {size: 'cell-m', visible: false}, - message: {size: 'cell-xl', visible: true} + date: { size: 'cell-m', visible: false }, + time: { size: 'cell-m', visible: true }, + hostname: { size: 'cell-m', visible: true }, + rolename: { size: 'cell-m', visible: false }, + pid: { size: 'cell-s', visible: false }, + username: { size: 'cell-m', visible: false }, + system: { size: 'cell-s', visible: true }, + facility: { size: 'cell-m', visible: true }, + detector: { size: 'cell-s', visible: true }, + partition: { size: 'cell-m', visible: true }, + run: { size: 'cell-s', visible: true }, + errcode: { size: 'cell-s', visible: false }, + errline: { size: 'cell-s', visible: false }, + errsource: { size: 'cell-m', visible: false }, + message: { size: 'cell-xl', visible: true }, }; - const columns = await page.evaluate(() => { - return window.model.table.colsHeader; - }); + const columns = await page.evaluate(() => window.model.table.colsHeader); assert.deepStrictEqual(columns, expectedColumns); }); it('should update filters based on profile when passed in the URI', async () => { - // for now check if the filters are reset once the profile is passed + // for now check if the filters are reset once the profile is passed const expectedParams = '?q={%22severity%22:{%22in%22:%22I%20W%20E%20F%22}}'; const searchParams = await page.evaluate(() => { - const params = {profile: 'physicist'}; + const params = { profile: 'physicist' }; window.model.parseLocation(params); return window.location.search; }); - await page.waitForFunction(`window.model.notification.state === 'shown'`); - await page.waitForFunction(`window.model.notification.type === 'success'`); - await page.waitForFunction(`window.model.notification.message === "The profile PHYSICIST was loaded successfully"`); + await page.waitForFunction('window.model.notification.state === \'shown\''); + await page.waitForFunction('window.model.notification.type === \'success\''); + await page.waitForFunction('window.model.notification.message === "The profile PHYSICIST was loaded successfully"'); assert.strictEqual(searchParams, expectedParams); }); it('should reset filters and show warning message when profile and filters are passed', async () => { // wait until the previous notification is hidden - await page.waitForFunction(`window.model.notification.state === 'hidden'`); + await page.waitForFunction('window.model.notification.state === \'hidden\''); const expectedParams = '?q={%22severity%22:{%22in%22:%22I%20W%20E%20F%22}}'; const searchParams = await page.evaluate(() => { - const params = {profile: "physicist", q: '"severity":{"in":"I W E F"}}'}; + const params = { profile: 'physicist', q: '"severity":{"in":"I W E F"}}' }; window.model.parseLocation(params); return window.location.search; }); - await page.waitForFunction(`window.model.notification.state === 'shown'`); - await page.waitForFunction(`window.model.notification.type === 'warning'`); - await page.waitForFunction(`window.model.notification.message === "URL can contain only filters or profile, not both"`); + await page.waitForFunction('window.model.notification.state === \'shown\''); + await page.waitForFunction('window.model.notification.type === \'warning\''); + await page.waitForFunction('window.model.notification.message === "URL can contain only filters or profile, not both"'); assert.strictEqual(searchParams, expectedParams); }); it('should update URI with new encoded "match" criteria', async () => { - /* eslint-disable max-len */ const decodedParams = '?q={"hostname":{"match":"\\"%ald_qdip01%"},"severity":{"in":"I W E F"}}'; const expectedParams = '?q={%22hostname%22:{%22match%22:%22%5C%22%25ald_qdip01%25%22},%22severity%22:{%22in%22:%22I%20W%20E%20F%22}}'; const searchParams = await page.evaluate(() => { window.model.log.filter.setCriteria('hostname', 'match', '"%ald_qdip01%'); - window.model.updateRouteOnModelChange(); return window.location.search; }); @@ -108,13 +103,11 @@ describe('Filter actions test-suite', async () => { }); it('should update URI with new encoded "exclude" criteria', async () => { - /* eslint-disable max-len */ const decodedParams = '?q={"hostname":{"exclude":"\\"%ald_qdip01%"},"severity":{"in":"I W E F"}}'; const expectedParams = '?q={%22hostname%22:{%22exclude%22:%22%5C%22%25ald_qdip01%25%22},%22severity%22:{%22in%22:%22I%20W%20E%20F%22}}'; const searchParams = await page.evaluate(() => { window.model.log.filter.resetCriteria(); window.model.log.filter.setCriteria('hostname', 'exclude', '"%ald_qdip01%'); - window.model.updateRouteOnModelChange(); return window.location.search; }); @@ -204,5 +197,4 @@ describe('Filter actions test-suite', async () => { assert.strictEqual(criterias.severity.in, 'I W E F'); assert.deepStrictEqual(criterias.severity.$in, ['W', 'I', 'E', 'F']); }); - });