From 8055d95fc140961cf5e636e86029fe3f8c71a384 Mon Sep 17 00:00:00 2001 From: Adam G-H <32250-phenaproxima@users.noreply.drupalcode.org> Date: Mon, 27 Jan 2025 21:55:10 +0000 Subject: [PATCH] Issue #3502612 by phenaproxima, lostcarpark: Normalize treatment of filters on the front end --- .../ProjectBrowserSource/RandomDataPlugin.php | 6 +- .../DrupalDotOrgJsonApi.php | 6 +- sveltejs/public/build/bundle.js | Bin 298510 -> 297852 bytes sveltejs/public/build/bundle.js.map | Bin 272414 -> 272084 bytes sveltejs/src/ProjectBrowser.svelte | 32 +------ sveltejs/src/Search/BooleanFilter.svelte | 10 +- sveltejs/src/Search/Search.svelte | 90 +++++++++++++----- .../ProjectBrowserTestMock.php | 6 +- .../ProjectBrowserPluginTest.php | 10 +- .../ProjectBrowserUiTest.php | 8 +- .../ProjectBrowserUiTestJsonApi.php | 14 +-- .../Nightwatch/Tests/consistentPagination.js | 12 ++- 12 files changed, 109 insertions(+), 85 deletions(-) diff --git a/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php b/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php index 7b4a9cc65..e673b6159 100644 --- a/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php +++ b/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php @@ -130,21 +130,21 @@ final class RandomDataPlugin extends ProjectBrowserSourceBase { ); $filters['categories'] = new MultipleChoiceFilter($choices, [], $this->t('Categories'), NULL); - $filters['securityCoverage'] = new BooleanFilter( + $filters['security_advisory_coverage'] = new BooleanFilter( TRUE, $this->t('Show projects covered by a security policy'), $this->t('Show all'), $this->t('Security advisory coverage'), NULL, ); - $filters['maintenanceStatus'] = new BooleanFilter( + $filters['maintenance_status'] = new BooleanFilter( TRUE, $this->t('Show actively maintained projects'), $this->t('Show all'), $this->t('Maintenance status'), NULL, ); - $filters['developmentStatus'] = new BooleanFilter( + $filters['development_status'] = new BooleanFilter( FALSE, $this->t('Show projects under active development'), $this->t('Show all'), diff --git a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php index c08960d57..7db69d4d3 100644 --- a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php +++ b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php @@ -245,21 +245,21 @@ final class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase { ); $filters['categories'] = new MultipleChoiceFilter($choices, [], $this->t('Categories'), NULL); - $filters['securityCoverage'] = new BooleanFilter( + $filters['security_advisory_coverage'] = new BooleanFilter( TRUE, $this->t('Show projects covered by a security policy'), $this->t('Show all'), $this->t('Security advisory coverage'), NULL, ); - $filters['maintenanceStatus'] = new BooleanFilter( + $filters['maintenance_status'] = new BooleanFilter( TRUE, $this->t('Show actively maintained projects'), $this->t('Show all'), $this->t('Maintenance status'), NULL, ); - $filters['developmentStatus'] = new BooleanFilter( + $filters['development_status'] = new BooleanFilter( FALSE, $this->t('Show projects under active development'), $this->t('Show all'), diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js index bc859d827ffe464d75d3ff368bc30e0908766fd2..5cfe970d1bd668fb2a2e64351ac7a2cc9a8df694 100644 GIT binary patch delta 2635 zcma)8du&rx7|(ZmVC%-_927EP?hF>!&bsZkT{lLCn}Dy$P{u=nIxppRyU_NQdv6Ez zg<uekO2jH(d?h3Lhek+77C0n?$4GocV+?BI>mMJ98cmEEBm%-b=iavNL5xk>d+#~t zd;Naj_q*NuYUSViD~G$!5lge;BR%Klfh(ybvWY)`$z7{(Xr|;wUHn{m8H(}LJ}An* zc>aE|KXU&32T;y$)P^P+wYIO9BN0?C!%ZWX{_1x;sTXgsJ?*{dx34EIdh^d^bule& zsfOvNB4+KS4%?@4=_Q!nPDMi53x97BYq)if<jFpKIba_+e7V~3efCOCr3g+tXkA^( z&{JlkIQ&{nx(<g*Nl|ven8!9h)e2Qkg=@#Wj_o(c<{x<j&MlXMLA?1*R}=32l~;Ij zE~&updf*NSqkjdgaRr(~Z1)P-MO=Yk8<wnsk9_8UzO7G-^~pSJQ^SB_-fCB|Mv13Y zGmnED@%r%efK;{EIh{Yd+Ek6MR4T5in;f%(MUY!8Dxv)2j;j_m)u^TENj!7`=HX8R zQW^Vw6_iTuLUgQs4`$=RekjXEKCURrt&7!J`1QS@6^A0;L6H;gtZ~g^58MaaL28L$ zZLiCV+rM#Dvzqnryi}AA)HTKpsYkk&or%DqV!ZM?6p=pJN3$Egpk-Q&dUGN8O8Hlm z-Lo0ak)lvrdrOOt;@J^b4cnqa1&}~<#EZ=a%wpLT^t+@$GgkMI`FOnrw@9G?ZnWTA zkD#rc!zZpe%z|Nde;O{q>>Q<&H`Ci-Kez%R8Ot*u3trjn8QAES!Y%CJF4$Tug~M3$ zG#s82;OI9sL={Wz*NsfxeGq?q8Xn_(Gwm682gFVDUicZR+vIjR;G+*M;6+ZNlan~Q z)>X^Ccn;2j6bRro`{Cq%7ff5Quz7;fR9?C1*2Nr@zzgs-Hw`jwdZ7f`@SZ9Tbj=Jt zN-xcT87LosIk3=PWsw8$eo=9&pVpbWVc}4eG~tG~pq^Xpi;_C_=3DRzKnr&ClLnT2 z8#LfU;ii_}t13ox;BLiG5~i1z;`EU_swYj0rtqoFWF9_#6jm>HRvw~#Rwkv=M|fLq zQe#?D6TOz}KDXU}cI$}2%FXC{!AfLNNzSudGz9K@5Inef7)m;un&=WeIj9;I&xY2^ z^;9=#eRF+d{=7TyuqU0^s2Wad`WkuamZ2s4accv3T2pobjizdOML0jTjq+pReuUrU z{28j1Hj>maKsiGw{x(QvvnvN7RE$I2;4U@Pn4y{j0uH3R$sBz27}Vj7N1#$!s#<)! zOv;O}22?|(iufioG*>KDoDrppMU{BmDS|dMIl*J;q&=Hco23AJRwgqW9cN1m_?o^( zQ%|UNX|!YUBxvz?hRog3tMasX$U-I@O@+pkxS4Ul$me3GLK|pTj4LRwLgUq#G|ElY zP5!H7woT(sbEpY-YTnU=qO!}sEiTOolMUPxM`2~de>Y8@;Rzk#$1w)Q)9gq%It+91 zv<d__FsR2LhGD+FEv=7;z1!>ul1#_r;?aX0hxu@HF5`N<ryHv9!wf0iF_AKw<~mBF z14^=A-87Cl2P2cl3_T&J)eO<!N;+<F@N<w&C|FMltgbe_1ukvSq$I^>kHY*;n?bKV z4gPVn6Y))Dl-72PAFoD7jXBNLc=HihzQdtTP{s$qrqCwts>%F6`gk?G<yC7OgE@9q zY~0K{zEMr`X;V$FXiXeC%5~*Si(HGpGN{T{@2L>*&%~NzP>N4>LoFLQ2H#27MB`jt z3N9C+zLQkp*iJHyy?dNXGJjP@PCz%8rQdcDAN%A4^g-t&9rfqZ81E{-c2)e*cM2Aj zPZTz`;S_u?!gY>v$!x)UN5NY;@kl$BTXAp{o||Nf<!9h}Np9Wq$0+cx#Qqp{tyw3@ zE$q&D<YywuAr`JB6-830jot1gWSSHXv7VbqiAxFx*}7)(xl3vdv0#XV%BF`Fwuksj z@b@zwwyTST%cjf!E_~WU#)uSZWuNtu1G9J7uk)M?o8vT^3#;?EL{FsjB&S6v;kW~Z z{{rsuX0|fcr<8uR-cS3)wV;htkHxiwq**vTNIbn$cf|{aJF#Ch|KY^c(?(Q8Te|Gl huGM#~>g!#xdgYR3eRnKH&la){Pnu*pJDwoD^dD_pZvg-R delta 2863 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 diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map index 7efeb3c7162edf6e7a6e9f71ca18a1465f4acdd6..d12b193f55d82ab6fae62b40b29726e517643db7 100644 GIT binary patch delta 3030 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 delta 3532 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 diff --git a/sveltejs/src/ProjectBrowser.svelte b/sveltejs/src/ProjectBrowser.svelte index 0847dd26c..a7fa549c8 100644 --- a/sveltejs/src/ProjectBrowser.svelte +++ b/sveltejs/src/ProjectBrowser.svelte @@ -71,36 +71,14 @@ */ async function load(_page) { loading = true; - const searchParams = new URLSearchParams({ - page: _page, - limit: $pageSize, - sort: $sort, - source: DEFAULT_SOURCE_ID, - }); + const searchParams = searchComponent.toSearchParams(); + searchParams.set('page', _page); + searchParams.set('limit', $pageSize); + searchParams.set('sort', $sort); + searchParams.set('source', DEFAULT_SOURCE_ID); if (searchText) { searchParams.set('search', searchText); } - if ($filters.categories && $filters.categories.length) { - searchParams.set('categories', $filters.categories); - } - if ('developmentStatus' in $filters) { - searchParams.set( - 'development_status', - Number($filters.developmentStatus).toString(), - ); - } - if ('maintenanceStatus' in $filters) { - searchParams.set( - 'maintenance_status', - Number($filters.maintenanceStatus).toString(), - ); - } - if ('securityCoverage' in $filters) { - searchParams.set( - 'security_advisory_coverage', - Number($filters.securityCoverage).toString(), - ); - } const url = `${BASE_URL}project-browser/data/project?${searchParams.toString()}`; diff --git a/sveltejs/src/Search/BooleanFilter.svelte b/sveltejs/src/Search/BooleanFilter.svelte index 8cd94aee4..15c2cb66c 100644 --- a/sveltejs/src/Search/BooleanFilter.svelte +++ b/sveltejs/src/Search/BooleanFilter.svelte @@ -3,18 +3,18 @@ export let definition; - const { name, on_label: onLabel, off_label: offLabel } = definition; + const { name: title, on_label: onLabel, off_label: offLabel } = definition; export let changeHandler; - export let type; + export let name; </script> <div class="filter-group__filter-options form-item"> - <label for={type} class="form-item__label">{name}</label> + <label for={name} class="form-item__label">{title}</label> <select - name={type} + {name} class="search__filter-select form-select form-element form-element--type-select" - bind:value={$filters[type]} + bind:value={$filters[name]} on:change={changeHandler} > <option value={true}>{onLabel}</option> diff --git a/sveltejs/src/Search/Search.svelte b/sveltejs/src/Search/Search.svelte index c94700997..b7f127b5d 100644 --- a/sveltejs/src/Search/Search.svelte +++ b/sveltejs/src/Search/Search.svelte @@ -33,6 +33,22 @@ export let filterDefinitions; + export function toSearchParams() { + const params = new URLSearchParams(); + + Object.entries(filterDefinitions).forEach(([name, definition]) => { + const { _type } = definition; + let value = $filters[name]; + + if (_type === 'boolean') { + // Convert to '1' or '0'. + value = Number(value).toString(); + } + params.set(name, value); + }); + return params; + } + export async function onSearch(event) { const state = stateContext.getState(); const detail = { @@ -107,32 +123,58 @@ document.getElementById('pb-text').focus(); } + function refresh() { + onAdvancedFilter(); + onSelectCategory(); + } + /** - * Resets the filters to the initial values provided by the source. + * Detects if there are any filters applied at all. + */ + function hasFilterValues() { + return Object.keys(filterDefinitions).some((name) => $filters[name]); + } + + /** + * Sets all filters to a falsy value. * - * @param {boolean} clear - * Whether to clear all filter values (i.e., not reset them to their defaults, - * but actually negate them all). + * After this is called, hasFilterValues() will return false. */ - const resetFilters = (clear) => { - $filters = {}; + function clearFilters() { Object.entries(filterDefinitions).forEach(([name, definition]) => { - let value; - if (clear) { - if (definition._type === 'boolean') { - value = false; - } else if (definition._type === 'multiple_choice') { - value = []; - } + const { _type } = definition; + + if (_type === 'boolean') { + $filters[name] = false; + } else if (_type === 'multiple_choice') { + $filters[name] = []; } else { - value = definition.value; + $filters[name] = null; } - $filters[name] = value; }); - $filters.categories = []; - onAdvancedFilter(); - onSelectCategory(); - }; + refresh(); + } + + /** + * Detects if the user changed any filter values from their defaults). + */ + function hasUserAppliedFilters() { + return Object.entries(filterDefinitions).some( + ([name, definition]) => $filters[name] !== definition.value, + ); + } + + /** + * Resets the filters to the initial values provided by the source. + * + * After calling this, hasUserAppliedFilters() will return false. + */ + function resetFilters() { + Object.entries(filterDefinitions).forEach(([name, definition]) => { + $filters[name] = definition.value; + }); + refresh(); + } </script> <form class="search__form-container"> @@ -196,11 +238,11 @@ {#if Object.keys(filterDefinitions).length !== 0} <div class="search__form-filters-container"> <div class="search__form-filters"> - {#each Object.entries(filterDefinitions) as [filterType, filter]} + {#each Object.entries(filterDefinitions) as [name, filter]} {#if filter._type === 'boolean'} <BooleanFilter definition={filter} - type={filterType} + {name} changeHandler={onAdvancedFilter} /> {:else if filter._type === 'multiple_choice'} @@ -236,16 +278,16 @@ {/each} {/if} - {#if $filters.securityCoverage || $filters.maintenanceStatus || $filters.developmentStatus || ('categories' in $filters && $filters.categories.length)} + {#if hasFilterValues()} <button class="search__filter-button" type="button" - on:click|preventDefault={() => resetFilters(true)} + on:click|preventDefault={() => clearFilters()} > {Drupal.t('Clear filters')} </button> {/if} - {#if !($filters.maintenanceStatus && $filters.securityCoverage && !$filters.developmentStatus && 'categories' in $filters && $filters.categories.length === 0)} + {#if hasUserAppliedFilters()} <button class="search__filter-button" type="button" diff --git a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php index 248149b42..5064cf694 100644 --- a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php +++ b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php @@ -314,21 +314,21 @@ final class ProjectBrowserTestMock extends ProjectBrowserSourceBase { ); $filters['categories'] = new MultipleChoiceFilter($choices, [], $this->t('Categories'), NULL); - $filters['securityCoverage'] = new BooleanFilter( + $filters['security_advisory_coverage'] = new BooleanFilter( TRUE, $this->t('Show projects covered by a security policy'), $this->t('Show all'), $this->t('Security advisory coverage'), NULL, ); - $filters['maintenanceStatus'] = new BooleanFilter( + $filters['maintenance_status'] = new BooleanFilter( TRUE, $this->t('Show actively maintained projects'), $this->t('Show all'), $this->t('Maintenance status'), NULL, ); - $filters['developmentStatus'] = new BooleanFilter( + $filters['development_status'] = new BooleanFilter( FALSE, $this->t('Show projects under active development'), $this->t('Show all'), diff --git a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php index fbbc5ebba..6976e05ff 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php @@ -16,9 +16,9 @@ class ProjectBrowserPluginTest extends WebDriverTestBase { use ProjectBrowserUiTestTrait; // Could be moved into trait under PHP 8.3. - protected const SECURITY_OPTION_SELECTOR = 'select[name="securityCoverage"] '; - protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenanceStatus"] '; - protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="developmentStatus"] '; + protected const SECURITY_OPTION_SELECTOR = 'select[name="security_advisory_coverage"] '; + protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenance_status"] '; + protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="development_status"] '; protected const OPTION_CHECKED = 'option:checked'; protected const OPTION_FIRST_CHILD = 'option:first-child'; protected const OPTION_LAST_CHILD = 'option:last-child'; @@ -109,9 +109,9 @@ class ProjectBrowserPluginTest extends WebDriverTestBase { $page = $this->getSession()->getPage(); // Clear the security covered filter. - $page->selectFieldOption('securityCoverage', 'Show all'); + $page->selectFieldOption('security_advisory_coverage', 'Show all'); // Set the development status filter. - $page->selectFieldOption('developmentStatus', 'Show projects under active development'); + $page->selectFieldOption('development_status', 'Show projects under active development'); // Clear all filters. $this->pressWithWait('Clear filters'); diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php index c55a1c41e..d8b23783a 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php @@ -28,9 +28,9 @@ class ProjectBrowserUiTest extends WebDriverTestBase { use ProjectBrowserUiTestTrait; // Could be moved into trait under PHP 8.3. - protected const SECURITY_OPTION_SELECTOR = 'select[name="securityCoverage"] '; - protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenanceStatus"] '; - protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="developmentStatus"] '; + protected const SECURITY_OPTION_SELECTOR = 'select[name="security_advisory_coverage"] '; + protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenance_status"] '; + protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="development_status"] '; protected const OPTION_CHECKED = 'option:checked'; protected const OPTION_FIRST_CHILD = 'option:first-child'; protected const OPTION_LAST_CHILD = 'option:last-child'; @@ -391,7 +391,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { } // Click the Active filter. - $page->selectFieldOption('developmentStatus', 'Show projects under active development'); + $page->selectFieldOption('development_status', 'Show projects under active development'); $this->assertProjectsVisible([ 'Jazz', diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php index 7154f5b6c..fea509ddd 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php @@ -19,9 +19,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { use ProjectBrowserUiTestTrait; // Could be moved into trait under PHP 8.3. - protected const SECURITY_OPTION_SELECTOR = 'select[name="securityCoverage"] '; - protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenanceStatus"] '; - protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="developmentStatus"] '; + protected const SECURITY_OPTION_SELECTOR = 'select[name="security_advisory_coverage"] '; + protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenance_status"] '; + protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="development_status"] '; protected const OPTION_CHECKED = 'option:checked'; protected const OPTION_FIRST_CHILD = 'option:first-child'; protected const OPTION_LAST_CHILD = 'option:last-child'; @@ -241,7 +241,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $assert_session->pageTextNotContains(' 0 Results'); // Make sure the second filter applied is the security covered filter. - $this->assertTrue($assert_session->optionExists('securityCoverage', 'Show projects covered by a security policy')->isSelected()); + $this->assertTrue($assert_session->optionExists('security_advisory_coverage', 'Show projects covered by a security policy')->isSelected()); // Clear the security covered filter. $this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD); @@ -320,9 +320,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $this->pressWithWait('Recommended filters'); // Check that the actively maintained tag is present. - $this->assertTrue($assert_session->optionExists('maintenanceStatus', 'Show actively maintained projects')->isSelected()); + $this->assertTrue($assert_session->optionExists('maintenance_status', 'Show actively maintained projects')->isSelected()); // Make sure the second filter applied is the security covered filter. - $this->assertTrue($assert_session->optionExists('securityCoverage', 'Show projects covered by a security policy')->isSelected()); + $this->assertTrue($assert_session->optionExists('security_advisory_coverage', 'Show projects covered by a security policy')->isSelected()); $this->assertTrue($assert_session->waitForText(' Results')); $assert_session->pageTextNotContains(' 0 Results'); } @@ -347,7 +347,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { // Set the names of filters which will be defined by the test mock. // @see \Drupal\project_browser_test\Plugin\ProjectBrowserSource\ProjectBrowserTestMock::getFilterDefinitions() - $filters_to_define = ['maintenanceStatus', 'securityCoverage']; + $filters_to_define = ['maintenance_status', 'security_advisory_coverage']; \Drupal::state()->set('filters_to_define', $filters_to_define); $this->drupalGet('admin/modules/browse/project_browser_test_mock'); diff --git a/tests/src/Nightwatch/Tests/consistentPagination.js b/tests/src/Nightwatch/Tests/consistentPagination.js index ae5b707f7..c4ac5de11 100644 --- a/tests/src/Nightwatch/Tests/consistentPagination.js +++ b/tests/src/Nightwatch/Tests/consistentPagination.js @@ -12,8 +12,10 @@ module.exports = { .drupalRelativeURL('/admin/modules/browse/project_browser_test_mock') .waitForElementVisible('h1', 100) .assert.textContains('h1', 'Browse projects') - .click('select[name="securityCoverage"] option[value="false"]') - .click('select[name="maintenanceStatus"] option[value="false"]') + .click( + 'select[name="security_advisory_coverage"] option[value="false"]', + ) + .click('select[name="maintenance_status"] option[value="false"]') .assert.visible('select.pagination__num-projects') .click('select.pagination__num-projects option[value="24"]'); @@ -22,8 +24,10 @@ module.exports = { .drupalRelativeURL('/admin/modules/browse/project_browser_test_mock') .waitForElementVisible('h1', 100) .assert.textContains('h1', 'Browse projects') - .click('select[name="securityCoverage"] option[value="false"]') - .click('select[name="maintenanceStatus"] option[value="false"]') + .click( + 'select[name="security_advisory_coverage"] option[value="false"]', + ) + .click('select[name="maintenance_status"] option[value="false"]') .assert.visible('select.pagination__num-projects') .getValue('select.pagination__num-projects', function (result) { this.assert.strictEqual( -- GitLab