diff --git a/src/api/controller/front/index.js b/src/api/controller/front/index.js index e367e3c7a..5fa5f3dc4 100644 --- a/src/api/controller/front/index.js +++ b/src/api/controller/front/index.js @@ -1,4 +1,24 @@ +import Koa from 'koa'; +import mount from 'koa-mount'; + import dev from './dev'; import prod from './prod'; -export default process.env.NODE_ENV === 'development' ? dev() : prod(); +const app = new Koa(); + +const middleware = process.env.NODE_ENV === 'development' ? dev() : prod(); + +app.use(async (ctx, next) => { + const uri = ctx.path; + + if (uri.startsWith('/ark:/') || uri.startsWith('/uid:/')) { + // Override the path so that webpack serves the application correctly + ctx.path = '/'; + } + + await next(); +}); + +app.use(mount(middleware)); + +export default app; diff --git a/src/app/e2e/home_published_julia.spec.js b/src/app/e2e/home_published_julia.spec.js index 4cc277ef9..2a6eae3bd 100644 --- a/src/app/e2e/home_published_julia.spec.js +++ b/src/app/e2e/home_published_julia.spec.js @@ -1,5 +1,5 @@ import { until, By } from 'selenium-webdriver'; -import { elementValueIs, elementIsClicked, elementTextIs } from 'selenium-smart-wait'; +import { elementValueIs, elementIsClicked, elementTextIs, stalenessOf } from 'selenium-smart-wait'; import expect from 'expect'; import driver from '../../common/tests/chromeDriver'; @@ -161,7 +161,7 @@ describe('Home page with published data when logged as Julia', function homePubl await driver.wait(elementTextIs(bestFriendValue, 'MERIADOC', DEFAULT_WAIT_TIMEOUT)); }); - it('should go to hide page', async () => { + it('should display the hide modal', async () => { await driver.wait(until.elementLocated(By.css('.hide-resource'))); const button = await driver.findElement(By.css('.hide-resource')); await driver.executeScript('document.getElementsByClassName("hide-resource")[0].scrollIntoView(true);'); @@ -172,7 +172,8 @@ describe('Home page with published data when logged as Julia', function homePubl await driver.wait(inputElementIsFocusable(reason), DEFAULT_WAIT_TIMEOUT); await reason.clear(); await reason.sendKeys('My bad, should not be here'); - await driver.wait(elementIsClicked('.hide-resource.save')); + await driver.wait(elementIsClicked('.hide-resource.save'), DEFAULT_WAIT_TIMEOUT); + await driver.wait(stalenessOf(form, DEFAULT_WAIT_TIMEOUT)); }); it('should display reason for removal', async () => { diff --git a/src/app/js/configureStore.js b/src/app/js/configureStore.js index 32be63577..2a19b1b56 100644 --- a/src/app/js/configureStore.js +++ b/src/app/js/configureStore.js @@ -8,6 +8,14 @@ import filter from 'redux-localstorage-filter'; const sagaMiddleware = createSagaMiddleware(); +export const getResourceUri = (location) => { + if (location.pathname.startsWith('/ark:/') || location.pathname.startsWith('/uid:/')) { + return location.pathname.substr(1); + } + + return null; +}; + export default function configureStore(pureReducer, sagas, initialState) { const rootReducer = __DEBUG__ ? (state, action) => { @@ -48,5 +56,15 @@ export default function configureStore(pureReducer, sagas, initialState) { if (__DEBUG__) { window.store = store; } + + const resourceUri = getResourceUri(window.location); + + if (resourceUri) { + hashHistory.replace({ + pathname: 'resource', + state: { uri: resourceUri }, + }); + } + return store; } diff --git a/src/app/js/public/resource/sagas/loadResource.js b/src/app/js/public/resource/sagas/loadResource.js index 091bca5be..1bdf23091 100644 --- a/src/app/js/public/resource/sagas/loadResource.js +++ b/src/app/js/public/resource/sagas/loadResource.js @@ -14,20 +14,25 @@ import fetchSaga from '../../../lib/fetchSaga'; import { fromResource } from '../../selectors'; -export const parsePathName = pathname => pathname.match(/^(\/resource)(\/ark:\/)?(.*$)/) || []; +export const parsePathName = pathname => pathname.match(/^\/resource(\/ark:\/)?(.*$)/) || []; export function* handleLoadResource({ payload }) { let isArk; let ark; - let name; let uri; + if (payload && payload.pathname && !payload.pathname.startsWith('/resource')) { + return; + } + if (payload && payload.pathname) { - [, name, isArk, ark] = yield call(parsePathName, payload.pathname); - if (name !== '/resource') { - return; + [, isArk, ark] = yield call(parsePathName, payload.pathname); + + if (payload && payload.state && payload.state.uri) { + uri = payload.state.uri; + } else { + uri = isArk ? ark : payload.query.uri; } - uri = isArk ? ark : payload.query.uri; } else { const resource = yield select(fromResource.getResourceLastVersion); diff --git a/src/app/js/public/resource/sagas/loadResource.spec.js b/src/app/js/public/resource/sagas/loadResource.spec.js index 6eacfa046..ef2a6a2f2 100644 --- a/src/app/js/public/resource/sagas/loadResource.spec.js +++ b/src/app/js/public/resource/sagas/loadResource.spec.js @@ -13,76 +13,102 @@ import { handleLoadResource, parsePathName } from './loadResource'; describe('resource saga', () => { describe('handleLoadResource', () => { - const action = { - payload: { - pathname: 'pathname', - query: { - uri: 'uri', + it('should end if pathname is not /resource', () => { + const saga = handleLoadResource({ + payload: { + pathname: '/different', }, - }, - }; - let saga; - - beforeEach(() => { - saga = handleLoadResource(action); - }); - - it('should call parsePathName', () => { - expect(saga.next().value).toEqual(call(parsePathName, 'pathname')); - }); - - it('should end if parsePathName return name different of /resource', () => { + }); saga.next(); const next = saga.next([null, '/different']); expect(next.done).toBe(true); }); - it('should put loadResource', () => { - saga.next(); - const next = saga.next([null, '/resource', true, 'ark']); - expect(next.value).toEqual(put(loadResource())); - }); + describe('with /resource pathname', () => { + const action = { + payload: { + pathname: '/resource', + query: { + uri: 'uri', + }, + }, + }; - it('should select getLoadResourceRequest with ark if returned by parsePathName', () => { - saga.next(); - saga.next([null, '/resource', true, 'ark']); - const next = saga.next(); - expect(next.value).toEqual(select(getLoadResourceRequest, 'ark')); - }); + let saga; - it('should select getLoadResourceRequest with payload.query.uri if ark not returned by parsePathName', () => { - saga.next(); - saga.next([null, '/resource', false]); - const next = saga.next(); - expect(next.value).toEqual(select(getLoadResourceRequest, 'uri')); - }); + it('should call parsePathName', () => { + saga = handleLoadResource(action); + expect(saga.next().value).toEqual(call(parsePathName, '/resource')); + }); - it('should call fetchSaga with returned request', () => { - saga.next(); - saga.next([null, '/resource', false]); - saga.next(); - const next = saga.next('request'); - expect(next.value).toEqual(call(fetchSaga, 'request')); - }); + it('should put loadResource', () => { + saga = handleLoadResource(action); + saga.next(); + const next = saga.next([null, '/resource', true, 'ark']); + expect(next.value).toEqual(put(loadResource())); + }); - it('should put loadResourceError if fetchSaga returned an error', () => { - saga.next(); - saga.next([null, '/resource', false]); - saga.next(); - saga.next('request'); - const next = saga.next({ error: 'error' }); - expect(next.value).toEqual(put(loadResourceError('error'))); - }); + it('should select getLoadResourceRequest with ark if returned by parsePathName', () => { + saga = handleLoadResource(action); + saga.next(); + saga.next([null, true, 'ark']); + const next = saga.next(); + expect(next.value).toEqual(select(getLoadResourceRequest, 'ark')); + }); - it('should put loadResourceSuccess and loadPublication if fetchSaga succeeded', () => { - saga.next(); - saga.next([null, '/resource', false]); - saga.next(); - saga.next('request'); - let next = saga.next({ response: 'response' }); - expect(next.value).toEqual(put(loadResourceSuccess('response'))); - next = saga.next(); - expect(next.value).toEqual(put(loadPublication())); + it('should select getLoadResourceRequest with uri returned from state', () => { + saga = handleLoadResource({ + payload: { + pathname: '/resource', + state: { + uri: 'uri', + }, + }, + }); + saga.next(); + saga.next([]); + const next = saga.next(); + expect(next.value).toEqual(select(getLoadResourceRequest, 'uri')); + }); + + it('should select getLoadResourceRequest with payload.query.uri if ark not returned by parsePathName', () => { + saga = handleLoadResource(action); + saga.next(); + saga.next([null, false]); + const next = saga.next(); + expect(next.value).toEqual(select(getLoadResourceRequest, 'uri')); + }); + + it('should call fetchSaga with returned request', () => { + saga = handleLoadResource(action); + saga.next(); + saga.next([null, false]); + saga.next(); + const next = saga.next('request'); + expect(next.value).toEqual(call(fetchSaga, 'request')); + }); + + it('should put loadResourceError if fetchSaga returned an error', () => { + saga = handleLoadResource(action); + saga.next(); + saga.next([null, false]); + saga.next(); + saga.next('request'); + const next = saga.next({ error: 'error' }); + expect(next.value).toEqual(put(loadResourceError('error'))); + }); + + it('should put loadResourceSuccess and loadPublication if fetchSaga succeeded', () => { + saga = handleLoadResource(action); + saga.next(); + saga.next([null, false]); + saga.next(); + saga.next('request'); + let next = saga.next({ response: 'response' }); + expect(next.value).toEqual(put(loadResourceSuccess('response'))); + next = saga.next(); + expect(next.value).toEqual(put(loadPublication())); + }); }); }); });