diff --git a/common/constants.js b/common/constants.js index c25f0fef31143d4a3fa6d7b2cd87a9c619c2da0b..e30caaa6ac365ed3e0ad5780d93070a2357776f6 100644 --- a/common/constants.js +++ b/common/constants.js @@ -67,6 +67,8 @@ ATLAS_NOT_FOUND: `Atlas not found. Maybe it is still loading. Try again in a few seconds?`, TEMPLATE_NOT_FOUND: `Template not found. Maybe it is still loading. Try again in a few seconds?`, - PARC_NOT_FOUND: `` + PARC_NOT_FOUND: ``, + + PINNED_DATASETS_BADGE_DESC: `Number of pinned datasets` } })(typeof exports === 'undefined' ? module.exports : exports) diff --git a/e2e/src/advanced/favDatasets.prod.e2e-spec.js b/e2e/src/advanced/favDatasets.prod.e2e-spec.js index c745200e50d1e67042f920e18b10d49b668dadbf..9cb93907a73c446fbbf63d40a7968b2e1248dfa3 100644 --- a/e2e/src/advanced/favDatasets.prod.e2e-spec.js +++ b/e2e/src/advanced/favDatasets.prod.e2e-spec.js @@ -1,7 +1,14 @@ const { AtlasPage } = require('../util') -const { ARIA_LABELS } = require('../../../common/constants') +const { ARIA_LABELS, CONST } = require('../../../common/constants') +const { retry } = require('../../../common/util') + +const atlasName = `Multilevel Human Atlas` + +const templates = [ + 'MNI Colin 27', + 'ICBM 152 2009c Nonlinear Asymmetric' +] -const template = 'ICBM 2009c Nonlinear Asymmetric' const area = 'Area hOc1 (V1, 17, CalcS)' const receptorName = `Density measurements of different receptors for Area hOc1 (V1, 17, CalcS) [human, v1.0]` @@ -9,51 +16,43 @@ const pmapName = `Probabilistic cytoarchitectonic map of Area hOc1 (V1, 17, Calc // TODO finish writing tests describe(`fav'ing dataset`, () => { - let iavPage + let iavPage = new AtlasPage() beforeEach(async () => { iavPage = new AtlasPage() await iavPage.init() await iavPage.goto() - await iavPage.selectTitleCard(template) - await iavPage.wait(500) - await iavPage.waitUntilAllChunksLoaded() - }) + await iavPage.setAtlasSpecifications(atlasName, [ templates[1] ]) - afterEach(async () => { - await iavPage.clearAlerts() - await iavPage.wait(500) + // account for linear template translation backend + await iavPage.wait(5000) + await iavPage.waitUntilAllChunksLoaded() - try { - await iavPage.clearSearchRegionWithText() - await iavPage.wait(500) - await iavPage.clearAllSelectedRegions() - }catch(e) { - console.warn(`#afterEach error: clearing text field`, e) - } + await iavPage.searchRegionWithText(area) + await iavPage.wait(2000) + await iavPage.selectSearchRegionAutocompleteWithText() + await retry(async () => { + await iavPage.dismissModal() + await iavPage.toggleExpansionPanelState(`${CONST.REGIONAL_FEATURES}`, true) + }, { + timeout: 2000, + retries: 10 + }) - try { - await iavPage.showPinnedDatasetPanel() - const textsArr = await iavPage.getBottomSheetList() - let length = textsArr.length - while(length > 0){ - await iavPage.clickNthItemFromBottomSheetList(0, `[aria-label="Toggle pinning this dataset"]`) - length -- - } - }catch(e){ - console.warn(`#afterEach error: unfav all`, e) - } + await iavPage.wait(1000) + await iavPage.waitUntilAllChunksLoaded() + await iavPage.clearAlerts() + }) - await iavPage.wait(500) + afterEach(async () => { + /** + * clear all fav'ed datasets + */ + + await iavPage.execScript(`window.localStorage.clear()`) }) it('> dataset can be fav ed from result panel', async () => { - await iavPage.searchRegionWithText(area) - await iavPage.wait(2000) - await iavPage.selectSearchRegionAutocompleteWithText() - await iavPage.dismissModal() - await iavPage.searchRegionWithText('') - const datasets = await iavPage.getVisibleDatasets() const receptorIndex = datasets.indexOf(receptorName) @@ -75,12 +74,6 @@ describe(`fav'ing dataset`, () => { describe('> fav dataset list', () => { beforeEach(async () => { - await iavPage.searchRegionWithText(area) - await iavPage.wait(2000) - await iavPage.selectSearchRegionAutocompleteWithText() - await iavPage.dismissModal() - await iavPage.searchRegionWithText('') - const datasets = await iavPage.getVisibleDatasets() const receptorIndex = datasets.indexOf(receptorName) @@ -91,18 +84,8 @@ describe(`fav'ing dataset`, () => { }) it('> fav ed dataset is visible on UI', async () => { - const number = await iavPage.getNumberOfFavDataset() - expect(number).toEqual(2) - }) - - it('> clicking pin shows pinned datasets', async () => { - await iavPage.showPinnedDatasetPanel() - await iavPage.wait(500) - const textsArr = await iavPage.getBottomSheetList() - - expect(textsArr.length).toEqual(2) - expect(textsArr).toContain(receptorName) - expect(textsArr).toContain(pmapName) + const content = await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content).toEqual('2') }) it('> click unpin in fav data panel unpins, but also allow user to undo', async () => { @@ -117,15 +100,15 @@ describe(`fav'ing dataset`, () => { const txt = await iavPage.getSnackbarMessage() expect(txt).toEqual(`Unpinned dataset: ${receptorName}`) - const number = await iavPage.getNumberOfFavDataset() - expect(number).toEqual(1) + const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content).toEqual('1') await iavPage.clickSnackbarAction() await iavPage.wait(500) const textsArr3 = await iavPage.getBottomSheetList() - const number2 = await iavPage.getNumberOfFavDataset() - expect(number2).toEqual(2) + const content2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content2).toEqual('2') expect( textsArr3.indexOf(receptorName) ).toBeGreaterThanOrEqual(0) @@ -139,18 +122,8 @@ describe(`fav'ing dataset`, () => { }) describe('> fav functionality in detailed dataset panel', () => { - beforeEach(async () => { - - await iavPage.searchRegionWithText(area) - await iavPage.wait(2000) - await iavPage.selectSearchRegionAutocompleteWithText() - await iavPage.dismissModal() - await iavPage.searchRegionWithText('') - - }) it('> click pin in dataset detail sheet pins fav, but also allows user to undo', async () => { - const datasets = await iavPage.getVisibleDatasets() const receptorIndex = datasets.indexOf(receptorName) @@ -158,20 +131,20 @@ describe(`fav'ing dataset`, () => { await iavPage.wait(500) // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test - await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`) + await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`) await iavPage.wait(500) const txt = await iavPage.getSnackbarMessage() expect(txt).toEqual(`Pinned dataset: ${receptorName}`) - const number = await iavPage.getNumberOfFavDataset() - expect(number).toEqual(1) + const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content).toEqual('1') await iavPage.clickSnackbarAction() await iavPage.wait(500) - const number2 = await iavPage.getNumberOfFavDataset() - expect(number2).toEqual(0) + const text = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(text).toBeFalsy() }) it('> click unpin in dataset detail sheet unpins fav, but also allows user to undo', async () => { @@ -183,31 +156,96 @@ describe(`fav'ing dataset`, () => { await iavPage.wait(500) // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test - await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`) + await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`) await iavPage.wait(500) - const numberOfFav = await iavPage.getNumberOfFavDataset() - expect(numberOfFav).toEqual(1) + const numberOfFav = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(numberOfFav).toEqual('1') // this wait is unfortunately necessary, as the snack bar sometimes obscures the unpin this dataset button await iavPage.wait(5000) // specificity is required, because single dataset card for julich brain also can be selected, and will be clicked and fail this test - await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`) + await iavPage.click(`[aria-label="${ARIA_LABELS.PIN_DATASET}"]`) await iavPage.wait(500) const txt = await iavPage.getSnackbarMessage() expect(txt).toEqual(`Unpinned dataset: ${receptorName}`) - const numberOfFav1 = await iavPage.getNumberOfFavDataset() - expect(numberOfFav1).toEqual(0) - + const text = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(text).toBeFalsy() + await iavPage.clickSnackbarAction() await iavPage.wait(500) + const numberOfFav2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(numberOfFav2).toEqual('1') + }) + + }) + + describe('> access via collection', () => { + beforeEach(async () => { + + const datasets = await iavPage.getVisibleDatasets() + + const receptorIndex = datasets.indexOf(receptorName) + const probMap = datasets.indexOf(pmapName) + + await iavPage.togglePinNthDataset(receptorIndex) + await iavPage.togglePinNthDataset(probMap) + }) + + it('> clicking pin shows collection of pinned datasets', async () => { + + await iavPage.showPinnedDatasetPanel() + await iavPage.wait(500) + const textsArr = await iavPage.getBottomSheetList() + + expect(textsArr.length).toEqual(2) + expect(textsArr).toContain(receptorName) + expect(textsArr).toContain(pmapName) + }) + + it('> dataset detail can be launched via collection', async () => { + await iavPage.showPinnedDatasetPanel() + const textsArr = await iavPage.getBottomSheetList() + const idx = textsArr.findIndex(t => t === receptorName) + expect(idx).toBeGreaterThanOrEqual(0) + await iavPage.clickNthItemFromBottomSheetList(idx) + await iavPage.wait(1000) + const modalText = await iavPage.getModalText() + expect(modalText.length).toBeGreaterThan(1e3) + }) + + it('> dataset can be pinned/unpinned via collection', async () => { + await iavPage.showPinnedDatasetPanel() + const textsArr = await iavPage.getBottomSheetList() + const idx = textsArr.findIndex(t => t === receptorName) + await iavPage.clickNthItemFromBottomSheetList(idx) + await iavPage.wait(1000) + + /** + * for now, from collection, a modal is launched + */ + await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`) + await iavPage.wait(1000) + const txt = await iavPage.getSnackbarMessage() + expect(txt).toEqual(`Unpinned dataset: ${receptorName}`) + + const content = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content).toEqual('1') + + await iavPage.wait(5000) + + await iavPage.click(`mat-dialog-container [aria-label="${ARIA_LABELS.PIN_DATASET}"]`) + await iavPage.wait(1000) + const txt2 = await iavPage.getSnackbarMessage() + expect(txt2).toEqual(`Pinned dataset: ${receptorName}`) + + const content2 = await await iavPage.getBadgeContentByDesc(CONST.PINNED_DATASETS_BADGE_DESC) + expect(content2).toEqual('2') - const numberOfFav2 = await iavPage.getNumberOfFavDataset() - expect(numberOfFav2).toEqual(1) }) }) }) diff --git a/e2e/util/selenium/layout.js b/e2e/util/selenium/layout.js index e4a01a62771f10ad11e7b82643392c0bc6f8ae81..dd52470db14b26fc25941e0bb70977c28feb36fb 100644 --- a/e2e/util/selenium/layout.js +++ b/e2e/util/selenium/layout.js @@ -293,6 +293,34 @@ class WdLayoutPage extends WdBase{ return txtArr } + /** + * Badge + */ + async getBadgeContentByDesc(description){ + const els = await this._browser.findElements( + By.css(`.mat-badge-content`) + ) + for (const el of els) { + const descById = await el.getAttribute('aria-describedby') + if (!!descById) { + const descEl = await this._browser.findElement( + By.id(`${descById}`) + ) + /** + * getText() will not return elements that are hidden + * which aria descriptions are. + * so use getInnerHtml instead + */ + const descElText = await descEl.getAttribute('innerHTML') + if (descElText === description) { + const elText = await el.getText() + return elText + } + } + } + return null + } + /** * Other */ diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html index d6ebc5aa1d406650a95e42f7bf40db960559b024..54e8c9e7be8ed518ad053151e79b6e1f12cfb574 100644 --- a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html +++ b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html @@ -88,7 +88,7 @@ <!-- pin data --> <ng-container *ngIf="downloadEnabled && kgId"> - <ng-container *ngTemplateOutlet="favDatasetBtn; context: { $implicit: (favedDataentries$ | async | datasetIsFaved : dataset) }"> + <ng-container *ngTemplateOutlet="favDatasetBtn; context: { $implicit: (favedDataentries$ | async | datasetIsFaved : ({ fullId: fullId })) }"> </ng-container> <ng-template #favDatasetBtn let-isFav> diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/signinBanner/signinBanner.components.ts index 524c174d1cdfe97166337266eef2359783c9786f..9c823d35fbd4ee77f8ff656b43f2b87e16ff2816 100644 --- a/src/ui/signinBanner/signinBanner.components.ts +++ b/src/ui/signinBanner/signinBanner.components.ts @@ -12,8 +12,9 @@ import { Observable } from "rxjs"; import { map } from "rxjs/operators"; import { AuthService } from "src/auth"; import { IavRootStoreInterface, IDataEntry } from "src/services/stateStore.service"; -import {MatDialog, MatDialogConfig, MatDialogRef} from "@angular/material/dialog"; -import {MatBottomSheet} from "@angular/material/bottom-sheet"; +import { MatDialog, MatDialogConfig, MatDialogRef } from "@angular/material/dialog"; +import { MatBottomSheet } from "@angular/material/bottom-sheet"; +import { CONST } from 'common/constants' @Component({ selector: 'signin-banner', @@ -27,6 +28,8 @@ import {MatBottomSheet} from "@angular/material/bottom-sheet"; export class SigninBanner { + public PINNED_DATASETS_BADGE_DESC = CONST.PINNED_DATASETS_BADGE_DESC + public matBtnStyle = '' public matBtnColor = 'primary' diff --git a/src/ui/signinBanner/signinBanner.template.html b/src/ui/signinBanner/signinBanner.template.html index 1e50eac2aa5723b442cdcc1d9c217f584f35eb04..ae9fe7663c001f81f708fc4f296fdc5a691a42d4 100644 --- a/src/ui/signinBanner/signinBanner.template.html +++ b/src/ui/signinBanner/signinBanner.template.html @@ -106,6 +106,7 @@ [matBadge]="(favDataEntries$ | async)?.length > 0 ? (favDataEntries$ | async)?.length : null " matBadgeColor="accent" matBadgePosition="above after" + [matBadgeDescription]="PINNED_DATASETS_BADGE_DESC" matTooltip="Pinned datasets"> <iav-dynamic-mat-button [attr.pinned-datasets-length]="(favDataEntries$ | async)?.length"