diff --git a/.github/workflows/dev-forestgeo-livesite.yml b/.github/workflows/dev-forestgeo-livesite.yml
index a6b701b2..b6bf929d 100644
--- a/.github/workflows/dev-forestgeo-livesite.yml
+++ b/.github/workflows/dev-forestgeo-livesite.yml
@@ -48,29 +48,35 @@ jobs:
echo OWNER=${{ secrets.OWNER }} >> frontend/.env
echo REPO=${{ secrets.REPO }} >> frontend/.env
-# - name: Cache node modules
-# uses: actions/cache@v2
-# with:
-# path: frontend/node_modules
-# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
-# restore-keys: |
-# ${{ runner.os }}-node-
+ # - name: Cache node modules
+ # uses: actions/cache@v2
+ # with:
+ # path: frontend/node_modules
+ # key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+ # restore-keys: |
+ # ${{ runner.os }}-node-
-# - name: Cache Next.js build
-# uses: actions/cache@v2
-# with:
-# path: frontend/build/cache
-# key: ${{ runner.os }}-next-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/.next/cache') }}
-# restore-keys: |
-# ${{ runner.os }}-next-
-# ${{ runner.os }}-next-${{ hashFiles('**/package-lock.json') }}
+ # - name: Cache Next.js build
+ # uses: actions/cache@v2
+ # with:
+ # path: frontend/build/cache
+ # key: ${{ runner.os }}-next-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/.next/cache') }}
+ # restore-keys: |
+ # ${{ runner.os }}-next-
+ # ${{ runner.os }}-next-${{ hashFiles('**/package-lock.json') }}
- name: move into frontend --> npm install, build, and test
run: |
cd frontend/
npm install
npm run build
- npm run test --if-present
+
+ - name: Cypress run
+ uses: cypress-io/github-action@v6
+ with:
+ build: npm run build
+ start: npm start
+ browser: chrome
- name: Move directories into build/standalone to reduce app load
run: |
diff --git a/frontend/CHANGELOG.md b/frontend/CHANGELOG.md
index ffff6414..c04d7c05 100644
--- a/frontend/CHANGELOG.md
+++ b/frontend/CHANGELOG.md
@@ -118,11 +118,11 @@
1. FixedData cases' queries updated to correctly work with updated schemas
2. New tables/cases added:
- 1. `personnelrole`
- 2. `sitespecificvalidations`
- 3. `roles`
- 4. `measurementssummary`
- 5. `viewfulltable`
+ 1. `personnelrole`
+ 2. `sitespecificvalidations`
+ 3. `roles`
+ 4. `measurementssummary`
+ 5. `viewfulltable`
###### POST
@@ -142,18 +142,18 @@
1. Postvalidation summary statistics calculation endpoint
2. Statistics queries:
- 1. `number of records by quadrat`
- 2. `all stem records by quadrat (count only)`
- 3. `live stem records by quadrat (count only)`
- 4. `tree records by quadrat (count only)`
- 5. `number of dead or missing stems by census`
- 6. `trees outside of plot limits`
- 7. `stems with largest DBH/HOM measurements by species`
- 8. `all trees that were recorded in last census that are NOT in current census`
- 9. `number of new stems per quadrat per census`
- 10. `quadrats with most and least new stems per census`
- 11. `number of dead stems per quadrat per census`
- 12. `number of dead stems per species per census`
+ 1. `number of records by quadrat`
+ 2. `all stem records by quadrat (count only)`
+ 3. `live stem records by quadrat (count only)`
+ 4. `tree records by quadrat (count only)`
+ 5. `number of dead or missing stems by census`
+ 6. `trees outside of plot limits`
+ 7. `stems with largest DBH/HOM measurements by species`
+ 8. `all trees that were recorded in last census that are NOT in current census`
+ 9. `number of new stems per quadrat per census`
+ 10. `quadrats with most and least new stems per census`
+ 11. `number of dead stems per quadrat per census`
+ 12. `number of dead stems per species per census`
#### frontend/app/api/refreshviews/[view]/[schema]/route.ts
@@ -220,7 +220,7 @@
3. customized cell and edit cell rendering added
4. some exceptions exist -- for instances where specific additional handling is needed, column states are directly
defined in the datagrid components themselves.
- 1. `alltaxonomiesview` -- specieslimits column customized addition
+ 1. `alltaxonomiesview` -- specieslimits column customized addition
#### GitHub Feedback Modal
@@ -250,18 +250,18 @@
1. The DataGridCommons generic datagrid instance has been replaced by the IsolatedDataGridCommons instance, which
isolates as much information as possible to the generic instance rather than the existing DataGridCommons, which
requires parameter drilling of all MUI X DataGrid parameters. Current datagrids using this new implementation are:
- - `alltaxonomiesview`
- - `attributes`
- - `personnel`
- - `quadratpersonnel`
- - `quadrats`
- - `roles`
- - `stemtaxonomiesview`
+ - `alltaxonomiesview`
+ - `attributes`
+ - `personnel`
+ - `quadratpersonnel`
+ - `quadrats`
+ - `roles`
+ - `stemtaxonomiesview`
2. found that attempting to use typescript runtime utilities to create "default" initial states for each RDS type was
causing cascading failures. Due to the way that runtime utility functions work, no data was actually reaching the
datagrids importing those initial states
- 1. replaced with manual definition of initial states -- planning on centralizing this to another place, similar to
- the `datagridcolumns.tsx` file
+ 1. replaced with manual definition of initial states -- planning on centralizing this to another place, similar to
+ the `datagridcolumns.tsx` file
3. `measurementssummaryview` datagrid instance added as a replacement to the previously defined summary page
#### Re-Entry Data Modal
@@ -312,12 +312,12 @@
### SQL Updates
1. Schema has been been updated -- new tables added:
- 1. `roles` - outlines user roles
- 2. `specieslimits` - allows setting min/max bounds on measurements
- 3. `specimens` - recording specimen data (added on request by ForestGEO)
- 4. `unifiedchangelog` - partitioned table that tracks all changes to all tables in schema. All tables have triggers
- that automatically update the `unifiedchangelog` on every change
- 5. `sitespecificvalidations` - for specific validations applicable only to the host site
+ 1. `roles` - outlines user roles
+ 2. `specieslimits` - allows setting min/max bounds on measurements
+ 3. `specimens` - recording specimen data (added on request by ForestGEO)
+ 4. `unifiedchangelog` - partitioned table that tracks all changes to all tables in schema. All tables have triggers
+ that automatically update the `unifiedchangelog` on every change
+ 5. `sitespecificvalidations` - for specific validations applicable only to the host site
2. validation stored procedures have been deprecated and removed, replaced with `validationprocedures` and
`sitespecificvalidations` tables
3. migration script set has been completed and tested
diff --git a/frontend/__tests__/dashboard.test.tsx b/frontend/__tests__/dashboard.test.tsx
deleted file mode 100644
index 9e682f10..00000000
--- a/frontend/__tests__/dashboard.test.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
-import DashboardPage from '@/app/(hub)/dashboard/page';
-import { useSession } from 'next-auth/react';
-import '@testing-library/jest-dom/vitest';
-import { LockAnimationProvider } from '@/app/contexts/lockanimationcontext';
-
-// Mock the useSession hook
-vi.mock('next-auth/react', () => ({
- useSession: vi.fn()
-}));
-
-// Define a mock session object
-const mockSession = {
- user: {
- name: 'John Doe',
- email: 'john.doe@example.com',
- userStatus: 'admin',
- sites: [
- { schemaName: 'site1', siteName: 'Site 1' },
- { schemaName: 'site2', siteName: 'Site 2' }
- ]
- }
-};
-
-describe.skip('DashboardPage Component', () => {
- // Mock the authenticated session before all tests
- beforeAll(() => {
- (useSession as Mock).mockReturnValue({ data: mockSession, status: 'authenticated' });
- });
-
- beforeEach(() => {
- // Reset mocks before each test
- vi.clearAllMocks();
- });
-
- const renderWithProvider = () => {
- return render(
-
-
-
- );
- };
-
- it("displays the user's name", () => {
- renderWithProvider();
-
- // Assert that the user's name is displayed
- expect(screen.getByText(/Welcome, John Doe!/i)).toBeInTheDocument();
- });
-
- it("displays the user's email", () => {
- renderWithProvider();
-
- // Assert that the user's email is displayed
- // To handle multiple instances of "Registered Email:"
- const emails = screen.getAllByText(/Registered Email:/i);
- expect(emails).length.greaterThanOrEqual(1); // Expect only one occurrence or handle all
- expect(emails[0]).toBeInTheDocument();
- expect(screen.getByText(/john.doe@example.com/i)).toBeInTheDocument();
- });
-
- it("displays the user's permission status", () => {
- renderWithProvider();
-
- // Same for "Assigned Role:"
- const roles = screen.getAllByText(/Assigned Role:/i);
- expect(roles).length.greaterThanOrEqual(1); // Handle according to your use case
- expect(roles[0]).toBeInTheDocument();
-
- expect(screen.getByText(/global/i)).toBeInTheDocument();
- });
-
- it('displays the list of allowed sites', () => {
- renderWithProvider();
-
- // Assert that the allowed sites are displayed
- const sites = screen.getAllByText(/You have access to the following sites:/i);
- expect(sites).length.greaterThanOrEqual(1); // Handle according to your use case
- expect(sites[0]).toBeInTheDocument();
- expect(screen.getByText(/Site 1/i)).toBeInTheDocument();
- expect(screen.getByText(/Site 2/i)).toBeInTheDocument();
- });
-});
diff --git a/frontend/__tests__/login.test.tsx b/frontend/__tests__/login.test.tsx
deleted file mode 100644
index 33135b1d..00000000
--- a/frontend/__tests__/login.test.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import { beforeAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
-import LoginPage from '@/app/(login)/login/page';
-import { useSession } from 'next-auth/react';
-import { redirect } from 'next/navigation';
-import '@testing-library/jest-dom/vitest';
-
-// Mock the useSession hook and next/navigation functions
-vi.mock('next-auth/react', () => ({
- useSession: vi.fn()
-}));
-
-vi.mock('next/navigation', () => ({
- redirect: vi.fn()
-}));
-
-// Mock the UnauthenticatedSidebar component
-vi.mock('@/components/unauthenticatedsidebar', () => ({
- default: () =>
Unauthenticated Sidebar
-}));
-
-// Define a mock session object to use across tests
-const mockSession = {
- user: {
- email: 'user@example.com',
- userStatus: 'admin',
- sites: [{ name: 'Site 1' }, { name: 'Site 2' }],
- allsites: [{ name: 'Site 1' }, { name: 'Site 2' }]
- }
-};
-
-describe('LoginPage Component with authenticated session', () => {
- // Set up the mock authenticated session once for all tests
- beforeAll(() => {
- (useSession as Mock).mockReturnValue({ data: mockSession, status: 'authenticated' });
- });
-
- beforeEach(() => {
- // Reset mocks before each test
- vi.clearAllMocks();
- });
-
- it('redirects to dashboard when the user is authenticated', () => {
- render();
-
- // Assert that redirect was called to navigate to the dashboard
- expect(redirect).toHaveBeenCalledWith('/dashboard');
- });
-
- // Add more tests here that assume the user is authenticated
- it('does not render the unauthenticated sidebar when the user is authenticated', () => {
- render();
-
- // Assert that the unauthenticated sidebar is not present
- expect(screen.queryByTestId('unauthenticated-sidebar')).not.toBeInTheDocument();
- });
-
- // Additional tests can go here, all assuming the user is already logged in...
-});
diff --git a/frontend/__tests__/sidebar.test.tsx b/frontend/__tests__/sidebar.test.tsx
deleted file mode 100644
index a330c7f6..00000000
--- a/frontend/__tests__/sidebar.test.tsx
+++ /dev/null
@@ -1,167 +0,0 @@
-// Mock ResizeObserver
-class ResizeObserver {
- observe() {}
-
- unobserve() {}
-
- disconnect() {}
-}
-
-global.ResizeObserver = ResizeObserver;
-
-import { render, screen } from '@testing-library/react';
-import { beforeEach, describe, expect, it, vi } from 'vitest';
-import Sidebar from '@/components/sidebar';
-import { useSession } from 'next-auth/react';
-import { useOrgCensusContext, usePlotContext, useSiteContext } from '@/app/contexts/userselectionprovider';
-import { useOrgCensusListContext, usePlotListContext, useSiteListContext } from '@/app/contexts/listselectionprovider';
-import '@testing-library/jest-dom/vitest';
-import { UserAuthRoles } from '@/config/macros';
-import { Session } from 'next-auth/core/types';
-import { CensusDateRange } from '@/config/sqlrdsdefinitions/timekeeping';
-
-// Mock the necessary hooks
-vi.mock('next-auth/react', () => ({
- useSession: vi.fn()
-}));
-
-vi.mock('@/app/contexts/userselectionprovider', () => ({
- useSiteContext: vi.fn(),
- usePlotContext: vi.fn(),
- useOrgCensusContext: vi.fn(),
- useSiteDispatch: vi.fn(),
- usePlotDispatch: vi.fn(),
- useOrgCensusDispatch: vi.fn()
-}));
-
-vi.mock('@/app/contexts/listselectionprovider', () => ({
- useSiteListContext: vi.fn(),
- usePlotListContext: vi.fn(),
- useOrgCensusListContext: vi.fn(),
- useSiteListDispatch: vi.fn(),
- usePlotListDispatch: vi.fn(),
- useOrgCensusListDispatch: vi.fn()
-}));
-
-vi.mock('next/navigation', async () => {
- const actual = await vi.importActual('next/navigation');
- return {
- ...actual,
- useRouter: vi.fn().mockReturnValue({
- route: '/',
- pathname: '/',
- query: {},
- asPath: '/',
- push: vi.fn(),
- replace: vi.fn(),
- back: vi.fn()
- }),
- usePathname: vi.fn().mockReturnValue('/mock-path'),
- useSearchParams: vi.fn().mockReturnValue({
- get: vi.fn()
- })
- };
-});
-
-describe.skip('Sidebar Component', () => {
- // Mock session data
- const mockSession = {
- user: {
- name: 'John Doe',
- email: 'john.doe@example.com',
- userStatus: 'global' as UserAuthRoles,
- sites: [
- { siteID: 1, siteName: 'Site 1', schemaName: 'schema1' },
- { siteID: 2, siteName: 'Site 2', schemaName: 'schema2' }
- ],
- allsites: [
- { siteID: 1, siteName: 'Site 1', schemaName: 'schema1' },
- { siteID: 2, siteName: 'Site 2', schemaName: 'schema2' }
- ]
- },
- expires: '9999-12-31T23:59:59.999Z' // Add this line to satisfy the 'Session' type
- };
-
- // Mock site, plot, and census contexts
- const mockSite = { siteID: 1, siteName: 'Site 1', schemaName: 'schema1' };
- const mockPlot = { plotID: 1, plotName: 'Plot 1', numQuadrats: 5 };
- const mockCensus = {
- plotCensusNumber: 1,
- dateRanges: [{ censusID: 1, startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') } as CensusDateRange],
- plotID: 1,
- censusIDs: [1, 2],
- description: 'Test Census'
- };
- const mockCensusList = [
- {
- plotCensusNumber: 1,
- dateRanges: [{ censusID: 1, startDate: new Date('2023-01-01'), endDate: new Date('2023-01-31') } as CensusDateRange],
- plotID: 1,
- censusIDs: [1, 2],
- description: 'Test Census'
- }
- ];
-
- beforeEach(() => {
- vi.clearAllMocks();
-
- // Mock session
- vi.mocked(useSession).mockReturnValue({
- data: mockSession,
- status: 'authenticated',
- update: function (_data?: any): Promise {
- throw new Error('Function not implemented.');
- }
- });
-
- // Mock contexts
- vi.mocked(useSiteContext).mockReturnValue(mockSite);
- vi.mocked(usePlotContext).mockReturnValue(mockPlot);
- vi.mocked(useOrgCensusContext).mockReturnValue(mockCensus);
-
- // Mock list contexts
- vi.mocked(useSiteListContext).mockReturnValue([mockSite]);
- vi.mocked(usePlotListContext).mockReturnValue([mockPlot]);
- vi.mocked(useOrgCensusListContext).mockReturnValue(mockCensusList);
- });
-
- it('renders the sidebar', async () => {
- render();
-
- // Check if the sidebar renders the user name and admin status
- expect(screen.getByTestId('login-logout-component')).toBeInTheDocument();
-
- // Check if the site, plot, and census dropdowns are rendered using data-testid
- expect(screen.getByTestId('site-select-component')).toBeInTheDocument();
- expect(screen.getByTestId('plot-select-component')).toBeInTheDocument();
- expect(screen.getByTestId('census-select-component')).toBeInTheDocument();
- });
-
- it('displays the selected site, plot, and census', async () => {
- render();
-
- // Check that the selected site, plot, and census are displayed correctly
- expect(screen.getByTestId('selected-site-name')).toHaveTextContent('Site: Site 1');
- expect(screen.getByTestId('selected-plot-name')).toHaveTextContent('Plot: Plot 1');
- expect(screen.getByTestId('selected-census-plotcensusnumber')).toHaveTextContent('Census: 1');
-
- // Check dates
- expect(screen.getByTestId('selected-census-dates')).toHaveTextContent('First Record: Sun Jan 01 2023');
- expect(screen.getByTestId('selected-census-dates')).toHaveTextContent('Last Record: Tue Jan 31 2023');
- });
-
- // it('opens the "Add New Census" modal when clicked', async () => {
- // render();
- //
- // // Find and click the "Add New Census" button
- // const addCensusButton = screen.getByTestId('add-new-census-button');
- // expect(addCensusButton).toBeInTheDocument();
- //
- // await act(async () => {
- // fireEvent.click(addCensusButton);
- // });
- //
- // // Verify that the modal opens successfully using its test ID
- // expect(screen.getByTestId('rollover-modal')).toBeInTheDocument();
- // });
-});
diff --git a/frontend/app/error.tsx b/frontend/app/error.tsx
index 5891e402..d2746d66 100644
--- a/frontend/app/error.tsx
+++ b/frontend/app/error.tsx
@@ -3,7 +3,8 @@
import React, { useEffect } from 'react';
import { Box, Button, Typography } from '@mui/joy';
-const ErrorPage = ({ error, reset }: { error: Error; reset: () => void }) => {
+const ErrorPage = (props: { error: Error; reset: () => void }) => {
+ const { error, reset } = props;
useEffect(() => {
const timer = setTimeout(() => {
reset();
@@ -14,7 +15,7 @@ const ErrorPage = ({ error, reset }: { error: Error; reset: () => void }) => {
return (
Something went wrong
- {error.message}
+ {error?.message ?? 'No error message received...'}Retrying in 5 seconds...
diff --git a/frontend/components/client/loginfailure.tsx b/frontend/components/client/loginfailure.tsx
index 7e9e47e0..a209ec60 100644
--- a/frontend/components/client/loginfailure.tsx
+++ b/frontend/components/client/loginfailure.tsx
@@ -6,8 +6,9 @@ import { useSearchParams } from 'next/navigation';
const LoginFailed = () => {
const searchParams = useSearchParams();
- let failureReason = searchParams.get('reason');
- if (failureReason === null || failureReason === '') failureReason = 'Login failure triggered without reason. Please speak to an administrator';
+ let failureReason = searchParams?.get('reason');
+ if (failureReason === null || failureReason === '' || failureReason === undefined)
+ failureReason = 'Login failure triggered without reason. Please speak to' + ' an administrator';
const handleTryAgain = () => {
sessionStorage.clear();
diff --git a/frontend/cypress.config.ts b/frontend/cypress.config.ts
index fac3981d..d1fc1a11 100644
--- a/frontend/cypress.config.ts
+++ b/frontend/cypress.config.ts
@@ -2,15 +2,17 @@ import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
- baseUrl: 'http://localhost:3000',
- setupNodeEvents(on, config) {},
- specPattern: 'cypress/e2e/**/*.cy.{js,ts,jsx,tsx}' // Ensures e2e tests go in `cypress/e2e`
+ specPattern: 'cypress/e2e/**/*.cy.{js,ts,jsx,tsx}', // E2E tests location
+ baseUrl: 'http://localhost:3000', // Define the base URL for tests
+ setupNodeEvents(on, config) {
+ // Add node event listeners here if needed
+ }
},
component: {
devServer: {
framework: 'next',
bundler: 'webpack'
},
- specPattern: 'cypress/component/**/*.cy.{js,ts,jsx,tsx}' // Ensures component tests go in `cypress/component`
+ specPattern: 'cypress/components/**/*.cy.{js,ts,jsx,tsx}' // Component tests location
}
});
diff --git a/frontend/cypress/component/about.cy.tsx b/frontend/cypress/component/about.cy.tsx
deleted file mode 100644
index 66c53206..00000000
--- a/frontend/cypress/component/about.cy.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import Page from '../../app/page';
-
-describe('', () => {
- it('should render and display expected content', () => {
- // Mount the React component for the Home page
- cy.mount();
- });
-});
diff --git a/frontend/cypress/component/headerHeader.cy.tsx b/frontend/cypress/component/headerHeader.cy.tsx
deleted file mode 100644
index 1e6be9ab..00000000
--- a/frontend/cypress/component/headerHeader.cy.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react';
-import Header from '../../components/header';
-
-describe('', () => {
- it('renders', () => {
- // see: https://on.cypress.io/mounting-react
- cy.mount();
- });
-});
diff --git a/frontend/cypress/components/errorErrorPage.cy.tsx b/frontend/cypress/components/errorErrorPage.cy.tsx
new file mode 100644
index 00000000..167e78c8
--- /dev/null
+++ b/frontend/cypress/components/errorErrorPage.cy.tsx
@@ -0,0 +1,8 @@
+import React from 'react'
+import ErrorPage from '../../app/error'
+
+describe('', () => {
+ it('renders', () => {
+ cy.mount()
+ })
+})
\ No newline at end of file
diff --git a/frontend/cypress/components/pageHomePage.cy.tsx b/frontend/cypress/components/pageHomePage.cy.tsx
new file mode 100644
index 00000000..c9a55b6a
--- /dev/null
+++ b/frontend/cypress/components/pageHomePage.cy.tsx
@@ -0,0 +1,9 @@
+import React from 'react'
+import HomePage from '../../app/page'
+
+describe('', () => {
+ it('renders', () => {
+ // see: https://on.cypress.io/mounting-react
+ cy.mount()
+ })
+})
\ No newline at end of file
diff --git a/frontend/cypress/components/pageLoginFailedPage.cy.tsx b/frontend/cypress/components/pageLoginFailedPage.cy.tsx
new file mode 100644
index 00000000..9163b5e0
--- /dev/null
+++ b/frontend/cypress/components/pageLoginFailedPage.cy.tsx
@@ -0,0 +1,9 @@
+import React from 'react'
+import LoginFailedPage from '../../app/loginfailed/page'
+
+describe('', () => {
+ it('renders', () => {
+ // see: https://on.cypress.io/mounting-react
+ cy.mount()
+ })
+})
\ No newline at end of file
diff --git a/frontend/cypress/e2e/app.cy.ts b/frontend/cypress/e2e/app.cy.ts
deleted file mode 100644
index 58362a9c..00000000
--- a/frontend/cypress/e2e/app.cy.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-describe('Navigation', () => {
- it('should navigate to the about page', () => {
- // Start from the index page
- cy.visit('http://localhost:3000/');
- });
-});
diff --git a/frontend/cypress/support/commands.ts b/frontend/cypress/support/commands.ts
index 95857aea..698b01a4 100644
--- a/frontend/cypress/support/commands.ts
+++ b/frontend/cypress/support/commands.ts
@@ -34,4 +34,4 @@
// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable
// }
// }
-// }
+// }
\ No newline at end of file
diff --git a/frontend/cypress/support/component-index.html b/frontend/cypress/support/component-index.html
index 800e8bdc..3e16e9b0 100644
--- a/frontend/cypress/support/component-index.html
+++ b/frontend/cypress/support/component-index.html
@@ -1,14 +1,14 @@
-
+
-
-
-
-
- Components App
-
-
-
-
-
-
-
+
+
+
+
+ Components App
+
+
+
+
+
+
+