Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b9933a2
added auth to Contribute PL,PL Info, Search by name & address res, Se…
Feb 18, 2025
19255b1
added task description
Feb 18, 2025
4fc075d
fixed old and added new auth tests for ContributeProductionLocation.test
Feb 18, 2025
149d831
fixed old and added new auth tests for SearchByOsIdResult.test
Feb 19, 2025
5f9fe63
moved AuthLogInFromRoute to separate component
Feb 19, 2025
ada1ca7
added AuthLogInFromRoute.test
Feb 19, 2025
e83ac48
added prop types
Feb 19, 2025
c7e719d
removed duplicate of Settings.jsx
Feb 20, 2025
0f5216b
added chek to Dashboard and removed from DashboardApiBlock because is…
Feb 20, 2025
5f441cd
added userHasSignedIn to propTypes for Dashboard
Feb 20, 2025
14262b8
merged main
Feb 20, 2025
a81e227
corrected tests, removed const
Feb 21, 2025
359da3d
removed extra space
Feb 21, 2025
412adac
Merge branch 'main' into OSDEV-1747-check-auth-for-slc-pages
Innavin369 Feb 21, 2025
f889503
fixed linter
Feb 21, 2025
cdba2f6
reuse one import
Feb 21, 2025
b9779e3
linter
Feb 21, 2025
77a7a64
Merge branch 'main' into OSDEV-1747-check-auth-for-slc-pages
Feb 21, 2025
3ce9ff5
import order
Feb 21, 2025
47a4786
Merge branch 'main' into OSDEV-1747-check-auth-for-slc-pages
Innavin369 Feb 25, 2025
f378803
merged main
Feb 26, 2025
02c7c4b
reamed component from AuthLogInFromRoute to RequireAuthNotice
Feb 26, 2025
1db4e28
updated link texts
Feb 26, 2025
3e89a17
resolved conflict
Feb 26, 2025
b1902ce
removed duplication
Feb 26, 2025
f8dde92
added test for loader, removed comma, moved Contribute to const
Feb 26, 2025
7370a7a
fixed auth in ProductionLocationInfo.test
Feb 26, 2025
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
1 change: 1 addition & 0 deletions doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
* *Describe architecture/environment changes here.*

### Bugfix
* [OSDEV-1747](https://opensupplyhub.atlassian.net/browse/OSDEV-1747) - All SLC pages have been made accessible only to authorized users.
* [OSDEV-1777](https://opensupplyhub.atlassian.net/browse/OSDEV-1777) - A consistent URL style was established across all pages of the SLC workflow. After the changes, the URL begins from `/contribute/single-location/`.
* [OSDEV-1678](https://opensupplyhub.atlassian.net/browse/OSDEV-1678) - Added asterisks next to each required form field (Name, Address, and Country) on the "Production Location Information" page. Highlighted an empty field and displayed an error message if it loses focus.

Expand Down
52 changes: 52 additions & 0 deletions src/react/src/__tests__/components/AuthLogInFromRoute.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import { Router } from "react-router-dom";
import { fireEvent } from '@testing-library/react';
import history from '../../util/history';
import renderWithProviders from '../../util/testUtils/renderWithProviders';
import {
authLoginFormRoute,
} from '../../util/constants';
import RequireAuthNotice from '../../components/RequireAuthNotice';

describe('RequireAuthNotice component', () => {
const renderComponent = (preloadedState = {}) =>
renderWithProviders(
<Router history={history}>
<RequireAuthNotice {...preloadedState}/>,
</Router>
);

beforeEach(() => {
jest.clearAllMocks();
});

test("renders component with default params", () => {
const defaultTitle = 'Unauthorized Access';
const defaultText = 'Log in to contribute to Open Supply Hub';

const { getByText, getByRole } = renderComponent();
const titleEl = getByRole("heading", { level: 2 });
const titleText = titleEl.textContent.trim();
const linkEl = getByRole("link", { name: defaultText });

expect(titleEl).toBeInTheDocument();
expect(defaultTitle).toBe(titleText);
expect(getByText(defaultText)).toBeInTheDocument();

fireEvent.click(linkEl);
expect(history.location.pathname).toBe(authLoginFormRoute);
});

test("renders component with set params", () => {
const expectedTitle = "Test title";
const expectedText = "Test text";
const preloadedState = {
title: expectedTitle,
text: expectedText,
}
const { getByText } = renderComponent(preloadedState);

expect(getByText(expectedTitle)).toBeInTheDocument();
expect(getByText(expectedText)).toBeInTheDocument();
});
})
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,75 @@ jest.mock('../../components/Contribute/SearchByOsIdTab', () => () => <div>Mocked
jest.mock('../../components/Contribute/SearchByNameAndAddressTab', () => () => <div>Mocked SearchByNameAndAddressTab</div>);

describe('ContributeProductionLocation component', () => {
const renderComponent = (queryParams = '') =>
const mockAuthorizedState = {
auth: {
user: { user: { isAnon: false } },
session: { fetching: false },
},
};

const mockNotAuthorizedState = {
auth: {
user: { user: { isAnon: true } },
session: { fetching: false },
},
};

const renderComponent = (preloadedState = {}, queryParams = '') =>
renderWithProviders(
<MemoryRouter initialEntries={[`/contribute/single-location${queryParams}`]}>
<ContributeProductionLocation />
</MemoryRouter>
</MemoryRouter>,
{ preloadedState }
);

beforeEach(() => {
jest.clearAllMocks();
});

it('renders for the unauthorized user', () => {
const expectedTitle = 'Production Location Search'
const { getByText, getByRole } = renderComponent(mockNotAuthorizedState);
const linkElement = getByRole('link', { name: /Log in to contribute to Open Supply Hub/i });

expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute('href', '/auth/login');
expect(getByText('Log in to contribute to Open Supply Hub')).toBeInTheDocument();
expect(getByText(expectedTitle)).toBeInTheDocument();
});

it('renders for the authorized user', () => {
const expectedTitle = 'Production Location Search'
const { getByText, getByRole } = renderComponent(mockAuthorizedState);
const title = getByText(expectedTitle);
const nameAddressTab = getByRole('tab', { name: /Search by name and address/i });
const osIdTab = getByRole('tab', { name: /Search by OS ID/i });

expect(title).toBeInTheDocument();
expect(nameAddressTab).toBeInTheDocument();
expect(osIdTab).toBeInTheDocument();
});

it('renders with the correct title', () => {
const { getByText } = renderComponent();
const { getByText } = renderComponent(mockAuthorizedState);
expect(getByText('Production Location Search')).toBeInTheDocument();
});

it('renders the Name and Address tab as selected by default', () => {
const { getByRole } = renderComponent();
const { getByRole } = renderComponent(mockAuthorizedState);
const nameAddressTab = getByRole('tab', { name: /Search by name and address/i });
expect(nameAddressTab).toHaveAttribute('aria-selected', 'true');
});

it('renders the OS ID tab as unselected by default', () => {
const { getByRole } = renderComponent();
const { getByRole } = renderComponent(mockAuthorizedState);
const osIdTab = getByRole('tab', { name: /Search by OS ID/i });
expect(osIdTab).toHaveAttribute('aria-selected', 'false');
});

it('changes the tab when clicked and updates the URL', () => {
const { getByRole } = renderComponent();
const { getByRole } = renderComponent(mockAuthorizedState);

const nameAddressTab = getByRole('tab', { name: /Search by name and address/i });
const osIdTab = getByRole('tab', { name: /Search by OS ID/i });

Expand All @@ -44,20 +87,20 @@ describe('ContributeProductionLocation component', () => {
});

it('renders SearchByNameAndAddressTab when Name and Address tab is selected', () => {
const { getByText } = renderComponent();
const { getByText } = renderComponent(mockAuthorizedState);
expect(getByText('Mocked SearchByNameAndAddressTab')).toBeInTheDocument();
});

it('renders SearchByOsIdTab when OS ID tab is selected', () => {
const { getByText, getByRole } = renderComponent();
const { getByText, getByRole } = renderComponent(mockAuthorizedState);
const osIdTab = getByRole('tab', { name: /Search by OS ID/i });

fireEvent.click(osIdTab);
expect(getByText('Mocked SearchByOsIdTab')).toBeInTheDocument();
});

it('handles invalid tab and defaults to Name and Address tab', () => {
const { getByRole } = renderComponent('?tab=invalid-tab');
const { getByRole } = renderComponent(mockAuthorizedState,'?tab=invalid-tab');
const nameAddressTab = getByRole('tab', { name: /Search by name and address/i });

expect(nameAddressTab).toHaveAttribute('aria-selected', 'true');
Expand Down
52 changes: 45 additions & 7 deletions src/react/src/__tests__/components/SearchByOsIdResult.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,38 @@ import renderWithProviders from '../../util/testUtils/renderWithProviders';


describe('SearchByOsIdResult component', () => {

const renderComponent = (detailOverride) => {
const mockNotAuthorizedState = {
auth: {
user: { user: { isAnon: true } },
session: { fetching: false },
},
};

const renderComponent = (detailOverride, authOverride) => {
const preloadedState = {
contributeProductionLocation: {
singleProductionLocation: {
data: {},
fetching: false,

singleProductionLocation: {
data: {},
fetching: false,
...detailOverride,
},
},
auth: {
user: { user: { isAnon: false } },
session: { fetching: false },
},
...authOverride,
};

return renderWithProviders(
<Router history={history}>
<SearchByOsIdResult />
</Router>,
{ preloadedState }
);
};

beforeEach(() => {
jest.clearAllMocks();
});
Expand All @@ -36,6 +48,32 @@ describe('SearchByOsIdResult component', () => {
expect(getByText('Production Location Search')).toBeInTheDocument();
});

it('renders for the unauthorized user', () => {
const expectedTitle = 'Production Location Search'
const { getByText, getByRole } = renderComponent({}, mockNotAuthorizedState);
const linkElement = getByRole('link', { name: /Log in to contribute to Open Supply Hub/i });

expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute('href', '/auth/login');
expect(getByText('Log in to contribute to Open Supply Hub')).toBeInTheDocument();
expect(getByText(expectedTitle)).toBeInTheDocument();
});

it('renders for the authorized user', () => {
const expectedTitle = 'Production Location Search'
const { getByText, getByRole } = renderComponent();
const title = getByText(expectedTitle);
const backToIdBtn = getByRole('button', { name: /Back to ID search/i });
const byNameAndIdBtn = getByRole('button', { name: /Search by Name and Address/i });
const anotherIdBtn = getByRole('button', { name: /Search for another ID/i });


expect(title).toBeInTheDocument();
expect(backToIdBtn).toBeInTheDocument();
expect(byNameAndIdBtn).toBeInTheDocument();
expect(anotherIdBtn).toBeInTheDocument();
});

it('shows loading spinner when fetching is true', () => {
const {getByRole} = renderComponent({ fetching: true });

Expand Down
14 changes: 2 additions & 12 deletions src/react/src/components/AddLocationData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import Grid from '@material-ui/core/Grid';
import CircularProgress from '@material-ui/core/CircularProgress';

import AppGrid from './AppGrid';
import RequireAuthNotice from './RequireAuthNotice';

import { openInNewTab } from '../util/util';
import {
authLoginFormRoute,
InfoLink,
InfoPaths,
contributeProductionLocationRoute,
Expand Down Expand Up @@ -43,17 +43,7 @@ function AddLocationData({ classes, userHasSignedIn, fetchingSessionSignIn }) {
}

if (!userHasSignedIn) {
return (
<AppGrid title="Contribute">
<Grid container className="margin-bottom-64">
<Grid item xs={12}>
<Link to={authLoginFormRoute} href={authLoginFormRoute}>
Log in to contribute to Open Supply Hub
</Link>
</Grid>
</Grid>
</AppGrid>
);
return <RequireAuthNotice title="Contribute" />;
}

return (
Expand Down
24 changes: 6 additions & 18 deletions src/react/src/components/Contribute.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ import Paper from '@material-ui/core/Paper';
import AppGrid from './AppGrid';
import AppOverflow from './AppOverflow';
import ContributeForm from './ContributeForm';
import RequireAuthNotice from './RequireAuthNotice';

import {
listsRoute,
authLoginFormRoute,
InfoLink,
InfoPaths,
} from '../util/constants';
import { listsRoute, InfoLink, InfoPaths } from '../util/constants';

function ContributeList({ userHasSignedIn, fetchingSessionSignIn }) {
const TITLE = 'Contribute';

if (fetchingSessionSignIn) {
return (
<AppGrid title="Contribute">
<AppGrid title={TITLE}>
<Grid container className="margin-bottom-64">
<Grid item xs={12}>
<CircularProgress />
Expand All @@ -31,17 +29,7 @@ function ContributeList({ userHasSignedIn, fetchingSessionSignIn }) {
}

if (!userHasSignedIn) {
return (
<AppGrid title="Contribute">
<Grid container className="margin-bottom-64">
<Grid item xs={12}>
<Link to={authLoginFormRoute} href={authLoginFormRoute}>
Log in to contribute to Open Supply Hub
</Link>
</Grid>
</Grid>
</AppGrid>
);
return <RequireAuthNotice title={TITLE} />;
}

return (
Expand Down
Loading
Loading