@treely/strapi-slices 7.15.0 → 7.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,8 +62,8 @@ declare const getMessages: (locale: string) => {
62
62
  'features.projectInfo.properties.verificationStandard.label': string;
63
63
  'features.projectInfo.properties.verificationStandard.value.SilvaconsultFCSISO14': string;
64
64
  'features.projectInfo.properties.verificationStandard.value.MfKWCH': string;
65
- 'features.projectInfo.properties.forecastedAmountYear.label': string;
66
- 'features.projectInfo.properties.forecastedAmountYear.toolTip': string;
65
+ 'features.projectInfo.properties.projectVolume.label': string;
66
+ 'features.projectInfo.properties.projectVolume.toolTip': string;
67
67
  'features.projectInfo.properties.riskBuffer': string;
68
68
  'features.projectInfo.properties.year': string;
69
69
  'features.portfolio.documentsDownloadList.projectDocuments': string;
@@ -148,8 +148,8 @@ declare const getMessages: (locale: string) => {
148
148
  'features.projectInfo.properties.verificationStandard.label': string;
149
149
  'features.projectInfo.properties.verificationStandard.value.SilvaconsultFCSISO14': string;
150
150
  'features.projectInfo.properties.verificationStandard.value.MfKWCH': string;
151
- 'features.projectInfo.properties.forecastedAmountYear.toolTip': string;
152
- 'features.projectInfo.properties.forecastedAmountYear.label': string;
151
+ 'features.projectInfo.properties.projectVolume.toolTip': string;
152
+ 'features.projectInfo.properties.projectVolume.label': string;
153
153
  'features.projectInfo.properties.riskBuffer': string;
154
154
  'features.projectInfo.properties.year': string;
155
155
  'features.portfolio.documentsDownloadList.projectDocuments': string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treely/strapi-slices",
3
- "version": "7.15.0",
3
+ "version": "7.15.2",
4
4
  "license": "MIT",
5
5
  "author": "Tree.ly FlexCo",
6
6
  "description": "@treely/strapi-slices is a open source library maintained by Tree.ly.",
@@ -87,7 +87,7 @@ describe('The ProjectInfo component', () => {
87
87
 
88
88
  const tooltip = await screen.findByRole('tooltip');
89
89
  expect(tooltip).toHaveTextContent(
90
- messagesEn['features.projectInfo.properties.forecastedAmountYear.toolTip']
90
+ messagesEn['features.projectInfo.properties.projectVolume.toolTip']
91
91
  );
92
92
 
93
93
  await userEvent.unhover(trigger);
@@ -43,7 +43,6 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
43
43
  subtitles,
44
44
  }: ProjectInfoProps) => {
45
45
  const { formatMessage, formatNumber, formatDate } = useContext(IntlContext);
46
-
47
46
  return (
48
47
  <Container p="2" width="full">
49
48
  <Heading size="xl" textAlign="left">
@@ -196,7 +195,9 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
196
195
  <></>
197
196
  )}
198
197
 
199
- {project.averageSellableAmountPerYear !== 0 || project.riskBuffer ? (
198
+ {(project.averageSellableAmountPerYear &&
199
+ project.averageSellableAmountPerYear > 0) ||
200
+ project.riskBuffer ? (
200
201
  <>
201
202
  <Spacer height="8" />
202
203
  <Divider />
@@ -206,16 +207,16 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
206
207
  <></>
207
208
  )}
208
209
  <SimpleGrid columns={[1, null, null, 2]} spacingX="10" spacingY="8">
209
- {project.averageSellableAmountPerYear !== 0 && (
210
+ {project.averageSellableAmountPerYear > 0 ? (
210
211
  <Tooltip
211
212
  label={formatMessage({
212
- id: 'features.projectInfo.properties.forecastedAmountYear.toolTip',
213
+ id: 'features.projectInfo.properties.projectVolume.toolTip',
213
214
  })}
214
215
  >
215
216
  <Box>
216
217
  <LabelTextPair
217
218
  label={formatMessage({
218
- id: 'features.projectInfo.properties.forecastedAmountYear.label',
219
+ id: 'features.projectInfo.properties.projectVolume.label',
219
220
  })}
220
221
  text={formatMessage(
221
222
  {
@@ -234,6 +235,10 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
234
235
  />
235
236
  </Box>
236
237
  </Tooltip>
238
+ ) : (
239
+ <Box>
240
+ <CreditsAvailableBadge status={project.creditAvailability} />
241
+ </Box>
237
242
  )}
238
243
 
239
244
  {project.riskBuffer && (
@@ -252,9 +257,13 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
252
257
  )}
253
258
  </SimpleGrid>
254
259
 
255
- <Box mt="2">
256
- <CreditsAvailableBadge status={project.creditAvailability} />
257
- </Box>
260
+ {project.averageSellableAmountPerYear > 0 ? (
261
+ <Box mt="2">
262
+ <CreditsAvailableBadge status={project.creditAvailability} />
263
+ </Box>
264
+ ) : (
265
+ <></>
266
+ )}
258
267
  </Container>
259
268
  );
260
269
  };
@@ -12,10 +12,9 @@ const messagesDe = {
12
12
  'SILVACONSULT® Forest Carbon Standard, ISO 14064-2',
13
13
  'features.projectInfo.properties.verificationStandard.value.MfKWCH':
14
14
  'Methodik für Klimaschutzprojekte im Wald für die Schweiz',
15
- 'features.projectInfo.properties.forecastedAmountYear.toolTip':
16
- 'Dies ist der jährlich verkaufbare Betrag an Credits pro Jahr im Durchschnitt. Dieser Wert repräsentiert nicht die Verfügbarkeiten.',
17
- 'features.projectInfo.properties.forecastedAmountYear.label':
18
- 'Projektvolumen',
15
+ 'features.projectInfo.properties.projectVolume.toolTip':
16
+ 'Dies ist die durchschnittliche Anzahl der Credits, die pro Jahr ausgestellt werden. Dieser Wert entspricht nicht den Verfügbarkeiten.',
17
+ 'features.projectInfo.properties.projectVolume.label': 'Projektvolumen',
19
18
  'features.projectInfo.properties.riskBuffer': 'Anteil Risikopuffer',
20
19
 
21
20
  'features.projectInfo.properties.year':
@@ -12,9 +12,8 @@ const messagesEn = {
12
12
  'SILVACONSULT® Forest Carbon Standard, ISO 14064-2',
13
13
  'features.projectInfo.properties.verificationStandard.value.MfKWCH':
14
14
  'Methodik für Klimaschutzprojekte im Wald für die Schweiz',
15
- 'features.projectInfo.properties.forecastedAmountYear.label':
16
- 'Project Volume',
17
- 'features.projectInfo.properties.forecastedAmountYear.toolTip':
15
+ 'features.projectInfo.properties.projectVolume.label': 'Project Volume',
16
+ 'features.projectInfo.properties.projectVolume.toolTip':
18
17
  "This is the average amount of credits that are issued per year. This value doesn't represent availabilities.",
19
18
  'features.projectInfo.properties.riskBuffer': 'Risk Buffer Share',
20
19
 
@@ -0,0 +1,24 @@
1
+ import MockAxios from 'jest-mock-axios';
2
+ import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
3
+ import getFpmProjectById from './getFpmProjectById';
4
+
5
+ describe('The getFpmProjectById function', () => {
6
+ afterEach(() => {
7
+ MockAxios.reset();
8
+ });
9
+
10
+ it('fetches FPM project by ID successfully', async () => {
11
+ const projectId = 'test-project-1';
12
+ const projectPromise = getFpmProjectById(projectId);
13
+
14
+ MockAxios.mockResponseFor(
15
+ { url: `/public/projects/${projectId}` },
16
+ { data: fpmProjectMock }
17
+ );
18
+
19
+ const result = await projectPromise;
20
+
21
+ expect(result).toEqual(fpmProjectMock);
22
+ expect(MockAxios.get).toHaveBeenCalledWith(`/public/projects/${projectId}`);
23
+ });
24
+ });
@@ -0,0 +1,12 @@
1
+ import FPMProject from '../../models/fpm/FPMProject';
2
+ import fpmClient from '../fpmClient';
3
+
4
+ const getFpmProjectById = async (projectId: string): Promise<FPMProject> => {
5
+ const fpmResponse = await fpmClient.get<FPMProject>(
6
+ `/public/projects/${projectId}`
7
+ );
8
+
9
+ return fpmResponse.data;
10
+ };
11
+
12
+ export default getFpmProjectById;
@@ -2,76 +2,55 @@ import MockAxios from 'jest-mock-axios';
2
2
  import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
3
3
  import { strapiProjectMock } from '../../test/strapiMocks/strapiProject';
4
4
  import getPortfolioProjects from './getPortfolioProjects';
5
- import fpmClient from '../fpmClient';
6
- import strapiClient from './strapiClient';
7
-
8
- // Mock the fpmClient module
9
- jest.mock('../fpmClient', () => ({
10
- __esModule: true,
11
- default: {
12
- get: jest.fn(),
13
- },
14
- }));
15
-
16
- // Mock the strapiClient module
17
- jest.mock('./strapiClient', () => ({
18
- __esModule: true,
19
- default: {
20
- get: jest.fn(),
21
- },
22
- }));
23
5
 
24
6
  describe('The getPortfolioProjects function', () => {
25
7
  afterEach(() => {
26
8
  MockAxios.reset();
27
- jest.clearAllMocks();
28
9
  });
29
10
 
30
11
  it('returns the FPM projects with the slug from strapi', async () => {
31
- // Mock fpmClient responses
32
- (fpmClient.get as jest.Mock)
33
- .mockResolvedValueOnce({ data: [fpmProjectMock] }) // /public/projects
34
- .mockResolvedValueOnce({
35
- data: { ...fpmProjectMock, averageSellableAmountPerYear: 1000 },
36
- }); // /public/projects/${id}
12
+ const projectsPromise = getPortfolioProjects();
37
13
 
38
- // Mock strapiClient responses
39
- (strapiClient.get as jest.Mock)
40
- .mockResolvedValueOnce({ data: { data: [strapiProjectMock] } }) // First /projects call
41
- .mockResolvedValueOnce({ data: { data: [] } }); // Second /projects call
14
+ MockAxios.mockResponseFor(
15
+ { url: '/public/projects' },
16
+ { data: [fpmProjectMock] }
17
+ );
18
+ MockAxios.mockResponseFor(
19
+ { url: '/projects' },
20
+ { data: { data: [strapiProjectMock] } }
21
+ );
22
+ MockAxios.mockResponseFor({ url: '/projects' }, { data: { data: [] } });
42
23
 
43
- const projects = await getPortfolioProjects();
24
+ const projects = await projectsPromise;
44
25
 
45
26
  expect(projects.length).toBe(1);
46
27
  expect(projects[0]).toStrictEqual({
47
28
  ...fpmProjectMock,
48
29
  slug: strapiProjectMock.attributes.slug,
49
30
  creditAvailability: fpmProjectMock.creditAvailability,
50
- averageSellableAmountPerYear: 1000,
51
31
  });
52
32
  });
53
33
 
54
34
  it('returns the FPM project in english if no localized version is available', async () => {
55
- // Mock fpmClient responses
56
- (fpmClient.get as jest.Mock)
57
- .mockResolvedValueOnce({ data: [fpmProjectMock] }) // /public/projects
58
- .mockResolvedValueOnce({
59
- data: { ...fpmProjectMock, averageSellableAmountPerYear: 1000 },
60
- }); // /public/projects/${id}
35
+ const projectsPromise = getPortfolioProjects('de');
61
36
 
62
- // Mock strapiClient responses
63
- (strapiClient.get as jest.Mock)
64
- .mockResolvedValueOnce({ data: { data: [] } }) // First /projects call (localized)
65
- .mockResolvedValueOnce({ data: { data: [strapiProjectMock] } }); // Second /projects call (english fallback)
37
+ MockAxios.mockResponseFor(
38
+ { url: '/public/projects' },
39
+ { data: [fpmProjectMock] }
40
+ );
41
+ MockAxios.mockResponseFor({ url: '/projects' }, { data: { data: [] } });
42
+ MockAxios.mockResponseFor(
43
+ { url: '/projects' },
44
+ { data: { data: [strapiProjectMock] } }
45
+ );
66
46
 
67
- const projects = await getPortfolioProjects('de');
47
+ const projects = await projectsPromise;
68
48
 
69
49
  expect(projects.length).toBe(1);
70
50
  expect(projects[0]).toStrictEqual({
71
51
  ...fpmProjectMock,
72
52
  slug: strapiProjectMock.attributes.slug,
73
53
  creditAvailability: fpmProjectMock.creditAvailability,
74
- averageSellableAmountPerYear: 1000,
75
54
  });
76
55
  });
77
56
  });
@@ -15,45 +15,24 @@ const getPortfolioProjects = async (
15
15
  getStrapiProjects(locale, STRAPI_DEFAULT_POPULATE_DEPTH, preview),
16
16
  ]);
17
17
 
18
- return Promise.all(
19
- fpmProjects.map(async (fpmProject: FPMProject) => {
20
- // fetch the averageSellableAmountPerYear for each project
21
- try {
22
- const fpmProjectWithAverageSellableAmountPerYear =
23
- await fpmClient.get<FPMProject>(`/public/projects/${fpmProject.id}`, {
24
- cache,
25
- });
26
-
27
- fpmProject.averageSellableAmountPerYear =
28
- fpmProjectWithAverageSellableAmountPerYear.data.averageSellableAmountPerYear;
29
- // Handle 404 errors for private projects
30
- } catch (error: any) {
31
- if (error.response?.status === 404) {
32
- fpmProject.averageSellableAmountPerYear = 0;
33
- } else {
34
- // Re-throw other errors
35
- throw error;
36
- }
37
- }
38
-
39
- const strapiProject = strapiProjects.get(fpmProject.id);
40
-
41
- const toReturn: PortfolioProject = fpmProject;
42
-
43
- if (strapiProject?.attributes.slug) {
44
- toReturn.slug = strapiProject.attributes.slug;
45
- }
46
- if (strapiProject?.attributes.thumbnail) {
47
- toReturn.thumbnail = strapiProject?.attributes.thumbnail;
48
- }
49
- if (strapiProject?.attributes.portfolio.data?.attributes.host) {
50
- toReturn.portfolioHost =
51
- strapiProject.attributes.portfolio.data.attributes.host;
52
- }
53
-
54
- return toReturn;
55
- })
56
- );
18
+ return fpmProjects.map((fpmProject: FPMProject) => {
19
+ const strapiProject = strapiProjects.get(fpmProject.id);
20
+
21
+ const toReturn: PortfolioProject = fpmProject;
22
+
23
+ if (strapiProject?.attributes.slug) {
24
+ toReturn.slug = strapiProject.attributes.slug;
25
+ }
26
+ if (strapiProject?.attributes.thumbnail) {
27
+ toReturn.thumbnail = strapiProject?.attributes.thumbnail;
28
+ }
29
+ if (strapiProject?.attributes.portfolio.data?.attributes.host) {
30
+ toReturn.portfolioHost =
31
+ strapiProject.attributes.portfolio.data.attributes.host;
32
+ }
33
+
34
+ return toReturn;
35
+ });
57
36
  };
58
37
 
59
38
  export default getPortfolioProjects;
@@ -1,21 +1,33 @@
1
1
  import React from 'react';
2
- import { render, screen } from '../../test/testUtils';
2
+ import { render, screen, waitFor } from '../../test/testUtils';
3
3
  import ProjectFacts from '.';
4
4
  import { ProjectFactsProps } from './ProjectFacts';
5
5
  import portfolioProjectMock from '../../test/mocks/portfolioProjectMock';
6
+ import getFpmProjectById from '../../integrations/strapi/getFpmProjectById';
7
+
8
+ // Mock the getFpmProjectById function
9
+ jest.mock('../../integrations/strapi/getFpmProjectById');
10
+ const mockGetFpmProjectById = getFpmProjectById as jest.MockedFunction<
11
+ typeof getFpmProjectById
12
+ >;
6
13
 
7
14
  const defaultProps: ProjectFactsProps = {
8
15
  slice: {
9
16
  projectId: 'project-id-1',
10
17
  },
11
18
  };
19
+
12
20
  const setup = (props: Partial<ProjectFactsProps> = {}) => {
13
21
  const combinedProps = { ...defaultProps, ...props };
14
22
  render(<ProjectFacts {...combinedProps} />);
15
23
  };
16
24
 
17
25
  describe('The ProjectFacts slice', () => {
18
- it('displays nothing if there is no project', () => {
26
+ beforeEach(() => {
27
+ jest.clearAllMocks();
28
+ });
29
+
30
+ it('displays error message if there is no project', () => {
19
31
  setup();
20
32
 
21
33
  expect(
@@ -25,11 +37,47 @@ describe('The ProjectFacts slice', () => {
25
37
  ).toBeInTheDocument();
26
38
  });
27
39
 
28
- it('displays the project info if there is a project', () => {
40
+ it('displays loading state when fetching project data', () => {
41
+ // Mock a delayed response to test loading state
42
+ mockGetFpmProjectById.mockImplementation(
43
+ () =>
44
+ new Promise((resolve) =>
45
+ setTimeout(() => resolve(portfolioProjectMock), 100)
46
+ )
47
+ );
48
+
29
49
  setup({ project: portfolioProjectMock });
30
50
 
31
- expect(
32
- screen.getByText(portfolioProjectMock.location || '')
33
- ).toBeInTheDocument();
51
+ expect(screen.getByText('Loading project data...')).toBeInTheDocument();
52
+ });
53
+
54
+ it('displays the enhanced project info with averageSellableAmountPerYear from FPM data', async () => {
55
+ // Create enhanced FPM data with different averageSellableAmountPerYear
56
+ const enhancedFpmData = {
57
+ ...portfolioProjectMock,
58
+ averageSellableAmountPerYear: 1200000, // Value from FPM findOne project
59
+ };
60
+
61
+ mockGetFpmProjectById.mockResolvedValue(enhancedFpmData);
62
+
63
+ setup({ project: portfolioProjectMock });
64
+
65
+ await waitFor(() => {
66
+ expect(mockGetFpmProjectById).toHaveBeenCalledWith(
67
+ portfolioProjectMock.id
68
+ );
69
+ });
70
+
71
+ await waitFor(() => {
72
+ expect(mockGetFpmProjectById).toHaveBeenCalledTimes(1);
73
+ });
74
+
75
+ await waitFor(() => {
76
+ expect(
77
+ screen.queryByText('Loading project data...')
78
+ ).not.toBeInTheDocument();
79
+
80
+ expect(screen.getByText('1,200 tCO₂/year')).toBeInTheDocument();
81
+ });
34
82
  });
35
83
  });
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { DefaultSectionContainer, Flex, Wrapper } from 'boemly';
3
3
  import StrapiLink from '../../models/strapi/StrapiLink';
4
4
  import PortfolioProject from '../../models/PortfolioProject';
@@ -7,6 +7,7 @@ import ProjectInfo from '../../components/portfolio/ProjectInfo';
7
7
  import DocumentsDownloadList from '../../components/portfolio/DocumentsDownloadList';
8
8
  import Contact from '../../components/portfolio/Contact';
9
9
  import StrapiImage from '../../models/strapi/StrapiImage';
10
+ import getFpmProjectById from '../../integrations/strapi/getFpmProjectById';
10
11
 
11
12
  export interface ProjectFactsProps {
12
13
  project?: PortfolioProject;
@@ -47,17 +48,61 @@ export const ProjectFacts: React.FC<ProjectFactsProps> = ({
47
48
  slice,
48
49
  project,
49
50
  }: ProjectFactsProps) => {
50
- if (!project) {
51
+ const [enhancedProject, setEnhancedProject] = useState<
52
+ PortfolioProject | undefined
53
+ >(project);
54
+ const [isLoading, setIsLoading] = useState(false);
55
+
56
+ useEffect(() => {
57
+ const fetchCompleteProjectData = async () => {
58
+ if (project && project.id) {
59
+ setIsLoading(true);
60
+ try {
61
+ const completeFpmProject = await getFpmProjectById(project.id);
62
+
63
+ // Merge the complete FPM data with existing project data (preserving Strapi fields like slug, portfolioHost, thumbnail)
64
+ const mergedProject: PortfolioProject = {
65
+ ...completeFpmProject,
66
+ slug: project.slug,
67
+ portfolioHost: project.portfolioHost,
68
+ thumbnail: project.thumbnail,
69
+ };
70
+
71
+ setEnhancedProject(mergedProject);
72
+ } catch (error) {
73
+ console.error('Error fetching complete project data:', error);
74
+ // Fallback to original project data if fetch fails
75
+ setEnhancedProject(project);
76
+ } finally {
77
+ setIsLoading(false);
78
+ }
79
+ }
80
+ };
81
+
82
+ fetchCompleteProjectData();
83
+ }, [project]);
84
+
85
+ if (!enhancedProject) {
51
86
  return (
52
87
  <>Invalid configuration, check if a project this id exists in the FPM</>
53
88
  );
54
89
  }
55
90
 
91
+ if (isLoading) {
92
+ return (
93
+ <DefaultSectionContainer>
94
+ <Wrapper>
95
+ <div>Loading project data...</div>
96
+ </Wrapper>
97
+ </DefaultSectionContainer>
98
+ );
99
+ }
100
+
56
101
  return (
57
102
  <DefaultSectionContainer>
58
103
  <Wrapper>
59
104
  <Flex flexDir={['column', null, null, 'row']} gap="4" width="full">
60
- <ProjectInfo project={project} subtitles={slice} />
105
+ <ProjectInfo project={enhancedProject} subtitles={slice} />
61
106
  <Flex flexDir="column" gap="4" width="full">
62
107
  {slice.documentUrls && slice.documentUrls.length > 0 && (
63
108
  <DocumentsDownloadList documentUrls={slice.documentUrls} />
@@ -1,9 +1,20 @@
1
1
  import shuffleElements from './shuffleElements';
2
2
 
3
- const originalSlides = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
3
+ const originalSlides = [
4
+ { id: 1 },
5
+ { id: 2 },
6
+ { id: 3 },
7
+ { id: 4 },
8
+ { id: 5 },
9
+ { id: 6 },
10
+ { id: 7 },
11
+ { id: 8 },
12
+ { id: 9 },
13
+ { id: 10 },
14
+ ];
4
15
 
5
16
  describe('shuffleElement', () => {
6
- it('returns a new array with the same elements but in a different order', () => {
17
+ it('returns a new array with the same elements without mutating the original array', () => {
7
18
  const shuffled = shuffleElements(originalSlides);
8
19
 
9
20
  // Check that the shuffled array is not the same reference as the original
@@ -13,18 +24,25 @@ describe('shuffleElement', () => {
13
24
  expect(shuffled).toEqual(expect.arrayContaining(originalSlides));
14
25
  expect(originalSlides).toEqual(expect.arrayContaining(shuffled));
15
26
 
16
- // Verify that at least one element is in a different position to ensure it's shuffled
17
- const isShuffled = originalSlides.some(
18
- (slide, index) => slide.id !== shuffled[index].id
19
- );
20
- expect(isShuffled).toBe(true);
27
+ // Check that the arrays have the same length
28
+ expect(shuffled).toHaveLength(originalSlides.length);
21
29
  });
22
30
 
23
- it('does not mutate the original array', () => {
24
- const originalSlidesCopy = [...originalSlides];
25
- shuffleElements(originalSlides);
31
+ it('produces a different order when shuffled multiple times', () => {
32
+ // Test multiple shuffles to ensure at least one produces a different order
33
+ const shuffles = [
34
+ shuffleElements(originalSlides),
35
+ shuffleElements(originalSlides),
36
+ shuffleElements(originalSlides),
37
+ ];
26
38
 
27
- // Verify that the original array remains unchanged
28
- expect(originalSlides).toEqual(originalSlidesCopy);
39
+ // Check that at least one shuffle produces a different order
40
+ const hasDifferentOrder = shuffles.some((shuffled) => {
41
+ return shuffled.some(
42
+ (element, index) => element.id !== originalSlides[index].id
43
+ );
44
+ });
45
+
46
+ expect(hasDifferentOrder).toBe(true);
29
47
  });
30
48
  });