From 090c2fca6ca822d9d11815e0d131151905b23a35 Mon Sep 17 00:00:00 2001
From: xgui3783 <xgui3783@gmail.com>
Date: Thu, 2 Jul 2020 19:19:58 +0200
Subject: [PATCH] bump kgdsprv version (#572)

* fix region coloring

* update release notes

* Add test case to change template coloring bug #543

* small changes for fix bug #543

* Chore travisci (#548)

add travis ci

* fix travis e2e (#549)

* fix travis e2e test

* fix travis e2e

* debug travis e2e

* fix travis e2e

* Chore debug travis e2e (#551)

fix travis ci

* Update index.html (#571)

Co-authored-by: fsdavid <daviti1@mail.com>
---
 .travis.yml                                   | 102 ++++++++++++++++++
 deploy/datasets/testData/ibcDataExpected.js   |   3 +-
 deploy/server.js                              |   9 +-
 deploy/server.spec.js                         |  29 +++--
 docs/releases/v2.2.4.md                       |   7 ++
 e2e/protractor.conf.js                        |  94 +++++++++++++---
 .../advanced/nonAtlasImages.prod.e2e-spec.js  |   4 +-
 .../changeTemplate.prod.e2e-spec.js           |  34 +++++-
 .../mouseOverNehuba.prod.e2e-spec.js          |   8 +-
 e2e/src/util.js                               |  52 +++++----
 package.json                                  |   1 +
 src/index.html                                |   4 +-
 .../nehubaContainer.component.ts              |   7 +-
 .../splashScreen/splashScreen.template.html   |   2 +-
 14 files changed, 301 insertions(+), 55 deletions(-)
 create mode 100644 .travis.yml
 create mode 100644 docs/releases/v2.2.4.md

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..e9d1d40d2
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,102 @@
+language: node_js
+
+os: linux
+dist: xenial
+node_js:
+- 12
+
+git:
+  depth: 3
+
+# skipping install and script at root
+# as otherwise, travis will run npm install / npm test
+install: skip
+script: skip
+
+jobs:
+  include:
+    - stage: Unit tests and Lint
+      if: |
+        type = push AND \
+        branch NOT IN (master, staging, dev)
+      name: Unit test frontend / Lint
+      install:
+      - npm i
+      script:
+      - npm run lint
+      - npm test
+      env:
+      - NODE_ENV=test
+
+    - name: Unit test backend
+      if: |
+        type = push AND \
+        branch NOT IN (master, staging, dev)
+      before_install:
+      - cd deploy
+      install:
+      - npm i
+      script:
+      - npm test
+      env:
+      - NODE_ENV=test
+      - PORT=12234
+
+
+    # Temporarily disabling browserstack e2e tests. They seem to fail without any reason
+
+    # - stage: browserstack e2e
+    #   # only triggered via API, where env can be overwritten
+    #   if: NOT env(LOCAL_TEST_E2E) = 1
+    #   name: e2e (with browserstack)
+    #   install:
+    #   - npm i
+    #   script:
+    #   - PROTRACTOR_SPECS=./src/navigating/*.e2e-spec.js BROWSERSTACK_TEST_NAME=e2e_navigating npm run e2e
+    #   env:
+    #   - ATLAS_URL=https://interactive-viewer-next.apps-dev.hbp.eu/
+    #   - BROWSERSTACK_USERNAME=xiao33
+    #   - secure: "YD2hDBnWzcMs9mTJCsKkJimd+mYKP8V1lTaCnxNvspJUxTuBWFmr8cvryIs9G9DhwgxkC3YL7hugsGkwMg6OIq27vLlo8mgoKS7/qrkWAJApGvDW4jc4CHpI2iE/ryrwG1bI3u9TuG0kSw+2sN/786LBgArlf5NbmwB9zmW4zyzjXXzSME34cwYdfEP96L2cob/uGiIj9YdaA1k3zfBhQQlp328i/xzYbIAcwfIia1AKYh/wgCzj+yfWDQ0Rtg9VcI2JiNfcbzMCgvDEBzshgeXuubFd9GPqPsc8zJhYqAi/15ge+WiB8R50MnZsYHO39JJihQzKz6WxIZQDeOQ2xd600NhFFLg6WPdE3jxAyENouTAd+0zJgXEeUU71YBDBl6RViagf8k7eOe9oMPW5ZlevdD3vcI8BC/qUL6Evye8QDDNi0s8gbIvcnJl5QMRBpeYcm/QaRUow1YeJobpccj/3tb7qTbc7T4Rha/NRBNhbhp/WzDSO/BUSEtpgJ3YwSEPTiEeSocTRT8ylnhEtBB70h4vQSClV73lW4vn7WjdZUTRACdxFNJ1MteQJ+3bgzyWMhDtdQo6BSz2UxF0mQFayAu2p9j0+MbB7x2zW9tksSw+6B6EjzPhQw6eOs2K0+syxWg09MTW1Fy6n0Zgchn0RWSnEPqPvss6kB2pkAR4="
+
+env:
+  global:
+    - CHROMIUM_VERSION=80.0.3987.106
+    - PPTR_VERSION=2.1.0
+    - PROTRACTOR_SPECS=./src/navigating/*.e2e-spec.js
+
+# addons:
+#   browserstack:
+#     username: "xiao33"
+#     access_key:
+#       secure: "j0NdVLyNwm1gDclEeE/xYrXAYiYAlx3HQxNRHMFhJyFml5R22spEMTwrTRl/vzyhv1FwfJAKfh4qbOn99cZ5Dzm7fWc8+Kq1zpp/1PRTzbFaLluJkV1wCwoODZkzmSVPj43M6070FhCJvOfe5VRUV440CgZH8IWRm7xaxRnN/MVyFMErMV/GIczEBB7D7E4mMhe6c9pBxjmojDDP4rGvKLGOYU7oVQKgZtbHtP/BxjQ7uzMysdTHZGZ/2c/XW/2bKVSADi4vFzge5PMVF3nSH+vzA09ro180Q5aoaek4XQPoIza0s0cqtqkbvkbJ+lWRE+Q7wJDhQLM4WNx5GX3fegJiqJRT7272EgGAUy6C+e2F+D5nPucf3w6Uov9vBn5zZjbfXdNah3GZEXOTRNAVzstySiwiZe7/f4bk0vWIiEhHC+iutjn8skMxFnuw2eM3SJ5ayjxskHOdRux+1fuDya32ctx8y9a3XLhuFcuGTaeMSAn5Dw5qOlI5Qoc+xRSARoRWKmlEuxTUudD0e+b8xqfZgmOP7D3GZ6QX2W4yFrOLGqUzEySHr8hxxzhIlfwSvVdJ15AtN2AtPFQYQXb7M+XX1L7fr39Z/5ctr7DDgljSE3F2U5ofyWV2hh54aGMBQe76cZfVzF4bi98X3r6u0b3Knyti2pvx5jIoxP46nOA="
+
+
+# to run e2e tests, send API request with the following payload
+# {
+#  "request": {
+#  "message": "API request: e2e on deployed staging build",
+#  "branch":"chore_debugTravisE2e",
+#  "merge_mode": "deep_merge",
+#  "config": {
+#    "env": {
+#      "global": [
+#         "PROTRACTOR_SPECS=./src/navigating/*.e2e-spec.js",
+#         "CHROMIUM_VERSION=80.0.3987.106",
+#         "PPTR_VERSION=2.1.0"
+#      ],
+#      "jobs": [
+#        "ATLAS_URL=https://interactive-viewer-staging.apps.hbp.eu/",
+#        "ATLAS_URL=https://atlases.ebrains.eu/viewer-staging/"
+#      ]
+#    },
+#    "install": [
+#      "npm i",
+#      "npm run wd -- update --versions.chrome=${CHROMIUM_VERSION}",
+#      "npm i --no-save puppeteer@${PPTR_VERSION}"
+#    ],
+#    "script": [
+#      "echo Running e2e on $ATLAS_URL with protractor specs $PROTRACTOR_SPECS",
+#      "npm run e2e"
+#     ]
+#   }
+# }}
diff --git a/deploy/datasets/testData/ibcDataExpected.js b/deploy/datasets/testData/ibcDataExpected.js
index 24beaf359..0dfcc930b 100644
--- a/deploy/datasets/testData/ibcDataExpected.js
+++ b/deploy/datasets/testData/ibcDataExpected.js
@@ -40,8 +40,7 @@ module.exports = {
     {
       name: 'Jülich Cytoarchitechtonic Brain Atlas (human)',
       fullId:
-        'https://nexus.humanbrainproject.org/v0/data/minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579',
-      id: [Array]
+        'https://nexus.humanbrainproject.org/v0/data/minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579'
     }],
   parcellationRegion: [
     {
diff --git a/deploy/server.js b/deploy/server.js
index b803a0958..fdc0fbbbc 100644
--- a/deploy/server.js
+++ b/deploy/server.js
@@ -58,7 +58,6 @@ if (process.env.FLUENT_HOST) {
 
 const server = require('express')()
 
-const app = require('./app')
 const PORT = process.env.PORT || 3000
 
 // e.g. HOST_PATHNAME=/viewer
@@ -82,5 +81,9 @@ if (HOST_PATHNAME && HOST_PATHNAME !== '') {
   })
 }
 
-server.use(`${HOST_PATHNAME}/`, app)
-server.listen(PORT, () => console.log(`listening on port ${PORT}`))
\ No newline at end of file
+if (process.env.NODE_ENV !== 'test') {
+  const app = require('./app')
+  server.use(`${HOST_PATHNAME}/`, app)
+}
+
+server.listen(PORT, () => console.log(`listening on port ${PORT}`))
diff --git a/deploy/server.spec.js b/deploy/server.spec.js
index 502cce97c..6e8e36df8 100644
--- a/deploy/server.spec.js
+++ b/deploy/server.spec.js
@@ -1,8 +1,10 @@
 const { spawn } = require("child_process")
-const { expect } = require('chai')
+const { expect, assert } = require('chai')
 const path = require('path')
 const got = require('got')
 
+const PORT = process.env.PORT || 3000
+
 describe('> server.js', () => {
   const cwdPath = path.join(__dirname)
 
@@ -13,17 +15,19 @@ describe('> server.js', () => {
         cwd: cwdPath,
         env: {
           ...process.env,
+          NODE_ENV: 'test',
           HOST_PATHNAME: 'viewer'
         }
       })
   
       const timedKillSig = setTimeout(() => {
-        childProcess.kill(0)
+        childProcess.kill()
       }, 500)
       
       childProcess.on('exit', (code) => {
+        childProcess.kill()
         clearTimeout(timedKillSig)
-        expect(code).not.to.equal(0)
+        expect(code).to.be.greaterThan(0)
         done()
       })
     })
@@ -34,6 +38,7 @@ describe('> server.js', () => {
         cwd: cwdPath,
         env: {
           ...process.env,
+          NODE_ENV: 'test',
           HOST_PATHNAME: '/viewer/'
         }
       })
@@ -44,7 +49,7 @@ describe('> server.js', () => {
       
       childProcess.on('exit', (code) => {
         clearTimeout(timedKillSig)
-        expect(code).not.to.equal(0)
+        expect(code).to.be.greaterThan(0)
         done()
       })
     })
@@ -53,19 +58,23 @@ describe('> server.js', () => {
   
       const childProcess = spawn('node', ['server.js'],  {
         cwd: cwdPath,
+        stdio: 'inherit',
         env: {
           ...process.env,
+          NODE_ENV: 'test',
+          PORT,
           HOST_PATHNAME: '/viewer'
         }
       })
-  
+
       const timedKillSig = setTimeout(() => {
-        childProcess.kill(2)
+        console.log('killing on timeout')
+        childProcess.kill()
       }, 500)
       
-      childProcess.on('exit', (code) => {
+      childProcess.on('exit', (code, signal) => {
         clearTimeout(timedKillSig)
-        expect(code).to.equal(null)
+        expect(signal).to.equal('SIGTERM')
         done()
       })
     })
@@ -80,6 +89,8 @@ describe('> server.js', () => {
         cwd: cwdPath,
         env: {
           ...process.env,
+          NODE_ENV: 'test',
+          PORT,
           HOST_PATHNAME: '/viewer'
         }
       })
@@ -87,7 +98,7 @@ describe('> server.js', () => {
     })
   
     it('> redirects as expected', async () => {
-      const { statusCode } = await got(`http://localhost:3000/viewer`, {
+      const { statusCode } = await got(`http://localhost:${PORT}/viewer`, {
         followRedirect: false
       })
       expect(statusCode).to.be.greaterThan(300)
diff --git a/docs/releases/v2.2.4.md b/docs/releases/v2.2.4.md
new file mode 100644
index 000000000..d4931dc2c
--- /dev/null
+++ b/docs/releases/v2.2.4.md
@@ -0,0 +1,7 @@
+# v2.2.4
+
+15 June 2020
+
+## Bugfixes
+
+- Fixed parcellation region colors are invisible after template change when region selected #543
\ No newline at end of file
diff --git a/e2e/protractor.conf.js b/e2e/protractor.conf.js
index c04080983..4169f0e15 100644
--- a/e2e/protractor.conf.js
+++ b/e2e/protractor.conf.js
@@ -1,27 +1,24 @@
 
 // n.b. to start selenium, run npm run wd -- update && npm run wd -- start
 // n.b. you will need to run `npm i --no-save puppeteer`, so that normal download script does not download chrome binary
-const pptr = require('puppeteer')
 const chromeOpts = require('./chromeOpts')
 const SELENIUM_ADDRESS = process.env.SELENIUM_ADDRESS
 
-const PROD_FLAG = process.env.NODE_ENV === 'production'
+const bsTestname = process.env.BROWSERSTACK_TEST_NAME
+const bsUsername = process.env.BROWSERSTACK_USERNAME
+const bsAccessKey = process.env.BROWSERSTACK_ACCESS_KEY
+const directConnect = !!process.env.DIRECT_CONNECT
 
-exports.config = {
+const PROTRACTOR_SPECS = process.env.PROTRACTOR_SPECS
+
+const localConfig = bsUsername && bsAccessKey
+  ? {}
+  : {
   ...(SELENIUM_ADDRESS
     ? { seleniumAddress: SELENIUM_ADDRESS }
     : { directConnect: true } 
   ),
-  specs: [
-    PROD_FLAG
-      ? './src/**/*.prod.e2e-spec.js'
-      : './src/**/*.e2e-spec.js'
-  ],
-  jasmineNodeOpts: {
-    defaultTimeoutInterval: 1000 * 60 * 10
-  },
-  capabilities: { 
-
+  capabilities: {
     // Use headless chrome
     browserName: 'chrome',
     'goog:chromeOptions': {
@@ -31,8 +28,77 @@ exports.config = {
       ...(
         SELENIUM_ADDRESS
           ? {}
-          : { binary: pptr.executablePath() }
+          : { binary: (() => require('puppeteer').executablePath())() }
       )
     }
   }
+}
+
+
+const { Local } = require('browserstack-local');
+
+let bsLocal
+/**
+ * config adapted from
+ * https://github.com/browserstack/protractor-browserstack
+ * 
+ * MIT licensed
+ */
+const bsConfig = {
+  'browserstackUser': bsUsername,
+  'browserstackKey': bsAccessKey,
+  
+  'capabilities': {
+    'build': 'protractor-browserstack',
+    'name': bsTestname || 'iav_e2e',
+    "os" : "Windows",
+    "osVersion" : "10",
+    'browserName': 'chrome',
+    // 'browserstack.local': false,
+    "seleniumVersion" : "4.0.0-alpha-2",
+    'browserstack.debug': 'true'
+  },
+  "browserName" : "Chrome",
+  "browserVersion" : "83.0",
+
+  // // Code to start browserstack local before start of test
+  // beforeLaunch: function(){
+  //   console.log("Connecting local");
+  //   return new Promise(function(resolve, reject){
+  //     bsLocal = new Local();
+  //     bsLocal.start({'key': bsAccessKey }, function(error) {
+  //       if (error) return reject(error);
+  //       console.log('Connected. Now testing...');
+
+  //       resolve();
+  //     });
+  //   });
+  // },
+
+  // // Code to stop browserstack local after end of test
+  // afterLaunch: function(){
+  //   return new Promise(function(resolve, reject){
+  //     if (bsLocal) bsLocal.stop(resolve)
+  //     else resolve()
+  //   });
+  // }
+}
+
+exports.config = {
+  specs: [
+    (PROTRACTOR_SPECS && PROTRACTOR_SPECS) || './src/**/*.prod.e2e-spec.js'
+  ],
+  jasmineNodeOpts: {
+    defaultTimeoutInterval: 1000 * 60 * 10
+  },
+  
+  ...(
+    bsAccessKey && bsUsername
+    ? bsConfig
+    : localConfig
+  ),
+
+  ...(
+    (directConnect && { directConnect }) || {}
+  )
 }
\ No newline at end of file
diff --git a/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js b/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js
index 26bdfb011..71fc460e0 100644
--- a/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js
+++ b/e2e/src/advanced/nonAtlasImages.prod.e2e-spec.js
@@ -81,7 +81,7 @@ describe('> non-atlas images', () => {
       await iavPage.wait(10000)
       const interceptedCalls = await iavPage.getInterceptedHttpCalls()
 
-      const arr = [
+      const array = [
         'BI-FOM-HSV_R',
         'BI-FOM-HSV_G',
         'BI-FOM-HSV_B',
@@ -91,7 +91,7 @@ describe('> non-atlas images', () => {
         'BI-MRS',
       ]
 
-      for (const item of arr) {
+      for (const item of array) {
         expect(
           interceptedCalls.find(({
             method,
diff --git a/e2e/src/navigating/changeTemplate.prod.e2e-spec.js b/e2e/src/navigating/changeTemplate.prod.e2e-spec.js
index a1585c415..df74a6cbd 100644
--- a/e2e/src/navigating/changeTemplate.prod.e2e-spec.js
+++ b/e2e/src/navigating/changeTemplate.prod.e2e-spec.js
@@ -17,17 +17,49 @@ describe('trans template navigation', () => {
     await iavPage.goto(`/?${searchParam.toString()}`, { interceptHttp: true, doNotAutomate: true })
     await iavPage.wait(200)
     await iavPage.dismissModal()
+
     await iavPage.waitUntilAllChunksLoaded()
 
     await iavPage.selectDropdownTemplate('Big Brain (Histology)')
     await iavPage.wait(2000)
     const interceptedCalls = await iavPage.getInterceptedHttpCalls()
+    
+    expect(interceptedCalls).toBeTruthy()
 
-    const found = interceptedCalls.find(({ method, url }) => {
+    const found = interceptedCalls && interceptedCalls.find(({ method, url }) => {
       return method === 'POST' && /transform-points/.test(url)
     })
     expect(!!found).toBe(true)
   })
 
+  it('Check region color after template change when region was selected', async () => {
+
+    const url = '/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas'
+    const area = 'Area TE 3 (STG) - right hemisphere'
+    const expectedPosition = [630, 510]
+    const expectedColor = {red: 70, green: 139, blue: 57}
+
+    await iavPage.goto(url)
+
+    await iavPage.searchRegionWithText(area)
+    await iavPage.wait(1000)
+
+    await iavPage.selectSearchRegionAutocompleteWithText()
+    await iavPage.dismissModal()
+    await iavPage.wait(500)
+    await iavPage.selectDropdownTemplate('MNI Colin 27')
+    /**
+     * wait for template translate & js execution
+     */
+    await iavPage.wait(1000)
+    await iavPage.waitUntilAllChunksLoaded()
+    const actualColor = await iavPage.getRgbAt({ position: expectedPosition })
+
+    for (const key in actualColor) {
+      expect(Math.abs(actualColor[key] - expectedColor[key])).toBeLessThan(5)
+    }
+
+  })
+
   // TODO test that nav/zoom/orientation are actually preserved
 })
diff --git a/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js b/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js
index eaa2458b4..d446ea1ed 100644
--- a/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js
+++ b/e2e/src/navigating/mouseOverNehuba.prod.e2e-spec.js
@@ -97,8 +97,12 @@ const dictionary = {
           expectedLabelName: 'rh_SP-SM_0',
         },
         {
-          position: [642, 541],
-          expectedLabelName: 'lh_PoCi-PrCu_0',
+          /**
+           * Changed from [677, 579] as it is extremely unfortunate in that
+           * it is literally the connecting point between lh_CAC-PrCu_0 and lh_PoCi-PrCu_0
+           */
+          position: [677, 579],
+          expectedLabelName: 'lh_ST-TT_0',
         }
       ]
     }
diff --git a/e2e/src/util.js b/e2e/src/util.js
index c96a61803..217e00978 100644
--- a/e2e/src/util.js
+++ b/e2e/src/util.js
@@ -1,14 +1,15 @@
 const chromeOpts = require('../chromeOpts')
-const pptr = require('puppeteer')
+// const pptr = require('puppeteer')
 const ATLAS_URL = (process.env.ATLAS_URL || 'http://localhost:3000').replace(/\/$/, '')
 const USE_SELENIUM = !!process.env.SELENIUM_ADDRESS
 if (ATLAS_URL.length === 0) throw new Error(`ATLAS_URL must either be left unset or defined.`)
 if (ATLAS_URL[ATLAS_URL.length - 1] === '/') throw new Error(`ATLAS_URL should not trail with a slash: ${ATLAS_URL}`)
-const { By, WebDriver, Key } = require('selenium-webdriver')
+const { By, Key, until } = require('selenium-webdriver')
 const CITRUS_LIGHT_URL = `https://unpkg.com/citruslight@0.1.0/citruslight.js`
 const { polyFillClick } = require('./material-util')
 
 const { ARIA_LABELS } = require('../../common/constants')
+const { retry } = require('../../common/util')
 
 function getActualUrl(url) {
   return /^http\:\/\//.test(url) ? url : `${ATLAS_URL}/${url.replace(/^\//, '')}`
@@ -327,7 +328,7 @@ class WdBase{
   }
 
   // it seems if you set intercept http to be true, you might also want ot set do not automat to be true
-  async goto(url = '/', { interceptHttp, doNotAutomate, forceTimeout } = {}){
+  async goto(url = '/', { interceptHttp, doNotAutomate, forceTimeout = 20 * 1000 } = {}){
     const actualUrl = getActualUrl(url)
     if (interceptHttp) {
       this._browser.get(actualUrl)
@@ -356,7 +357,17 @@ class WdBase{
 
   async wait(ms) {
     if (!ms) throw new Error(`wait duration must be specified!`)
-    await this._browser.sleep(ms)
+    return new Promise(rs => {
+      setTimeout(rs, ms)
+    })
+  }
+
+  async waitForCss(cssSelector) {
+    if (!cssSelector) throw new Error(`css selector must be defined`)
+    await this._browser.wait(
+      until.elementLocated( By.css(cssSelector) ),
+      1e3 * 60 * 10
+    )
   }
 
   async waitFor(animation = false, async = false){
@@ -434,9 +445,12 @@ class WdBase{
 }
 
 class WdLayoutPage extends WdBase{
-
   constructor(){
     super()
+    WdLayoutPage.TagNames = {
+      ...(WdBase.TagNames || {} ),
+      sideNav: 'search-side-nav'
+    }
   }
 
   _getModal(){
@@ -532,7 +546,7 @@ class WdLayoutPage extends WdBase{
 
   // SideNav
   _getSideNav() {
-    return this._browser.findElement( By.tagName('search-side-nav') )
+    return this._browser.findElement( By.tagName(WdLayoutPage.TagNames.sideNav) )
   }
 
   async getSideNavTag(){
@@ -760,19 +774,12 @@ class WdIavPage extends WdLayoutPage{
   }
 
   async waitUntilAllChunksLoaded(){
-    const checkReady = async () => {
-      const el = await this._browser.findElements(
+    await this._browser.wait(async () => {
+      const els = await this._browser.findElements(
         By.css('div.loadingIndicator')
       )
-      return !el.length
-    }
-
-    do {
-      // Do nothing, until ready
-    } while (
-      await this.wait(1000),
-      !(await checkReady())
-    )
+      return els.length === 0
+    }, 1e3 * 60 * 10)
   }
 
   async getFloatingCtxInfoAsText(){
@@ -790,11 +797,20 @@ class WdIavPage extends WdLayoutPage{
       .findElement( By.css('[aria-label="Select a new template"]') )
     await templateBtn.click()
 
+    await this._browser.wait(
+      until.elementLocated( By.tagName('mat-option') ),
+      1e3 * 60 * 10
+    )
+
     const options = await this._browser.findElements(
       By.tagName('mat-option')
     )
     const idx = await _getIndexFromArrayOfWebElements(title, options)
-    if (idx >= 0) await options[idx].click()
+    if (idx >= 0) {
+      retry(async () => {
+        await options[idx].click()
+      }, { timeout: 1000, retries: 3 })
+    }
     else throw new Error(`${title} is not found as one of the dropdown templates`)
   }
 
diff --git a/package.json b/package.json
index 29ba287e6..f3a7aff77 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
     "@typescript-eslint/eslint-plugin": "^2.12.0",
     "@typescript-eslint/parser": "^2.12.0",
     "angular2-template-loader": "^0.6.2",
+    "browserstack-local": "^1.4.5",
     "codelyzer": "^5.0.1",
     "core-js": "^3.0.1",
     "css-loader": "^3.2.0",
diff --git a/src/index.html b/src/index.html
index 65ddf0e75..db01a3a08 100644
--- a/src/index.html
+++ b/src/index.html
@@ -11,7 +11,7 @@
   <link rel="stylesheet" href="theme.css">
   <link rel="stylesheet" href="version.css">
   
-  <script src="https://unpkg.com/kg-dataset-previewer@0.0.18/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer>
+  <script src="https://unpkg.com/kg-dataset-previewer@0.0.19/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer>
   </script>
 
   <title>Interactive Atlas Viewer</title>
@@ -35,7 +35,7 @@
 </head>
 <body>
   <atlas-viewer>
-    <h1 class="text-center" id="iav-inner">
+    <h1 class="text-center loadingIndicator" id="iav-inner">
       <span class="homeAnimationDots loadingAnimationDots">&bull;</span>
       <span class="homeAnimationDots loadingAnimationDots">&bull;</span>
       <span class="homeAnimationDots loadingAnimationDots">&bull;</span>
diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts
index 1ee340abf..275b2ffa1 100644
--- a/src/ui/nehubaContainer/nehubaContainer.component.ts
+++ b/src/ui/nehubaContainer/nehubaContainer.component.ts
@@ -516,6 +516,8 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy {
       this.selectedParcellation$.subscribe((this.handleParcellation).bind(this)),
     )
 
+    let prevParcellation = null
+
     this.subscriptions.push(
 
       combineLatest(
@@ -538,13 +540,16 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy {
         const { ngId: defaultNgId } = selectedParcellation
 
         /* selectedregionindexset needs to be updated regardless of forceshowsegment */
-        this.selectedRegionIndexSet = new Set(regions.map(({ngId = defaultNgId, labelIndex}) => generateLabelIndexId({ ngId, labelIndex })))
+        this.selectedRegionIndexSet = !prevParcellation || prevParcellation === selectedParcellation?
+          new Set(regions.map(({ngId = defaultNgId, labelIndex}) => generateLabelIndexId({ ngId, labelIndex }))) : new Set()
 
         if ( forceShowSegment === false || (forceShowSegment === null && hideSegmentFlag) ) {
           this.nehubaViewer.hideAllSeg()
           return
         }
 
+        prevParcellation = selectedParcellation
+
         this.selectedRegionIndexSet.size > 0
           ? this.nehubaViewer.showSegs([...this.selectedRegionIndexSet])
           : this.nehubaViewer.showAllSeg()
diff --git a/src/ui/nehubaContainer/splashScreen/splashScreen.template.html b/src/ui/nehubaContainer/splashScreen/splashScreen.template.html
index af7271b05..56c9e61fe 100644
--- a/src/ui/nehubaContainer/splashScreen/splashScreen.template.html
+++ b/src/ui/nehubaContainer/splashScreen/splashScreen.template.html
@@ -44,7 +44,7 @@
       </mat-card-footer>
     </mat-card>
     <ng-container *ngIf="stillLoadingTemplates$ | async as stillLoadingTemplates">
-      <div class="d-flex align-items-center p-4" *ngFor="let t of stillLoadingTemplates">
+      <div class="d-flex align-items-center p-4 loadingIndicator" *ngFor="let t of stillLoadingTemplates">
         <h1 class="mat-h1">
           <div class="spinnerAnimationCircle"></div>
         </h1>
-- 
GitLab