From 64786c2dd6f8fdf9cafd2d1edbb1dc3df5ffa3d0 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Wed, 9 Sep 2020 16:04:45 -0400 Subject: [PATCH 1/2] Allow the default space to be accessed via /s/default --- .../common/lib/spaces_url_parser.test.ts | 37 ++++++-- .../spaces/common/lib/spaces_url_parser.ts | 28 ++++-- .../on_request_interceptor.ts | 5 +- .../spaces_service/spaces_service.test.ts | 2 +- .../server/spaces_service/spaces_service.ts | 2 +- .../apis/spaces/get_active_space.ts | 14 +++ .../common/lib/space_test_utils.ts | 21 +++++ .../common/suites/create.ts | 86 ++++++++++--------- .../common/suites/delete.ts | 50 +++++------ .../common/suites/get.ts | 16 ++-- .../common/suites/get_all.ts | 50 +++++------ 11 files changed, 192 insertions(+), 119 deletions(-) diff --git a/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts b/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts index b25d79c0a6907..d563a0c86cd4a 100644 --- a/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts +++ b/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts @@ -10,41 +10,60 @@ describe('getSpaceIdFromPath', () => { describe('without a serverBasePath defined', () => { test('it identifies the space url context', () => { const basePath = `/s/my-awesome-space-lives-here`; - expect(getSpaceIdFromPath(basePath)).toEqual('my-awesome-space-lives-here'); + expect(getSpaceIdFromPath(basePath)).toEqual({ + spaceId: 'my-awesome-space-lives-here', + pathHasExplicitSpaceIdentifier: true, + }); }); test('ignores space identifiers in the middle of the path', () => { const basePath = `/this/is/a/crazy/path/s/my-awesome-space-lives-here`; - expect(getSpaceIdFromPath(basePath)).toEqual(DEFAULT_SPACE_ID); + expect(getSpaceIdFromPath(basePath)).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: false, + }); }); test('it handles base url without a space url context', () => { const basePath = `/this/is/a/crazy/path/s`; - expect(getSpaceIdFromPath(basePath)).toEqual(DEFAULT_SPACE_ID); + expect(getSpaceIdFromPath(basePath)).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: false, + }); }); }); describe('with a serverBasePath defined', () => { test('it identifies the space url context', () => { const basePath = `/s/my-awesome-space-lives-here`; - expect(getSpaceIdFromPath(basePath, '/')).toEqual('my-awesome-space-lives-here'); + expect(getSpaceIdFromPath(basePath, '/')).toEqual({ + spaceId: 'my-awesome-space-lives-here', + pathHasExplicitSpaceIdentifier: true, + }); }); test('it identifies the space url context following the server base path', () => { const basePath = `/server-base-path-here/s/my-awesome-space-lives-here`; - expect(getSpaceIdFromPath(basePath, '/server-base-path-here')).toEqual( - 'my-awesome-space-lives-here' - ); + expect(getSpaceIdFromPath(basePath, '/server-base-path-here')).toEqual({ + spaceId: 'my-awesome-space-lives-here', + pathHasExplicitSpaceIdentifier: true, + }); }); test('ignores space identifiers in the middle of the path', () => { const basePath = `/this/is/a/crazy/path/s/my-awesome-space-lives-here`; - expect(getSpaceIdFromPath(basePath, '/this/is/a')).toEqual(DEFAULT_SPACE_ID); + expect(getSpaceIdFromPath(basePath, '/this/is/a')).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: false, + }); }); test('it handles base url without a space url context', () => { const basePath = `/this/is/a/crazy/path/s`; - expect(getSpaceIdFromPath(basePath, basePath)).toEqual(DEFAULT_SPACE_ID); + expect(getSpaceIdFromPath(basePath, basePath)).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: false, + }); }); }); }); diff --git a/x-pack/plugins/spaces/common/lib/spaces_url_parser.ts b/x-pack/plugins/spaces/common/lib/spaces_url_parser.ts index 994ec7c59cb6e..be950e6a651e6 100644 --- a/x-pack/plugins/spaces/common/lib/spaces_url_parser.ts +++ b/x-pack/plugins/spaces/common/lib/spaces_url_parser.ts @@ -5,20 +5,22 @@ */ import { DEFAULT_SPACE_ID } from '../constants'; +const spaceContextRegex = /^\/s\/([a-z0-9_\-]+)/; + export function getSpaceIdFromPath( requestBasePath: string = '/', serverBasePath: string = '/' -): string { - let pathToCheck: string = requestBasePath; +): { spaceId: string; pathHasExplicitSpaceIdentifier: boolean } { + const pathToCheck: string = stripServerBasePath(requestBasePath, serverBasePath); - if (serverBasePath && serverBasePath !== '/' && requestBasePath.startsWith(serverBasePath)) { - pathToCheck = requestBasePath.substr(serverBasePath.length); - } // Look for `/s/space-url-context` in the base path - const matchResult = pathToCheck.match(/^\/s\/([a-z0-9_\-]+)/); + const matchResult = pathToCheck.match(spaceContextRegex); if (!matchResult || matchResult.length === 0) { - return DEFAULT_SPACE_ID; + return { + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: false, + }; } // Ignoring first result, we only want the capture group result at index 1 @@ -28,7 +30,10 @@ export function getSpaceIdFromPath( throw new Error(`Unable to determine Space ID from request path: ${requestBasePath}`); } - return spaceId; + return { + spaceId, + pathHasExplicitSpaceIdentifier: true, + }; } export function addSpaceIdToPath( @@ -45,3 +50,10 @@ export function addSpaceIdToPath( } return `${basePath}${requestedPath}`; } + +function stripServerBasePath(requestBasePath: string, serverBasePath: string) { + if (serverBasePath && serverBasePath !== '/' && requestBasePath.startsWith(serverBasePath)) { + return requestBasePath.substr(serverBasePath.length); + } + return requestBasePath; +} diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts index 4b3a5d662f12d..6408803c2114b 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts @@ -10,7 +10,6 @@ import { CoreSetup, } from 'src/core/server'; import { format } from 'url'; -import { DEFAULT_SPACE_ID } from '../../../common/constants'; import { modifyUrl } from '../utils/url'; import { getSpaceIdFromPath } from '../../../common'; @@ -28,9 +27,9 @@ export function initSpacesOnRequestInterceptor({ http }: OnRequestInterceptorDep // If navigating within the context of a space, then we store the Space's URL Context on the request, // and rewrite the request to not include the space identifier in the URL. - const spaceId = getSpaceIdFromPath(path, serverBasePath); + const { spaceId, pathHasExplicitSpaceIdentifier } = getSpaceIdFromPath(path, serverBasePath); - if (spaceId !== DEFAULT_SPACE_ID) { + if (pathHasExplicitSpaceIdentifier) { const reqBasePath = `/s/${spaceId}`; http.basePath.set(request, reqBasePath); diff --git a/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts b/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts index b341d76c86649..b48bf971d0c1b 100644 --- a/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts +++ b/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts @@ -58,7 +58,7 @@ const createService = async (serverBasePath: string = '') => { serverBasePath, } as HttpServiceSetup['basePath']; httpSetup.basePath.get = jest.fn().mockImplementation((request: KibanaRequest) => { - const spaceId = getSpaceIdFromPath(request.url.path); + const { spaceId } = getSpaceIdFromPath(request.url.path); if (spaceId !== DEFAULT_SPACE_ID) { return `/s/${spaceId}`; diff --git a/x-pack/plugins/spaces/server/spaces_service/spaces_service.ts b/x-pack/plugins/spaces/server/spaces_service/spaces_service.ts index cf181a78efcb8..3630675a7ed3f 100644 --- a/x-pack/plugins/spaces/server/spaces_service/spaces_service.ts +++ b/x-pack/plugins/spaces/server/spaces_service/spaces_service.ts @@ -63,7 +63,7 @@ export class SpacesService { ? (request as Record).getBasePath() : http.basePath.get(request); - const spaceId = getSpaceIdFromPath(basePath, http.basePath.serverBasePath); + const { spaceId } = getSpaceIdFromPath(basePath, http.basePath.serverBasePath); return spaceId; }; diff --git a/x-pack/test/api_integration/apis/spaces/get_active_space.ts b/x-pack/test/api_integration/apis/spaces/get_active_space.ts index b925df3918825..16cb03fe8a316 100644 --- a/x-pack/test/api_integration/apis/spaces/get_active_space.ts +++ b/x-pack/test/api_integration/apis/spaces/get_active_space.ts @@ -35,6 +35,20 @@ export default function ({ getService }: FtrProviderContext) { }); }); + it('returns the default space when explicitly referenced', async () => { + await supertest + .get('/s/default/internal/spaces/_active_space') + .set('kbn-xsrf', 'xxx') + .expect(200, { + id: 'default', + name: 'Default', + description: 'This is your default space!', + color: '#00bfb3', + disabledFeatures: [], + _reserved: true, + }); + }); + it('returns the foo space', async () => { await supertest .get('/s/foo-space/internal/spaces/_active_space') diff --git a/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts b/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts index f233bc1d11d7c..c8e13f6bada7a 100644 --- a/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts +++ b/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts @@ -13,3 +13,24 @@ export function getUrlPrefix(spaceId?: string) { export function getIdPrefix(spaceId?: string) { return spaceId === DEFAULT_SPACE_ID ? '' : `${spaceId}-`; } + +export function getTestScenariosForSpace(spaceId: string) { + const explicitScenario = { + spaceId, + urlPrefix: `/s/${spaceId}`, + scenario: `when referencing the ${spaceId} space explicitly in the URL`, + }; + + if (spaceId === DEFAULT_SPACE_ID) { + return [ + { + spaceId, + urlPrefix: ``, + scenario: 'when referencing the default space implicitly', + }, + explicitScenario, + ]; + } + + return [explicitScenario]; +} diff --git a/x-pack/test/spaces_api_integration/common/suites/create.ts b/x-pack/test/spaces_api_integration/common/suites/create.ts index 4de638c784147..7c2120ce6eeaf 100644 --- a/x-pack/test/spaces_api_integration/common/suites/create.ts +++ b/x-pack/test/spaces_api_integration/common/suites/create.ts @@ -6,7 +6,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { getUrlPrefix } from '../lib/space_test_utils'; +import { getTestScenariosForSpace } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; interface CreateTest { @@ -67,56 +67,58 @@ export function createTestSuiteFactory(esArchiver: any, supertest: SuperTest { describeFn(description, () => { - before(() => esArchiver.load('saved_objects/spaces')); - after(() => esArchiver.unload('saved_objects/spaces')); + beforeEach(() => esArchiver.load('saved_objects/spaces')); + afterEach(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.newSpace.statusCode}`, async () => { - return supertest - .post(`${getUrlPrefix(spaceId)}/api/spaces/space`) - .auth(user.username, user.password) - .send({ - name: 'marketing', - id: 'marketing', - description: 'a description', - color: '#5c5959', - disabledFeatures: [], - }) - .expect(tests.newSpace.statusCode) - .then(tests.newSpace.response); - }); - - describe('when it already exists', () => { - it(`should return ${tests.alreadyExists.statusCode}`, async () => { + getTestScenariosForSpace(spaceId).forEach(({ urlPrefix, scenario }) => { + it(`should return ${tests.newSpace.statusCode} ${scenario}`, async () => { return supertest - .post(`${getUrlPrefix(spaceId)}/api/spaces/space`) + .post(`${urlPrefix}/api/spaces/space`) .auth(user.username, user.password) .send({ - name: 'space_1', - id: 'space_1', - color: '#ffffff', + name: 'marketing', + id: 'marketing', description: 'a description', + color: '#5c5959', disabledFeatures: [], }) - .expect(tests.alreadyExists.statusCode) - .then(tests.alreadyExists.response); + .expect(tests.newSpace.statusCode) + .then(tests.newSpace.response); }); - }); - describe('when _reserved is specified', () => { - it(`should return ${tests.reservedSpecified.statusCode} and ignore _reserved`, async () => { - return supertest - .post(`${getUrlPrefix(spaceId)}/api/spaces/space`) - .auth(user.username, user.password) - .send({ - name: 'reserved space', - id: 'reserved', - description: 'a description', - color: '#5c5959', - _reserved: true, - disabledFeatures: [], - }) - .expect(tests.reservedSpecified.statusCode) - .then(tests.reservedSpecified.response); + describe('when it already exists', () => { + it(`should return ${tests.alreadyExists.statusCode} ${scenario}`, async () => { + return supertest + .post(`${urlPrefix}/api/spaces/space`) + .auth(user.username, user.password) + .send({ + name: 'space_1', + id: 'space_1', + color: '#ffffff', + description: 'a description', + disabledFeatures: [], + }) + .expect(tests.alreadyExists.statusCode) + .then(tests.alreadyExists.response); + }); + }); + + describe('when _reserved is specified', () => { + it(`should return ${tests.reservedSpecified.statusCode} and ignore _reserved ${scenario}`, async () => { + return supertest + .post(`${urlPrefix}/api/spaces/space`) + .auth(user.username, user.password) + .send({ + name: 'reserved space', + id: 'reserved', + description: 'a description', + color: '#5c5959', + _reserved: true, + disabledFeatures: [], + }) + .expect(tests.reservedSpecified.statusCode) + .then(tests.reservedSpecified.response); + }); }); }); }); diff --git a/x-pack/test/spaces_api_integration/common/suites/delete.ts b/x-pack/test/spaces_api_integration/common/suites/delete.ts index 69b5697d8a9a8..2a6b2c0e69d1d 100644 --- a/x-pack/test/spaces_api_integration/common/suites/delete.ts +++ b/x-pack/test/spaces_api_integration/common/suites/delete.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { getUrlPrefix } from '../lib/space_test_utils'; +import { getTestScenariosForSpace } from '../lib/space_test_utils'; import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; @@ -176,7 +176,7 @@ export function deleteTestSuiteFactory(es: any, esArchiver: any, supertest: Supe { user = {}, spaceId, tests }: DeleteTestDefinition ) => { describeFn(description, () => { - before(async () => { + beforeEach(async () => { await esArchiver.load('saved_objects/spaces'); // since we want to verify that we only delete the right things @@ -189,33 +189,35 @@ export function deleteTestSuiteFactory(es: any, esArchiver: any, supertest: Supe .auth(user.username, user.password) .expect(200); }); - after(() => esArchiver.unload('saved_objects/spaces')); + afterEach(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.exists.statusCode}`, async () => { - return supertest - .delete(`${getUrlPrefix(spaceId)}/api/spaces/space/space_2`) - .auth(user.username, user.password) - .expect(tests.exists.statusCode) - .then(tests.exists.response); - }); - - describe(`when the space is reserved`, () => { - it(`should return ${tests.reservedSpace.statusCode}`, async () => { + getTestScenariosForSpace(spaceId).forEach(({ urlPrefix, scenario }) => { + it(`should return ${tests.exists.statusCode} ${scenario}`, async () => { return supertest - .delete(`${getUrlPrefix(spaceId)}/api/spaces/space/default`) + .delete(`${urlPrefix}/api/spaces/space/space_2`) .auth(user.username, user.password) - .expect(tests.reservedSpace.statusCode) - .then(tests.reservedSpace.response); + .expect(tests.exists.statusCode) + .then(tests.exists.response); }); - }); - describe(`when the space doesn't exist`, () => { - it(`should return ${tests.doesntExist.statusCode}`, async () => { - return supertest - .delete(`${getUrlPrefix(spaceId)}/api/spaces/space/space_3`) - .auth(user.username, user.password) - .expect(tests.doesntExist.statusCode) - .then(tests.doesntExist.response); + describe(`when the space is reserved`, () => { + it(`should return ${tests.reservedSpace.statusCode} ${scenario}`, async () => { + return supertest + .delete(`${urlPrefix}/api/spaces/space/default`) + .auth(user.username, user.password) + .expect(tests.reservedSpace.statusCode) + .then(tests.reservedSpace.response); + }); + }); + + describe(`when the space doesn't exist`, () => { + it(`should return ${tests.doesntExist.statusCode} ${scenario}`, async () => { + return supertest + .delete(`${urlPrefix}/api/spaces/space/space_3`) + .auth(user.username, user.password) + .expect(tests.doesntExist.statusCode) + .then(tests.doesntExist.response); + }); }); }); }); diff --git a/x-pack/test/spaces_api_integration/common/suites/get.ts b/x-pack/test/spaces_api_integration/common/suites/get.ts index bd0e2a18d5c50..6bf5b0f180237 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; import { SuperAgent } from 'superagent'; -import { getUrlPrefix } from '../lib/space_test_utils'; +import { getTestScenariosForSpace } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; interface GetTest { @@ -80,12 +80,14 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperAgent) before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - return supertest - .get(`${getUrlPrefix(currentSpaceId)}/api/spaces/space/${spaceId}`) - .auth(user.username, user.password) - .expect(tests.default.statusCode) - .then(tests.default.response); + getTestScenariosForSpace(currentSpaceId).forEach(({ urlPrefix, scenario }) => { + it(`should return ${tests.default.statusCode} ${scenario}`, async () => { + return supertest + .get(`${urlPrefix}/api/spaces/space/${spaceId}`) + .auth(user.username, user.password) + .expect(tests.default.statusCode) + .then(tests.default.response); + }); }); }); }; diff --git a/x-pack/test/spaces_api_integration/common/suites/get_all.ts b/x-pack/test/spaces_api_integration/common/suites/get_all.ts index d41d73bba90bc..fce48e4938baa 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get_all.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get_all.ts @@ -5,7 +5,7 @@ */ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { getUrlPrefix } from '../lib/space_test_utils'; +import { getTestScenariosForSpace } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; interface GetAllTest { @@ -71,33 +71,35 @@ export function getAllTestSuiteFactory(esArchiver: any, supertest: SuperTest esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.exists.statusCode}`, async () => { - return supertest - .get(`${getUrlPrefix(spaceId)}/api/spaces/space`) - .auth(user.username, user.password) - .expect(tests.exists.statusCode) - .then(tests.exists.response); - }); - - describe('copySavedObjects purpose', () => { - it(`should return ${tests.copySavedObjectsPurpose.statusCode}`, async () => { + getTestScenariosForSpace(spaceId).forEach(({ scenario, urlPrefix }) => { + it(`should return ${tests.exists.statusCode} ${scenario}`, async () => { return supertest - .get(`${getUrlPrefix(spaceId)}/api/spaces/space`) - .query({ purpose: 'copySavedObjectsIntoSpace' }) + .get(`${urlPrefix}/api/spaces/space`) .auth(user.username, user.password) - .expect(tests.copySavedObjectsPurpose.statusCode) - .then(tests.copySavedObjectsPurpose.response); + .expect(tests.exists.statusCode) + .then(tests.exists.response); }); - }); - describe('copySavedObjects purpose', () => { - it(`should return ${tests.shareSavedObjectsPurpose.statusCode}`, async () => { - return supertest - .get(`${getUrlPrefix(spaceId)}/api/spaces/space`) - .query({ purpose: 'shareSavedObjectsIntoSpace' }) - .auth(user.username, user.password) - .expect(tests.copySavedObjectsPurpose.statusCode) - .then(tests.copySavedObjectsPurpose.response); + describe('copySavedObjects purpose', () => { + it(`should return ${tests.copySavedObjectsPurpose.statusCode} ${scenario}`, async () => { + return supertest + .get(`${urlPrefix}/api/spaces/space`) + .query({ purpose: 'copySavedObjectsIntoSpace' }) + .auth(user.username, user.password) + .expect(tests.copySavedObjectsPurpose.statusCode) + .then(tests.copySavedObjectsPurpose.response); + }); + }); + + describe('copySavedObjects purpose', () => { + it(`should return ${tests.shareSavedObjectsPurpose.statusCode} ${scenario}`, async () => { + return supertest + .get(`${urlPrefix}/api/spaces/space`) + .query({ purpose: 'shareSavedObjectsIntoSpace' }) + .auth(user.username, user.password) + .expect(tests.copySavedObjectsPurpose.statusCode) + .then(tests.copySavedObjectsPurpose.response); + }); }); }); }); From 2084f125b41d17eb8499724cf6e180ea02fb90ac Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Thu, 15 Oct 2020 20:57:52 -0400 Subject: [PATCH 2/2] apply suggestions from code review --- .../spaces/common/lib/spaces_url_parser.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts b/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts index d563a0c86cd4a..2b34bc77ec686 100644 --- a/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts +++ b/x-pack/plugins/spaces/common/lib/spaces_url_parser.test.ts @@ -31,6 +31,14 @@ describe('getSpaceIdFromPath', () => { pathHasExplicitSpaceIdentifier: false, }); }); + + test('it identifies the space url context with the default space', () => { + const basePath = `/s/${DEFAULT_SPACE_ID}`; + expect(getSpaceIdFromPath(basePath)).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: true, + }); + }); }); describe('with a serverBasePath defined', () => { @@ -58,6 +66,14 @@ describe('getSpaceIdFromPath', () => { }); }); + test('it identifies the space url context with the default space following the server base path', () => { + const basePath = `/server-base-path-here/s/${DEFAULT_SPACE_ID}`; + expect(getSpaceIdFromPath(basePath, '/server-base-path-here')).toEqual({ + spaceId: DEFAULT_SPACE_ID, + pathHasExplicitSpaceIdentifier: true, + }); + }); + test('it handles base url without a space url context', () => { const basePath = `/this/is/a/crazy/path/s`; expect(getSpaceIdFromPath(basePath, basePath)).toEqual({