Skip to content

Commit

Permalink
Remove react-photoswipe-gallery and use creat custom lightbox
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuadkitenge committed Dec 4, 2024
1 parent 9b6b97e commit c16564c
Show file tree
Hide file tree
Showing 18 changed files with 959 additions and 540 deletions.
138 changes: 117 additions & 21 deletions cypress/e2e/with_mock_data/items.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -767,41 +767,137 @@ describe('Items', () => {
cy.findByText('Gallery').click();

cy.findAllByAltText('Image: stfc-logo-blue-text').first().click();
cy.findByTestId('galleryLightBox').within(() => {
cy.findByText('File name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');

cy.findByText('File Name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');
cy.findByAltText('Image: stfc-logo-blue-text').should('exist');

cy.findByRole('dialog').within(() => {
cy.findByRole('img').should('exist');
cy.findByAltText('Image: stfc-logo-blue-text')
.should('have.attr', 'src')
.and(
'include',
'http://localhost:3000/images/stfc-logo-blue-text.png?text=1'
);

cy.findByLabelText('Next').click();

cy.findByText('File name: logo1.png').should('exist');
cy.findByText('Title: logo1').should('exist');
cy.findByText('test').should('exist');

cy.findByAltText('Image: logo1').should('exist');

cy.findByAltText('Image: logo1')
.should('have.attr', 'src')
.and('include', 'http://localhost:3000/logo192.png?text=2');
cy.findByLabelText('Close').click();
});

cy.findByRole('button', { name: 'Next' }).click();
cy.findByTestId('galleryLightBox').should('not.exist');
});

it('opens corrupted image, and navigates back to previous image (invalid url)', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findByText('File Name: logo1.png').should('exist');
cy.findByText('Title: logo1').should('exist');
cy.findByText('test').should('exist');
cy.findByText('The image cannot be loaded').click();
cy.findByTestId('galleryLightBox').within(() => {
cy.findByText('File name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('No description available').should('exist');

cy.findByRole('dialog').within(() => {
cy.findByRole('img').should('exist');
cy.findByText('The image cannot be loaded').should('exist');

cy.findByLabelText('Previous').click();

cy.findByText('File name: logo1.png').should('exist');
cy.findByText('Title: logo1').should('exist');
cy.findByText('test').should('exist');

cy.findByAltText('Image: logo1').should('exist');

cy.findByAltText('Image: logo1')
.should('have.attr', 'src')
.and('include', 'http://localhost:3000/logo192.png?text=2');
cy.findByLabelText('Close').click();
});

cy.findByRole('button', { name: 'Next' }).click();
// Failed to render image
cy.findByText('File Name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');
cy.findByTestId('galleryLightBox').should('not.exist');
});

cy.findByRole('dialog').within(() => {
cy.findByText('The image cannot be loaded', { timeout: 15000 }).should(
it('opens corrupted image (network error)', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByAltText('Image: stfc-logo-blue-text').eq(1).click();
cy.findByTestId('galleryLightBox').within(() => {
cy.findByText('The image cannot be loaded', { timeout: 10000 }).should(
'exist'
);

cy.findByText('File name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');

cy.findByLabelText('Close').click();
});

cy.findByTestId('galleryLightBox').should('not.exist');
});

it('opens information dialog in lightbox', () => {
cy.findByText('5YUQDDjKpz2z').click();
cy.findByText(
'High-resolution cameras for beam characterization. 1'
).should('exist');

cy.findByText('Gallery').click();

cy.findAllByAltText('Image: stfc-logo-blue-text').first().click();
cy.findByTestId('galleryLightBox').within(() => {
cy.findByText('File name: stfc-logo-blue-text.png').should('exist');
cy.findByText('Title: stfc-logo-blue-text').should('exist');
cy.findByText('test').should('exist');

cy.findByAltText('Image: stfc-logo-blue-text').should('exist');

cy.findByAltText('Image: stfc-logo-blue-text')
.should('have.attr', 'src')
.and(
'include',
'http://localhost:3000/images/stfc-logo-blue-text.png?text=1'
);

cy.findByLabelText('Image Actions').click();
});
// opens action menu

cy.findByRole('button', { name: 'Action menu button' }).click();
cy.findAllByText('Information').last().click();

cy.findByRole('dialog', { timeout: 10000 }).should('exist');

cy.findByRole('dialog').within(() => {
cy.findByText('Image Information').should('exist');
});

cy.findByRole('dialog').within(() => {
cy.findByRole('button', { name: 'Close' }).click();
});

cy.findByRole('dialog').should('not.exist');

cy.findByLabelText('Close').click();

cy.findAllByText('Information').should('have.length', 2);
cy.findByTestId('galleryLightBox').should('not.exist');
});
});

Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@
"lz-string": "^1.5.0",
"material-react-table": "^2.13.0",
"msw": "2.4.11",
"photoswipe": "^5.4.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.52.0",
"react-photoswipe-gallery": "^3.0.2",
"react-redux": "^9.1.2",
"react-router-dom": "^6.23.1",
"single-spa-react": "6.0.2",
Expand Down
20 changes: 19 additions & 1 deletion src/api/images.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { renderHook, waitFor } from '@testing-library/react';
import ImagesJSON from '../mocks/Images.json';
import { hooksWrapperWithProviders } from '../testUtils';
import { useGetImages } from './images';
import { useGetImage, useGetImages } from './images';

describe('images api functions', () => {
afterEach(() => {
Expand Down Expand Up @@ -32,4 +33,21 @@ describe('images api functions', () => {
expect(result.current.data?.length).toEqual(1);
});
});

describe('useGetImage', () => {
it('sends request to fetch image data and returns successful response', async () => {
const { result } = renderHook(() => useGetImage('1'), {
wrapper: hooksWrapperWithProviders(),
});

await waitFor(() => {
expect(result.current.isSuccess).toBeTruthy();
});

expect(result.current.data).toEqual({
...ImagesJSON[1],
url: 'http://localhost:3000/images/stfc-logo-blue-text.png?text=1',
});
});
});
});
10 changes: 10 additions & 0 deletions src/api/images.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ export const getImage = async (id: string): Promise<ImageGet> => {
});
};

export const useGetImage = (
id?: string
): UseQueryResult<ImageGet, AxiosError> => {
return useQuery({
queryKey: ['Image', id],
queryFn: () => getImage(id ?? ''),
enabled: !!id,
});
};

const getImages = async (
entityId: string,
primary?: boolean
Expand Down
88 changes: 88 additions & 0 deletions src/common/delayedLoader.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { act, render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import DelayedLoader from './delayedLoader.component';

vi.useFakeTimers();

describe('DelayedLoader', () => {
it('should render the loader after the specified delay', () => {
const timeMS = 2000;

render(
<DelayedLoader
timeMS={timeMS}
isLoading={true}
sx={{ color: 'primary' }}
/>
);
expect(screen.queryByRole('progressbar')).toBeNull();

act(() => {
vi.advanceTimersByTime(timeMS);
});

expect(screen.getByRole('progressbar')).toBeInTheDocument();
});

it('should not render the loader if isLoading is false', () => {
render(
<DelayedLoader
timeMS={2000}
isLoading={false}
sx={{ color: 'primary' }}
/>
);
expect(screen.queryByRole('progressbar')).toBeNull();
});

it('should remove the loader if isLoading changes to false before the delay', () => {
const timeMS = 2000;
const { rerender } = render(
<DelayedLoader
timeMS={timeMS}
isLoading={true}
sx={{ color: 'primary' }}
/>
);
expect(screen.queryByRole('progressbar')).toBeNull();

rerender(
<DelayedLoader
timeMS={timeMS}
isLoading={false}
sx={{ color: 'primary' }}
/>
);
act(() => {
vi.advanceTimersByTime(timeMS);
});

expect(screen.queryByRole('progressbar')).toBeNull();
});

it('should remove the loader when isLoading changes to false after being displayed', () => {
const timeMS = 2000;
const { rerender } = render(
<DelayedLoader
timeMS={timeMS}
isLoading={true}
sx={{ color: 'primary' }}
/>
);

act(() => {
vi.advanceTimersByTime(timeMS);
});

expect(screen.getByRole('progressbar')).toBeInTheDocument();

rerender(
<DelayedLoader
timeMS={timeMS}
isLoading={false}
sx={{ color: 'primary' }}
/>
);
expect(screen.queryByRole('progressbar')).toBeNull();
});
});
34 changes: 34 additions & 0 deletions src/common/delayedLoader.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { SxProps, Theme } from '@mui/material';
import CircularProgress from '@mui/material/CircularProgress';
import React from 'react';

interface DelayedLoaderProps {
timeMS: number;
isLoading: boolean;
sx: SxProps<Theme>;
}

const DelayedLoader = (props: DelayedLoaderProps) => {
const { timeMS, isLoading, sx } = props;
const [showLoader, setShowLoader] = React.useState(false);

React.useEffect(() => {
let timeout: NodeJS.Timeout | null = null;

if (isLoading) {
timeout = setTimeout(() => {
setShowLoader(true);
}, timeMS);
} else {
setShowLoader(false);
}

return () => {
if (timeout) clearTimeout(timeout);
};
}, [isLoading, timeMS]);

return <>{showLoader && <CircularProgress sx={sx} />}</>;
};

export default DelayedLoader;
Loading

0 comments on commit c16564c

Please sign in to comment.