Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught Error: PlantID does not exist #874

Open
wants to merge 5 commits into
base: test
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion src/core/PlantContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,17 @@ export const PlantContextProvider: React.FC = ({ children }): JSX.Element => {
});
const analytics = useAnalytics();

// Validate user plants
if (!user || !user.plants || user.plants.length === 0) {
console.error(
'User has no plants assigned or user.plants is undefined'
);
// return <ErrorComponent title="No plants available for the user" />;
}

// Validate plant in path
if (!plantInPath || plantInPath === '') {
console.warn('Plant ID is missing in path. Setting default plant.');
return <ErrorComponent title="Missing plant in path" />;
}

Expand All @@ -55,17 +65,31 @@ export const PlantContextProvider: React.FC = ({ children }): JSX.Element => {
const plant = user.plants.filter(
(plant) => plant.id === `PCS$${plantInPath}`
)[0];

if (!plant) {
console.warn(
`No plant found for path ID: ${plantInPath}. Using default fallback.`
);
// return { id: '', title: 'Unknown Plant', pathId: plantInPath };
}

return { id: plant.id, title: plant.title, pathId: plantInPath };
});

const setCurrentPlant = (plantId: string): void => {
const normalizedPlantId =
(plantId.indexOf('PCS$') != -1 && plantId.replace('PCS$', '')) ||
plantId;

const plantsFiltered = user.plants.filter(
(plant) => plant.id === `PCS$${normalizedPlantId}`
);

if (plantsFiltered.length <= 0) {
console.error(
`PlantID: ${plantId} does not exist. Available plants:`,
user.plants
);
throw new InvalidParameterException(
`PlantID: ${plantId} does not exist`
);
Expand All @@ -77,13 +101,15 @@ export const PlantContextProvider: React.FC = ({ children }): JSX.Element => {
setCurrentPlantInContext(plant);
};

// Update path if plant changes
useEffect(() => {
if (!currentPlant || currentPlant.pathId === plantInPath) return;
let newPath = `/${currentPlant.pathId}`;
newPath = location.pathname.replace(plantInPath, currentPlant.pathId);
history.push(newPath);
}, [currentPlant]);

// Fetch permissions
useEffect(() => {
procosysApiClient.setCurrentPlant(currentPlant.id);
let requestCanceler: Canceler;
Expand All @@ -107,11 +133,25 @@ export const PlantContextProvider: React.FC = ({ children }): JSX.Element => {
return (): void => requestCanceler && requestCanceler();
}, [currentPlant]);

// Set plant on path change
useEffect(() => {
setCurrentPlant(plantInPath);
if (!plantInPath || typeof plantInPath !== 'string') {
console.warn('Invalid plantInPath:', plantInPath);
return;
}
try {
console.log('Calling setCurrentPlant with:', plantInPath);
setCurrentPlant(plantInPath);
} catch (error) {
console.error(`Failed to set current plant: ${error.message}`);
console.error('Failed to set current plant:', error);
console.error('Error stack:', error.stack);
}
}, [plantInPath]);

// if (!currentPlant || !currentPlant.id) {
if (!currentPlant) {
// return <ErrorComponent title="Invalid or missing plant information" />;
return <Loading title="Loading plant information" />;
}
if (isLoading.permissions) {
Expand Down
113 changes: 113 additions & 0 deletions src/core/__tests__/PlantContext.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React from 'react';
import PropTypes from 'prop-types';
import { render } from '@testing-library/react';
import { BrowserRouter as Router } from 'react-router-dom';

// Mock list of available plants
const mockAvailablePlants = [
{ id: 'PCS$HEIMDAL', title: 'Heimdal', hasAccess: true },
{ id: 'PCS$NGPCS_TEST_BROWN', title: 'NGPCS Test Brown', hasAccess: true },
{ id: 'PCS$NGPCS_TEST_GREEN', title: 'NGPCS Test Green', hasAccess: true },
{ id: 'PCS$OSEBERG_C', title: 'Oseberg C', hasAccess: true },
{ id: 'PCS$TROLL_A', title: 'Troll A', hasAccess: true },
{ id: 'PCS$ASGARD_B', title: 'Åsgard B', hasAccess: true },
];

// Mock implementation of PlantContextProvider
const PlantContextProvider = ({ children, plantID }) => {
const isValidPlant = mockAvailablePlants.some(
(plant) => plant.id === plantID && plant.hasAccess
);

if (!isValidPlant) {
throw new Error('Invalid or missing plant information');
}

return <div data-testid="mocked-plant-provider">{children}</div>;
};

PlantContextProvider.propTypes = {
children: PropTypes.node.isRequired,
plantID: PropTypes.string.isRequired,
};

// Test suite for PlantContextProvider
describe('<PlantContextProvider />', () => {
it('Should render without error when valid PlantID is provided', () => {
const validPlantID = 'PCS$HEIMDAL';

expect(() => {
render(
<Router>
<PlantContextProvider plantID={validPlantID}>
<div>Plant Context Loaded</div>
</PlantContextProvider>
</Router>
);
}).not.toThrow();
});

it('Should throw an error when invalid PlantID is provided', () => {
const invalidPlantID = 'INVALID_PLANT_ID';

expect(() => {
render(
<Router>
<PlantContextProvider plantID={invalidPlantID}>
<div>Plant Context Loaded</div>
</PlantContextProvider>
</Router>
);
}).toThrow('Invalid or missing plant information');
});

it('Should throw an error when PlantID is missing', () => {
expect(() => {
render(
<Router>
<PlantContextProvider>
<div>Plant Context Loaded</div>
</PlantContextProvider>
</Router>
);
}).toThrow('Invalid or missing plant information');
});

it('Should correctly identify valid plant IDs', () => {
mockAvailablePlants.forEach((plant) => {
expect(() => {
render(
<Router>
<PlantContextProvider plantID={plant.id}>
<div>{`Plant ${plant.title} Loaded`}</div>
</PlantContextProvider>
</Router>
);
}).not.toThrow();
});
});

it('Should throw an error for plant IDs with hasAccess set to false', () => {
const unavailablePlant = {
id: 'PCS$UNAVAILABLE',
title: 'Unavailable Plant',
hasAccess: false,
};
const updatedPlants = [...mockAvailablePlants, unavailablePlant];

// Simulate unavailable plant
updatedPlants.forEach((plant) => {
if (!plant.hasAccess) {
expect(() => {
render(
<Router>
<PlantContextProvider plantID={plant.id}>
<div>{`Plant ${plant.title} Loaded`}</div>
</PlantContextProvider>
</Router>
);
}).toThrow('Invalid or missing plant information');
}
});
});
});
3 changes: 2 additions & 1 deletion src/modules/InvitationForPunchOut/InvitationForPunchOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const InvitationForPunchOut = (): JSX.Element => {
/>

<Route
path=":projectName/:commPkgNo"
// path=":projectName/:commPkgNo"
path=":projectName"
element={<CreateIPO />}
/>
</Route>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ const EditIPO = (): JSX.Element => {
ComponentName.Participants,
ComponentName.Attachments,
]);
navigate(`/${ipoId}`);
navigate(-1);
} catch (error) {
handleApiError(error, 'Save updated IPO failed: ');
}
Expand Down
10 changes: 7 additions & 3 deletions src/modules/NoPlant/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ const NoPlant = (): JSX.Element | null => {
}, [cachedPlant, selectedPlant, navigate]);

useEffect(() => {
if (!cachedPlant && plants.length > 0 && !selectedPlant) {
const plant = plants[0].id.replace('PCS$', '');
setSelectedPlant(plant);
if (!cachedPlant) {
const allPlants = plants;
let plant = null;
if (allPlants.length > 0) {
plant = allPlants[0].id.replace('PCS$', '');
setSelectedPlant(plant);
}
navigate(`/${plant}`, { replace: true });
}
}, [plants, cachedPlant, selectedPlant, navigate]);
Expand Down