diff --git a/react/src/__fixtures__/appConfigurationFixture.ts b/react/src/__fixtures__/appConfigurationFixture.ts
index affa8afb..ac4ecfb6 100644
--- a/react/src/__fixtures__/appConfigurationFixture.ts
+++ b/react/src/__fixtures__/appConfigurationFixture.ts
@@ -1,4 +1,9 @@
-import { AppConfiguration, MapillaryConfiguration } from '@hazmapper/types';
+import {
+ AppConfiguration,
+ GeoapiBackendEnvironment,
+ MapillaryConfiguration,
+} from '@hazmapper/types';
+import { getGeoapiUrl } from '@hazmapper/hooks/environment/utils';
export const mapillaryConfig: MapillaryConfiguration = {
authUrl: 'https://www.mapillary.com/connect',
@@ -14,7 +19,8 @@ export const mapillaryConfig: MapillaryConfiguration = {
export const testDevConfiguration: AppConfiguration = {
basePath: '/test',
- geoapiUrl: 'https://geoapi.unittest',
+ geoapiEnv: GeoapiBackendEnvironment.Test,
+ geoapiUrl: getGeoapiUrl(GeoapiBackendEnvironment.Test),
designsafePortalUrl: 'https://designsafeci.unittest',
tapisUrl: 'https://tapis.io.unittest',
mapillary: mapillaryConfig,
diff --git a/react/src/components/ManageMapProjectPanel/ManageMapProjectPanel.test.tsx b/react/src/components/ManageMapProjectPanel/ManageMapProjectPanel.test.tsx
index c60b436b..394519fc 100644
--- a/react/src/components/ManageMapProjectPanel/ManageMapProjectPanel.test.tsx
+++ b/react/src/components/ManageMapProjectPanel/ManageMapProjectPanel.test.tsx
@@ -1,38 +1,12 @@
import React from 'react';
-import { screen, fireEvent } from '@testing-library/react';
+import { within, screen, fireEvent } from '@testing-library/react';
import ManageMapProjectPanel from './ManageMapProjectPanel';
import { projectMock } from '@hazmapper/__fixtures__/projectFixtures';
import { renderInTest, testQueryClient } from '@hazmapper/test/testUtil';
-// Mock the child components
-jest.mock('./MapTabContent', () => {
- return function MockMapTabContent() {
- return
Map Tab Content
;
- };
-});
-
-jest.mock('./MembersTabContent', () => {
- return function MockMembersTabContent() {
- return Members Tab Content
;
- };
-});
-
-jest.mock('./PublicTabContent', () => {
- return function MockPublicTabContent() {
- return Public Tab Content
;
- };
-});
-
-jest.mock('./SaveTabContent', () => {
- return function MockSaveTabContent() {
- return Save Tab Content
;
- };
-});
-
describe('ManageMapProjectPanel', () => {
const defaultProps = {
project: projectMock,
- onProjectUpdate: jest.fn(),
};
beforeEach(() => {
@@ -40,36 +14,34 @@ describe('ManageMapProjectPanel', () => {
testQueryClient.clear();
});
- it('renders all tab buttons', () => {
+ it('renders the default Map tab content initially', () => {
renderInTest();
- expect(screen.getByRole('tab', { name: 'Map' })).toBeTruthy();
- expect(screen.getByRole('tab', { name: 'Members' })).toBeTruthy();
- expect(screen.getByRole('tab', { name: 'Public' })).toBeTruthy();
- expect(screen.getByRole('tab', { name: 'Save' })).toBeTruthy();
- });
+ // Get the active tab container
+ const activeTab = screen.getByRole('tabpanel', { hidden: false });
- it('renders map tab content by default', () => {
- renderInTest();
+ // Ensure the active tab contains "Map Details"
+ expect(within(activeTab).getByText(/Map Details/i)).toBeDefined();
- expect(screen.getByTestId('map-tab-content')).toBeTruthy();
+ // Ensure other tab content is NOT present in the active tab
+ expect(within(activeTab).queryByText(/Members/i)).toBeNull();
+ expect(within(activeTab).queryByText(/Public Access/i)).toBeNull();
+ expect(within(activeTab).queryByText(/Save Location/i)).toBeNull();
});
+
it('switches between tabs correctly', () => {
renderInTest();
- // Click Members tab
- const membersTab = screen.getByRole('tab', { name: 'Members' });
- fireEvent.click(membersTab);
- expect(screen.getByTestId('members-tab-content')).toBeTruthy();
+ // Click "Members" tab
+ fireEvent.click(screen.getByRole('tab', { name: 'Members' }));
+
+ // Get the newly active tab container
+ const activeTab = screen.getByRole('tabpanel', { hidden: false });
- // Click Public tab
- const publicTab = screen.getByRole('tab', { name: 'Public' });
- fireEvent.click(publicTab);
- expect(screen.getByTestId('public-tab-content')).toBeTruthy();
+ // Ensure the "Members" tab content is now visible
+ expect(within(activeTab).getByText(/Members/i)).toBeDefined();
- // Click Save tab
- const saveTab = screen.getByRole('tab', { name: 'Save' });
- fireEvent.click(saveTab);
- expect(screen.getByTestId('save-tab-content')).toBeTruthy();
+ // Ensure the previous tab content is NOT present in the active tab
+ expect(within(activeTab).queryByText(/Map Details/i)).toBeNull();
});
});
diff --git a/react/src/components/ManageMapProjectPanel/MapTabContent.test.tsx b/react/src/components/ManageMapProjectPanel/MapTabContent.test.tsx
new file mode 100644
index 00000000..f18a57dd
--- /dev/null
+++ b/react/src/components/ManageMapProjectPanel/MapTabContent.test.tsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import { screen, fireEvent, waitFor } from '@testing-library/react';
+import { renderInTest } from '@hazmapper/test/testUtil';
+import { projectMock } from '@hazmapper/__fixtures__/projectFixtures';
+import { testDevConfiguration } from '@hazmapper/__fixtures__/appConfigurationFixture';
+import MapTabContent from './MapTabContent';
+
+const mockNavigate = jest.fn();
+
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useNavigate: () => mockNavigate,
+}));
+
+describe('MapTabContent', () => {
+ const mockOnProjectUpdate = jest.fn();
+
+ beforeEach(() => {
+ mockNavigate.mockClear();
+ jest.clearAllMocks();
+ });
+
+ it('renders project details correctly', () => {
+ renderInTest(
+
+ );
+
+ expect(screen.getByText('Name:')).toBeDefined();
+ expect(screen.getByText(projectMock.name)).toBeDefined();
+
+ expect(screen.getByText('Description:')).toBeDefined();
+ expect(screen.getByText(projectMock.description)).toBeDefined();
+ });
+
+ it('navigates to Taggit when "View in Taggit" button is clicked', async () => {
+ renderInTest(
+
+ );
+
+ const taggitButton = screen.getByTestId('taggit-button');
+ fireEvent.click(taggitButton);
+
+ await waitFor(() => {
+ // Taggit will read from local storage
+ expect(localStorage.getItem('testLastProject')).toBe(
+ JSON.stringify(projectMock)
+ );
+ });
+ await waitFor(() => expect(mockNavigate).toHaveBeenCalledTimes(1));
+ expect(mockNavigate).toHaveBeenCalledWith(testDevConfiguration.taggitUrl);
+ });
+});
diff --git a/react/src/components/ManageMapProjectPanel/MapTabContent.tsx b/react/src/components/ManageMapProjectPanel/MapTabContent.tsx
index 423bbecc..3f84d3aa 100644
--- a/react/src/components/ManageMapProjectPanel/MapTabContent.tsx
+++ b/react/src/components/ManageMapProjectPanel/MapTabContent.tsx
@@ -3,6 +3,7 @@ import { Project, ProjectRequest } from '@hazmapper/types';
import { SectionMessage } from '@tacc/core-components';
import { EditFilled, CheckOutlined, DeleteOutlined } from '@ant-design/icons';
import { Button, Flex, List, Input, Modal } from 'antd';
+import { useNavigate } from 'react-router-dom';
import { useAppConfiguration } from '@hazmapper/hooks';
import DeleteMapModal from '../DeleteMapModal/DeleteMapModal';
@@ -65,6 +66,19 @@ const MapTabContent: React.FC = ({
const config = useAppConfiguration();
+ const navigate = useNavigate();
+
+ const navigateToCorrespondingTaggitGallery = () => {
+ // We set some info in local storage for Taggit and then navigate to Taggit
+
+ // key for local storage is backend-specific
+ const lastProjectKeyword = `${config.geoapiEnv}LastProject`;
+
+ // note that entire project gets stringified but only `id` is used by taggit
+ localStorage.setItem(lastProjectKeyword, JSON.stringify(project));
+ navigate(config.taggitUrl);
+ };
+
return (
<>
@@ -105,11 +119,9 @@ const MapTabContent: React.FC = ({
diff --git a/react/src/hooks/environment/getLocalAppConfiguration.ts b/react/src/hooks/environment/getLocalAppConfiguration.ts
index 17a8df80..b6a134b5 100644
--- a/react/src/hooks/environment/getLocalAppConfiguration.ts
+++ b/react/src/hooks/environment/getLocalAppConfiguration.ts
@@ -36,11 +36,12 @@ export const getLocalAppConfiguration = (
const appConfig: AppConfiguration = {
basePath: basePath,
+ geoapiEnv: localDevelopmentConfiguration.geoapiBackend,
geoapiUrl: getGeoapiUrl(localDevelopmentConfiguration.geoapiBackend),
designsafePortalUrl: getDesignsafePortalUrl(designSafePortal),
tapisUrl: 'https://designsafe.tapis.io',
mapillary: mapillaryConfig,
- taggitUrl: origin + '/taggit-staging',
+ taggitUrl: origin + '/taggit-local', // TODO: we don't support allowing taggit to run at the same time in local dev env
};
appConfig.mapillary.clientId = '5156692464392931';
appConfig.mapillary.clientSecret =
diff --git a/react/src/hooks/environment/useAppConfiguration.ts b/react/src/hooks/environment/useAppConfiguration.ts
index 64531470..8cd83b3b 100644
--- a/react/src/hooks/environment/useAppConfiguration.ts
+++ b/react/src/hooks/environment/useAppConfiguration.ts
@@ -46,6 +46,7 @@ export const useAppConfiguration = (): AppConfiguration => {
) {
const appConfig: AppConfiguration = {
basePath: basePath,
+ geoapiEnv: GeoapiBackendEnvironment.Staging,
geoapiUrl: getGeoapiUrl(GeoapiBackendEnvironment.Staging),
designsafePortalUrl: getDesignsafePortalUrl(
DesignSafePortalEnvironment.PPRD
@@ -67,6 +68,7 @@ export const useAppConfiguration = (): AppConfiguration => {
) {
const appConfig: AppConfiguration = {
basePath: basePath,
+ geoapiEnv: GeoapiBackendEnvironment.Dev,
geoapiUrl: getGeoapiUrl(GeoapiBackendEnvironment.Dev),
designsafePortalUrl: getDesignsafePortalUrl(
DesignSafePortalEnvironment.PPRD
@@ -86,6 +88,7 @@ export const useAppConfiguration = (): AppConfiguration => {
} else if (/^hazmapper.tacc.utexas.edu/.test(hostname)) {
const appConfig: AppConfiguration = {
basePath: basePath,
+ geoapiEnv: GeoapiBackendEnvironment.Production,
geoapiUrl: getGeoapiUrl(GeoapiBackendEnvironment.Production),
designsafePortalUrl: getDesignsafePortalUrl(
DesignSafePortalEnvironment.Production
diff --git a/react/src/hooks/environment/utils.ts b/react/src/hooks/environment/utils.ts
index 92b55562..7e6913c8 100644
--- a/react/src/hooks/environment/utils.ts
+++ b/react/src/hooks/environment/utils.ts
@@ -8,6 +8,8 @@ import {
*/
export function getGeoapiUrl(backend: GeoapiBackendEnvironment): string {
switch (backend) {
+ case GeoapiBackendEnvironment.Test:
+ return 'https://geoapi.unittest';
case GeoapiBackendEnvironment.Local:
return 'http://localhost:8888';
case GeoapiBackendEnvironment.Experimental:
diff --git a/react/src/types/environment.ts b/react/src/types/environment.ts
index fb12d0c4..cf8ac619 100644
--- a/react/src/types/environment.ts
+++ b/react/src/types/environment.ts
@@ -7,6 +7,7 @@ export enum GeoapiBackendEnvironment {
Dev = 'dev',
Experimental = 'experimental',
Local = 'local',
+ Test = 'test', // for unit testing
}
/**
@@ -72,6 +73,9 @@ export interface AppConfiguration {
/** Base URL path for the application. */
basePath: string;
+ /** Geoapi environments. */
+ geoapiEnv: GeoapiBackendEnvironment;
+
/** URL for the GeoAPI service. */
geoapiUrl: string;