diff --git a/.travis.yml b/.travis.yml index e9d1d40d26897d755b439e0d8b1f70d76d32aa64..8bb9b983c6dc51d942b8e050a0145afed95d32c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,7 @@ env: - PPTR_VERSION=2.1.0 - PROTRACTOR_SPECS=./src/navigating/*.e2e-spec.js + # addons: # browserstack: # username: "xiao33" diff --git a/deploy/atlas/index.js b/deploy/atlas/index.js index 24fde48792abae55803d31156ed06dab05d69cf1..92ff4f851d80f5762ad6b9a8bdc045bb9738afb9 100644 --- a/deploy/atlas/index.js +++ b/deploy/atlas/index.js @@ -99,8 +99,7 @@ router.get('/:atlasId', async (req, res) => { const lastPathPreview = `preview?${searchParam.toString()}` return { ...tmpl, - previewUrl: getPreviewFn({ res, lastpart: lastPathPreview }), - url: getPreviewFn({ res, lastpart: lastTemplatePath }) + previewUrl: getPreviewFn({ res, lastpart: lastPathPreview }) } }) }) diff --git a/deploy/atlas/index.spec.js b/deploy/atlas/index.spec.js index 9762c9a2076477435fdefe22488cdce0eb06e984..727ae6e55a48746943df2cfe7a59375ae5cf57da 100644 --- a/deploy/atlas/index.spec.js +++ b/deploy/atlas/index.spec.js @@ -1,12 +1,12 @@ const { expect, assert } = require('chai') const express = require('express') -const router = require('./index') const { retry } = require('../../common/util') const got = require('got') let server, atlases, templates = [] const PORT = 12345 const baseUrl = `http://localhost:${PORT}` +process.env.HOSTNAME = baseUrl let routePathname describe('atlas/index.js', () => { before(async () => { @@ -19,7 +19,7 @@ describe('atlas/index.js', () => { next() }) - app.use(router) + app.use(require('./index')) server = app.listen(PORT) @@ -52,28 +52,18 @@ describe('atlas/index.js', () => { const { body } = await got(`${baseUrl}/`, { responseType: 'json' }) expect(body.length).to.equal(3) assert( - body.every(({ url }) => /^marshmellow/.test(url)), + body.every(({ url }) => /marshmellow/.test(url)), 'url pathname should be as set' ) }) it('> every end point works', async () => { for (const { url } of atlases) { expect(!!url).to.be.true - const { body } = await got(`${baseUrl}/${url}`, {responseType: 'json'}) - expect(body.templateSpaces.length).to.be.greaterThan(0) - templates.push( - body.templateSpaces + const { body } = await got( + /^http/.test(url) ? url : `${baseUrl}/${url}`, + {responseType: 'json'} ) - } - }) - - it('> templates resolves fine', async () => { - for (const arrTmpl of templates) { - for (const { url } of arrTmpl) { - expect(!!url).to.equal(true) - const { body } = await got(`${baseUrl}/${url}`, { responseType: 'json' }) - expect(body.parcellations.length).to.be.greaterThan(0) - } + expect(body.templateSpaces.length).to.be.greaterThan(0) } }) }) \ No newline at end of file diff --git a/deploy/datasets/util.js b/deploy/datasets/util.js index 25953080f60a025c8d321ee976dd50cf894cc4f3..eea0c8f742b4d1cdfb8142168c09ff0892f171e8 100644 --- a/deploy/datasets/util.js +++ b/deploy/datasets/util.js @@ -7,6 +7,14 @@ const { getIdFromFullId, retry, flattenRegions } = require('../../common/util') let getPublicAccessToken +const KG_IDS = { + PARCELLATIONS: { + LONG_BUNDLE: 'juelich/iav/atlas/v1.0.0/5', + SHORT_BUNDLE: 'juelich/iav/atlas/v1.0.0/6', + JULICH_BRAIN: 'minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579' + } +} + const getUserKGRequestParam = async ({ user }) => { let publicAccessToken /** @@ -95,9 +103,9 @@ initPrArray.push( readConfigFile('MNI152.json') .then(data => JSON.parse(data)) .then(json => { - const longBundle = flattenRegions(json.parcellations.find(({ name }) => name === 'Fibre Bundle Atlas - Long Bundle').regions) - const shortBundle = flattenRegions(json.parcellations.find(({ name }) => name === 'Fibre Bundle Atlas - Short Bundle').regions) - const jubrain = flattenRegions(json.parcellations.find(({ name }) => 'JuBrain Cytoarchitectonic Atlas' === name).regions) + const longBundle = flattenRegions(json.parcellations.find(({ ['@id']: id }) => id === KG_IDS.PARCELLATIONS.LONG_BUNDLE).regions) + const shortBundle = flattenRegions(json.parcellations.find(({ ['@id']: id }) => id === KG_IDS.PARCELLATIONS.SHORT_BUNDLE).regions) + const jubrain = flattenRegions(json.parcellations.find(({ ['@id']: id }) => id === KG_IDS.PARCELLATIONS.JULICH_BRAIN).regions) longBundleSet = populateSet(longBundle) shortBundleSet = populateSet(shortBundle) juBrainSet = populateSet(jubrain) diff --git a/src/atlasViewer/atlasViewer.urlUtil.spec.ts b/src/atlasViewer/atlasViewer.urlUtil.spec.ts index 74966bd4b9e4e02c8397d2cc150a1260d02f0cc8..2aff96c2df6af1d1a02b27b2f12d3710399a78d0 100644 --- a/src/atlasViewer/atlasViewer.urlUtil.spec.ts +++ b/src/atlasViewer/atlasViewer.urlUtil.spec.ts @@ -10,6 +10,9 @@ const mni152 = require('!json-loader!src/res/ext/MNI152.json') const mni152Nehubaconfig = require('!json-loader!src/res/ext/MNI152NehubaConfig.json') const allen = require('!json-loader!src/res/ext/allenMouse.json') const waxholm = require('!json-loader!src/res/ext/waxholmRatV2_0.json') +const atlasHumanMultilevel = require('!json-loader!src/res/ext/atlas/atlas_multiLevelHuman.json') + +const { defaultState: viewerHelperDefaultState,viewerStateHelperStoreName } = require('src/services/state/viewerState.store.helper') const { viewerState, ...rest } = defaultRootState const fetchedTemplateRootState = { @@ -18,24 +21,63 @@ const fetchedTemplateRootState = { ...viewerState, fetchedTemplates: [ bigbrainJson, colin, mni152, allen, waxholm ], }, + [viewerStateHelperStoreName]: { + ...viewerHelperDefaultState, + fetchedAtlases: [ atlasHumanMultilevel ] + } } // TODO finish writing tests describe('atlasViewer.urlService.service.ts', () => { describe('cvtSearchParamToState', () => { - it('parses template into atlasId properly', () => { - /** - * TODO finish test - */ - expect(true).toBe(false) - }) - it('convert empty search param to empty state', () => { + it('> convert empty search param to empty state', () => { const searchparam = new URLSearchParams() expect(() => cvtSearchParamToState(searchparam, defaultRootState)).toThrow() }) - it('successfully converts with only template defined', () => { + it('> parses template into atlasId properly', () => { + const searchparam = new URLSearchParams() + searchparam.set('templateSelected', bigbrainJson.name) + + const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState) + expect( + newState[viewerStateHelperStoreName]['selectedAtlasId'] + ).toEqual( + atlasHumanMultilevel['@id'] + ) + }) + + describe('> parses parcellation selected into overlayingAdditionalParcellations properly', () => { + it('> if the selected layer is base layer, it should not populate overlayingAdditionalParcellations', () => { + const searchparam = new URLSearchParams() + + searchparam.set('templateSelected', bigbrainJson.name) + searchparam.set('parcellationSelected', bigbrainJson.parcellations[0].name) + + const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState) + expect( + newState[viewerStateHelperStoreName]['overlayingAdditionalParcellations'] + ).toEqual([]) + }) + + it('> if the selected layer is non base layer, it should be populated', () => { + const searchparam = new URLSearchParams() + + searchparam.set('templateSelected', bigbrainJson.name) + searchparam.set('parcellationSelected', bigbrainJson.parcellations[1].name) + + const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState) + expect( + newState[viewerStateHelperStoreName]['overlayingAdditionalParcellations'].length + ).toEqual(1) + expect( + newState[viewerStateHelperStoreName]['overlayingAdditionalParcellations'][0]['@id'] + ).toEqual(bigbrainJson.parcellations[1]['@id']) + }) + }) + + it('> successfully converts with only template defined', () => { const searchparam = new URLSearchParams('?templateSelected=Big+Brain+%28Histology%29') const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState) diff --git a/src/atlasViewer/atlasViewer.urlUtil.ts b/src/atlasViewer/atlasViewer.urlUtil.ts index 6184b130722f96a04d8c9cb2e284476762a189f2..9697231b36839dac9afa766651cdb4e00d52446f 100644 --- a/src/atlasViewer/atlasViewer.urlUtil.ts +++ b/src/atlasViewer/atlasViewer.urlUtil.ts @@ -315,13 +315,14 @@ export const cvtSearchParamToState = (searchparams: URLSearchParams, state: IavR const viewreHelperState = returnState[viewerStateHelperStoreName] const { templateSelected, parcellationSelected } = returnState['viewerState'] const { fetchedAtlases, ...rest } = viewreHelperState - parcellationSelected['@id'] - const selectedAtlas = fetchedAtlases.find(a => a['templateSpaces'].find(t => t['@id'] === templateSelected['@id'])) - const overlayLayer = selectedAtlas['parcellations'].find(p => p['@id'] === parcellationSelected['@id']) + + const selectedAtlas = fetchedAtlases.find(a => a['templateSpaces'].find(t => t['@id'] === (templateSelected && templateSelected['@id']))) + + const overlayLayer = selectedAtlas && selectedAtlas['parcellations'].find(p => p['@id'] === (parcellationSelected && parcellationSelected['@id'])) returnState[viewerStateHelperStoreName] = { ...viewreHelperState, - selectedAtlasId: selectedAtlas['@id'], - overlayingAdditionalParcellations: !overlayLayer['baseLayer'] + selectedAtlasId: selectedAtlas && selectedAtlas['@id'], + overlayingAdditionalParcellations: (overlayLayer && !overlayLayer['baseLayer']) ? [ overlayLayer ] : [] } diff --git a/src/services/state/viewerState.store.helper.ts b/src/services/state/viewerState.store.helper.ts index ff34382e6938a70fc3b317de36dc2949ed360d93..21f3f715941b3f16d69a8aa15f215a6a2a28a97c 100644 --- a/src/services/state/viewerState.store.helper.ts +++ b/src/services/state/viewerState.store.helper.ts @@ -185,3 +185,4 @@ export function viewerStateFleshOutDetail(reducer: ActionReducer<any>): ActionRe } } +export const defaultState = initialState \ No newline at end of file diff --git a/src/services/stateStore.service.ts b/src/services/stateStore.service.ts index 83981d12f1bd436ada7cc052d49a8260124eb031..1aba9e107022f5b0a0ec793a791f985c706969bd 100644 --- a/src/services/stateStore.service.ts +++ b/src/services/stateStore.service.ts @@ -35,6 +35,11 @@ import { stateStore as viewerState, } from './state/viewerState.store' +import { + defaultState as defaultViewerHelperState, + viewerStateHelperStoreName +} from './state/viewerState.store.helper' + export { pluginState } export { viewerConfigState } export { NgViewerStateInterface, NgViewerActionInterface, ngViewerState } @@ -198,9 +203,8 @@ export interface IavRootStoreInterface { } import { DATASTORE_DEFAULT_STATE } from 'src/ui/databrowserModule' -import { createAction, props } from '@ngrx/store'; -export const defaultRootState: IavRootStoreInterface = { +export const defaultRootState: any = { pluginState: pluginDefaultState, dataStore: DATASTORE_DEFAULT_STATE, ngViewerState: ngViewerDefaultState, @@ -208,4 +212,5 @@ export const defaultRootState: IavRootStoreInterface = { userConfigState: userConfigDefaultState, viewerConfigState: viewerConfigDefaultState, viewerState: viewerDefaultState, + [viewerStateHelperStoreName]: defaultViewerHelperState } diff --git a/src/ui/viewerStateController/viewerState.useEffect.spec.ts b/src/ui/viewerStateController/viewerState.useEffect.spec.ts index dd055354b4e04fa8d05b06321f4f41c7dc9ffaee..513854f6703aa76d6b5b3c2f79b9fd574c8a13d6 100644 --- a/src/ui/viewerStateController/viewerState.useEffect.spec.ts +++ b/src/ui/viewerStateController/viewerState.useEffect.spec.ts @@ -85,45 +85,42 @@ describe('viewerState.useEffect.ts', () => { }).compileComponents() })) - describe('selectTemplateWithName$', () => { + describe('selectTemplate$', () => { it('if coordXform returns error', () => { - expect(false).toBe(true) const viewerStateCtrlEffect = TestBed.inject(ViewerStateControllerUseEffect) - // expect( - // viewerStateCtrlEffect.selectTemplateWithName$ - // ).toBeObservable( - // hot( - // 'a', - // { - // a: { - // type: NEWVIEWER, - // selectTemplate: reconstitutedColin, - // selectParcellation: reconstitutedColin.parcellations[0] - // } - // } - // ) - // ) + expect( + viewerStateCtrlEffect.selectTemplate$ + ).toBeObservable( + hot( + 'a', + { + a: { + type: NEWVIEWER, + selectTemplate: reconstitutedColin, + selectParcellation: reconstitutedColin.parcellations[0] + } + } + ) + ) }) it('calls with correct param', () => { - expect(false).toBe(true) - // necessary for observable to fire const viewerStateCtrlEffect = TestBed.inject(ViewerStateControllerUseEffect) - // expect( - // viewerStateCtrlEffect.selectTemplateWithName$ - // ).toBeObservable( - // hot( - // 'a', - // { - // a: { - // type: NEWVIEWER, - // selectTemplate: reconstitutedColin, - // selectParcellation: reconstitutedColin.parcellations[0] - // } - // } - // ) - // ) + expect( + viewerStateCtrlEffect.selectTemplate$ + ).toBeObservable( + hot( + 'a', + { + a: { + type: NEWVIEWER, + selectTemplate: reconstitutedColin, + selectParcellation: reconstitutedColin.parcellations[0] + } + } + ) + ) expect(spy).toHaveBeenCalledWith( bigbrainJson.name, reconstitutedColin.name, @@ -145,21 +142,21 @@ describe('viewerState.useEffect.ts', () => { } updatedColinNavigation.zoomFactor = zoom updatedColinNavigation.pose.orientation = orientation - expect(false).toBe(true) - // expect( - // viewerStateCtrlEffect.selectTemplateWithName$ - // ).toBeObservable( - // hot( - // 'a', - // { - // a: { - // type: NEWVIEWER, - // selectTemplate: updatedColin, - // selectParcellation: updatedColin.parcellations[0] - // } - // } - // ) - // ) + + expect( + viewerStateCtrlEffect.selectTemplate$ + ).toBeObservable( + hot( + 'a', + { + a: { + type: NEWVIEWER, + selectTemplate: updatedColin, + selectParcellation: updatedColin.parcellations[0] + } + } + ) + ) }) }) })