@genesislcap/blank-app-seed 3.30.1 → 3.31.0

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.
Files changed (58) hide show
  1. package/.genx/package.json +1 -1
  2. package/.genx/templates/react/chart.hbs +7 -3
  3. package/.genx/templates/react/component/component.column.defs.hbs +4 -2
  4. package/.genx/templates/react/component/component.create.form.hbs +2 -2
  5. package/.genx/templates/react/component/component.gridOptions.hbs +4 -2
  6. package/.genx/templates/react/component/component.hbs +64 -27
  7. package/.genx/templates/react/component/component.index.hbs +1 -1
  8. package/.genx/templates/react/component/component.update.form.hbs +1 -1
  9. package/.genx/templates/react/entityManager.hbs +62 -49
  10. package/.genx/templates/react/form.hbs +7 -3
  11. package/.genx/templates/react/grid.hbs +16 -10
  12. package/.genx/templates/react/route.hbs +1 -2
  13. package/.genx/templates/react/tabsLayout.hbs +5 -5
  14. package/.genx/utils/generateRoute.js +8 -7
  15. package/.genx/utils/generateTile.js +31 -16
  16. package/.genx/versions.json +3 -3
  17. package/.idea/modules.xml +6 -6
  18. package/CHANGELOG.md +29 -0
  19. package/client-tmp/angular/__mocks__/fileMock.js +1 -0
  20. package/client-tmp/angular/angular.json +0 -29
  21. package/client-tmp/angular/jest.config.js +20 -0
  22. package/client-tmp/angular/package.json +6 -6
  23. package/client-tmp/angular/src/app/layouts/default/default.layout.spec.ts +2 -2
  24. package/client-tmp/angular/src/jest.setup.ts +46 -0
  25. package/client-tmp/angular/tsconfig.app.json +1 -2
  26. package/client-tmp/angular/tsconfig.json +1 -2
  27. package/client-tmp/angular/tsconfig.spec.json +13 -7
  28. package/client-tmp/react/.babelrc +10 -0
  29. package/client-tmp/react/.eslintrc.cjs +1 -0
  30. package/client-tmp/react/jest.config.ts +15 -0
  31. package/client-tmp/react/jest.setup.ts +1 -0
  32. package/client-tmp/react/lint-css.ts +19 -0
  33. package/client-tmp/react/package.json +18 -8
  34. package/client-tmp/react/src/App.tsx +1 -1
  35. package/client-tmp/react/src/components/{ErrorMessage.test.js → ErrorMessage/ErrorMessage.test.tsx} +31 -16
  36. package/client-tmp/react/src/components/ErrorMessage/{ErrorMessage.jsx → ErrorMessage.tsx} +9 -4
  37. package/client-tmp/react/src/custom-elements.d.ts +19 -9
  38. package/client-tmp/react/src/guards/AuthGuard.tsx +1 -1
  39. package/client-tmp/react/src/index.ts +21 -0
  40. package/client-tmp/react/src/pages/AuthPage/AuthPage.test.tsx +10 -0
  41. package/client-tmp/react/src/pages/AuthPage/{AuthPage.jsx → AuthPage.tsx} +3 -2
  42. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.test.tsx +17 -0
  43. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.tsx +14 -0
  44. package/client-tmp/react/src/{reportWebVitals.js → reportWebVitals.ts} +1 -1
  45. package/client-tmp/react/tsconfig.app.json +2 -5
  46. package/client-tmp/react/tsconfig.json +4 -1
  47. package/client-tmp/react/tsconfig.node.json +1 -1
  48. package/client-tmp/react/{vite.config.js → vite.config.ts} +9 -9
  49. package/client-tmp/web-components/src/main/main.styles.ts +1 -1
  50. package/package.json +1 -1
  51. package/server/settings.gradle.kts +2 -2
  52. package/client-tmp/angular/karma.conf.js +0 -9
  53. package/client-tmp/angular/src/app/app.component.spec.ts +0 -23
  54. package/client-tmp/react/lint-css.js +0 -18
  55. package/client-tmp/react/src/index.js +0 -17
  56. package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.jsx +0 -13
  57. /package/client-tmp/react/src/{setupTests.js → setupTests.ts} +0 -0
  58. /package/server/{{appName}}-app/src/main/genesis/scripts/{{{appName}}-data-pipelines.kts → {{appName}}-pipelines.kts} +0 -0
@@ -90,35 +90,6 @@
90
90
  "buildTarget": "{{pkgName}}:build"
91
91
  }
92
92
  },
93
- "test": {
94
- "builder": "@angular-builders/custom-webpack:karma",
95
- "configurations": {
96
- "production": {
97
- "customWebpackConfig": {
98
- "path": "./webpack.prod.config.js",
99
- "mergeStrategies": {
100
- "externals": "replace"
101
- }
102
- }
103
- },
104
- "development": {
105
- "customWebpackConfig": {
106
- "path": "./webpack.dev.config.js",
107
- "mergeStrategies": {
108
- "externals": "replace"
109
- }
110
- }
111
- }
112
- },
113
- "defaultConfiguration": "development",
114
- "options": {
115
- "polyfills": ["zone.js", "zone.js/testing"],
116
- "tsConfig": "tsconfig.spec.json",
117
- "assets": ["src/favicon.ico", "src/assets"],
118
- "styles": ["src/styles/styles.css"],
119
- "scripts": []
120
- }
121
- },
122
93
  "lint": {
123
94
  "builder": "@angular-eslint/builder:lint",
124
95
  "options": {
@@ -0,0 +1,20 @@
1
+ const { pathsToModuleNameMapper } = require('ts-jest');
2
+ const { compilerOptions } = require('./tsconfig');
3
+
4
+ module.exports = {
5
+ preset: 'jest-preset-angular',
6
+ roots: ['<rootDir>/src/'],
7
+ testMatch: ['**/+(*.)+(spec).+(ts)'],
8
+ setupFilesAfterEnv: ['<rootDir>/src/jest.setup.ts'],
9
+ collectCoverage: true,
10
+ coverageReporters: ['html'],
11
+ coverageDirectory: 'coverage/my-app',
12
+ transformIgnorePatterns: [
13
+ 'node_modules/(?!(@genesislcap/*|consola|@angular|@microsoft|exenv-es6|uuid))',
14
+ ],
15
+ moduleNameMapper: {
16
+ ...pathsToModuleNameMapper(compilerOptions.paths || {}, { prefix: '<rootDir>/' }),
17
+ '\\.(jpg|jpeg|png|gif|svg)$': '<rootDir>/src/__mocks__/fileMock.js',
18
+ '\\.(css)$': 'identity-obj-proxy',
19
+ },
20
+ };
@@ -27,7 +27,7 @@
27
27
  "lint:fix": "genx lint --fix",
28
28
  "lint:eslint": "genx lint -l eslint --profile",
29
29
  "lint:stylelint": "node lint-css.js",
30
- "test": "ng test",
30
+ "test": "jest",
31
31
  "test:e2e": "genx test --e2e",
32
32
  "test:e2e:debug": "genx test --e2e --debug",
33
33
  "test:e2e:ui": "genx test --e2e --interactive",
@@ -54,14 +54,14 @@
54
54
  "@genesislcap/genx": "{{versions.UI}}",
55
55
  "@genesislcap/build-kit": "{{versions.UI}}",
56
56
  "@types/jasmine": "~5.1.0",
57
+ "@types/jest": "^29.5.13",
57
58
  "@types/numeral": "^2.0.5",
58
59
  "file-loader": "^6.2.0",
59
60
  "jasmine-core": "~5.1.0",
60
- "karma": "~6.4.0",
61
- "karma-chrome-launcher": "~3.2.0",
62
- "karma-coverage": "~2.2.0",
63
- "karma-jasmine": "~5.1.0",
64
- "karma-jasmine-html-reporter": "~2.1.0",
61
+ "jest": "^29.7.0",
62
+ "jest-environment-jsdom": "^29.7.0",
63
+ "jest-preset-angular": "^14.2.4",
64
+ "jest-transform-stub": "^2.0.0",
65
65
  "svg-url-loader": "^8.0.0",
66
66
  "typescript": "~5.4.5",
67
67
  "ts-node": "10.9.2",
@@ -4,7 +4,7 @@ import { DefaultLayoutComponent } from './default.layout';
4
4
  import { ElementRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
5
5
 
6
6
  class MockRouter {
7
- navigate = jasmine.createSpy('navigate');
7
+ navigate = jest.fn();
8
8
  }
9
9
 
10
10
  class MockElementRef implements ElementRef {
@@ -46,4 +46,4 @@ describe('DefaultLayoutComponent', () => {
46
46
  component.navigateAngular(path);
47
47
  expect(router.navigate).toHaveBeenCalledWith([path]);
48
48
  });
49
- });
49
+ });
@@ -0,0 +1,46 @@
1
+ import 'jest-preset-angular/setup-jest';
2
+
3
+ // Mock window.matchMedia
4
+ Object.defineProperty(window, 'matchMedia', {
5
+ writable: true,
6
+ value: (query: string) => ({
7
+ matches: false,
8
+ media: query,
9
+ onchange: null,
10
+ addListener: jest.fn(), // Deprecated
11
+ removeListener: jest.fn(), // Deprecated
12
+ addEventListener: jest.fn(),
13
+ removeEventListener: jest.fn(),
14
+ dispatchEvent: jest.fn(),
15
+ }),
16
+ });
17
+
18
+ // Mock BroadcastChannel
19
+ class MockBroadcastChannel {
20
+ name: string;
21
+ onmessage: ((this: BroadcastChannel, ev: MessageEvent) => any) | null = null;
22
+ onmessageerror: ((this: BroadcastChannel, ev: MessageEvent) => any) | null = null;
23
+
24
+ constructor(name: string) {
25
+ this.name = name;
26
+ }
27
+
28
+ postMessage(message: any) {
29
+ if (this.onmessage) {
30
+ this.onmessage({ data: message } as MessageEvent);
31
+ }
32
+ }
33
+
34
+ close() {}
35
+
36
+ addEventListener() {}
37
+ removeEventListener() {}
38
+ dispatchEvent() {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ Object.defineProperty(window, 'BroadcastChannel', {
44
+ writable: true,
45
+ value: MockBroadcastChannel,
46
+ });
@@ -1,9 +1,8 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
1
  {
3
2
  "extends": "./tsconfig.json",
4
3
  "compilerOptions": {
5
4
  "outDir": "./out-tsc/app",
6
- "types": ["node"],
5
+ "types": ["node"]
7
6
  },
8
7
  "files": [
9
8
  "src/main.ts"
@@ -1,4 +1,3 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
1
  {
3
2
  "compileOnSave": false,
4
3
  "compilerOptions": {
@@ -23,7 +22,7 @@
23
22
  "ES2022",
24
23
  "dom"
25
24
  ],
26
- "resolveJsonModule": true,
25
+ "resolveJsonModule": true
27
26
  },
28
27
  "angularCompilerOptions": {
29
28
  "enableI18nLegacyMessageIdFormat": false,
@@ -1,15 +1,21 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
1
  {
3
2
  "extends": "./tsconfig.json",
4
3
  "compilerOptions": {
4
+ "module": "ES2022",
5
+ "target": "ES2022",
5
6
  "outDir": "./out-tsc/spec",
6
7
  "types": [
7
- "jasmine"
8
- ]
8
+ "jest"
9
+ ],
10
+ "esModuleInterop": true,
11
+ "emitDecoratorMetadata": true,
12
+ "resolveJsonModule": true
9
13
  },
14
+ "files": [
15
+ "src/jest.setup.ts",
16
+ ],
10
17
  "include": [
11
- "src/**/*.d.ts",
12
- "src/pbc/**/*.ts",
13
- "src/**/*.spec.ts"
18
+ "src/**/*.spec.ts",
19
+ "src/**/*.d.ts"
14
20
  ]
15
- }
21
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "presets": [
3
+ "@babel/preset-env",
4
+ "@babel/preset-react",
5
+ "@babel/preset-typescript"
6
+ ],
7
+ "plugins": [
8
+ "react-require"
9
+ ]
10
+ }
@@ -10,6 +10,7 @@ module.exports = {
10
10
  parser: '@typescript-eslint/parser',
11
11
  plugins: ['react-refresh'],
12
12
  rules: {
13
+ '@typescript-eslint/no-explicit-any': 'off',
13
14
  '@typescript-eslint/no-unused-vars': 'off',
14
15
  '@typescript-eslint/no-var-requires': 'off',
15
16
  'react-refresh/only-export-components': [
@@ -0,0 +1,15 @@
1
+ import type { Config } from '@jest/types';
2
+
3
+ const config: Config.InitialOptions = {
4
+ testEnvironment: 'jsdom',
5
+ moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
6
+ transform: {
7
+ '^.+\\.jsx?$': 'babel-jest',
8
+ '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.app.json' }],
9
+ },
10
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
11
+ testMatch: ["**/?(*.)+(test).[jt]s?(x)"],
12
+ watchPathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/dist/"],
13
+ };
14
+
15
+ export default config;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,19 @@
1
+ import { execSync } from 'child_process';
2
+ import glob from 'glob';
3
+ import path from 'path';
4
+
5
+ const cssFiles: string[] = glob.sync(path.join(__dirname, '**/*.css'));
6
+
7
+ if (cssFiles.length === 0) {
8
+ console.log('No CSS files found.');
9
+ process.exit(0);
10
+ }
11
+
12
+ const command: string = `genx lint -l stylelint ${cssFiles.join(' ')}`;
13
+
14
+ try {
15
+ execSync(command, { stdio: 'inherit' });
16
+ } catch (error) {
17
+ console.error('Error running stylelint:', error);
18
+ process.exit(1);
19
+ }
@@ -15,16 +15,16 @@
15
15
  "dev:intellij": "npm run dev",
16
16
  "dev:https": "HTTPS=true npm run dev",
17
17
  "dsconfig": "dsconfig --path src/styles/design-tokens.json",
18
- "lint": "eslint src/**/*.js src/**/*.jsx",
19
- "lint:fix": "eslint src/**/*.js src/**/*.jsx --fix",
18
+ "lint": "eslint src/**/*.ts src/**/*.tsx",
19
+ "lint:fix": "eslint src/**/*.ts src/**/*.tsx --fix",
20
20
  "lint:eslint": "npm lint",
21
- "lint:stylelint": "node lint-css.js",
22
- "test": "genx test",
21
+ "lint:stylelint": "npx ts-node lint-css.ts",
22
+ "test": "jest",
23
+ "test:coverage": "jest --coverage",
24
+ "test:unit:watch": "jest --watchAll",
23
25
  "test:e2e": "genx test --e2e",
24
26
  "test:e2e:debug": "genx test --e2e --debug",
25
- "test:e2e:ui": "genx test --e2e --interactive",
26
- "test:coverage": "genx test --no-watch --coverage",
27
- "test:unit:watch": "genx test --watch"
27
+ "test:e2e:ui": "genx test --e2e --interactive"
28
28
  },
29
29
  "dependencies": {
30
30
  "@ag-grid-community/client-side-row-model": "29.2.0",
@@ -48,9 +48,13 @@
48
48
  "history": "^5.3.0",
49
49
  "react": "^19.0.0-beta-94eed63c49-20240425",
50
50
  "react-dom": "^19.0.0-beta-94eed63c49-20240425",
51
- "react-router-dom": "6.24.1"
51
+ "react-router-dom": "6.24.1",
52
+ "web-vitals": "^2.1.4"
52
53
  },
53
54
  "devDependencies": {
55
+ "@babel/core": "^7.25.2",
56
+ "@babel/preset-env": "^7.25.4",
57
+ "@babel/preset-react": "^7.24.7",
54
58
  "@genesislcap/design-system-configurator": "{{versions.UI}}",
55
59
  "@genesislcap/eslint-config": "{{versions.UI}}",
56
60
  "@genesislcap/prettier-config": "{{versions.UI}}",
@@ -60,15 +64,21 @@
60
64
  "@testing-library/dom": "^10.4.0",
61
65
  "@testing-library/jest-dom": "^6.5.0",
62
66
  "@testing-library/react": "^16.0.0",
67
+ "@types/jest": "^29.5.12",
63
68
  "@types/node": "^20.14.10",
64
69
  "@types/react": "npm:types-react@alpha",
65
70
  "@types/react-dom": "npm:types-react-dom@alpha",
66
71
  "@typescript-eslint/eslint-plugin": "^7.13.1",
67
72
  "@typescript-eslint/parser": "^7.13.1",
68
73
  "@vitejs/plugin-react": "^4.3.1",
74
+ "babel-plugin-react-require": "^4.0.3",
69
75
  "eslint": "^8.57.0",
70
76
  "eslint-plugin-react-hooks": "^4.6.2",
71
77
  "eslint-plugin-react-refresh": "^0.4.7",
78
+ "jest": "^29.7.0",
79
+ "jest-environment-jsdom": "^29.7.0",
80
+ "ts-jest": "^29.2.5",
81
+ "ts-node": "^10.9.2",
72
82
  "typescript": "^5.2.2",
73
83
  "vite": "^5.3.1"
74
84
  },
@@ -15,7 +15,7 @@ import { AuthProvider } from './store/AuthContext';
15
15
  import AuthPage from './pages/AuthPage/AuthPage';
16
16
  import NotPermittedPage from './pages/NotPermittedPage/NotPermittedPage';
17
17
  {{#each routes}}
18
- import {{pascalCase this.name}} from './pages/{{kebabCase this.name}}/{{pascalCase this.name}}';
18
+ import {{pascalCase this.name}} from './pages/{{pascalCase this.name}}/{{pascalCase this.name}}';
19
19
  {{/each}}
20
20
 
21
21
  // Genesis Components
@@ -1,35 +1,33 @@
1
- import React from 'react';
2
1
  import { render, screen } from '@testing-library/react';
3
- import '@testing-library/jest-dom';
4
- import ErrorMessage from './ErrorMessage';
2
+ import { default as ErrorMessage, ErrorMessageProps } from './ErrorMessage';
5
3
 
6
4
  describe('ErrorMessage Component', () => {
7
- const message = 'Test Error Message';
5
+ const message: string = 'Test Error Message';
8
6
 
9
7
  test('renders the message as a div by default', () => {
10
8
  render(<ErrorMessage message={message} />);
11
- const displayedMessage = screen.getByText(message);
9
+ const displayedMessage: HTMLElement = screen.getByText(message);
12
10
  expect(displayedMessage.tagName).toBe('DIV');
13
11
  expect(displayedMessage).toBeInTheDocument();
14
12
  });
15
13
 
16
14
  test('renders the message as an h1 element when elementType is "h1"', () => {
17
15
  render(<ErrorMessage message={message} elementType="h1" />);
18
- const displayedMessage = screen.getByRole('heading', { level: 1 });
16
+ const displayedMessage: HTMLElement = screen.getByRole('heading', { level: 1 });
19
17
  expect(displayedMessage.tagName).toBe('H1');
20
18
  expect(displayedMessage).toBeInTheDocument();
21
19
  });
22
20
 
23
21
  test('renders the message as a p element when elementType is "p"', () => {
24
22
  render(<ErrorMessage message={message} elementType="p" />);
25
- const displayedMessage = screen.getByText(message);
23
+ const displayedMessage: HTMLElement = screen.getByText(message);
26
24
  expect(displayedMessage.tagName).toBe('P');
27
25
  expect(displayedMessage).toBeInTheDocument();
28
26
  });
29
27
 
30
28
  test('applies the correct styles to the error message wrapper', () => {
31
29
  render(<ErrorMessage message={message} />);
32
- const wrapper = screen.getByText(message).closest('section');
30
+ const wrapper: HTMLElement | null = screen.getByText(message).closest('section');
33
31
  expect(wrapper).toHaveStyle(`
34
32
  display: flex;
35
33
  flex-direction: column;
@@ -42,8 +40,8 @@ describe('ErrorMessage Component', () => {
42
40
 
43
41
  test('applies the correct styles to the error message itself', () => {
44
42
  render(<ErrorMessage message={message} />);
45
- const displayedMessage = screen.getByText(message);
46
- const messageWrapper = displayedMessage.parentElement;
43
+ const displayedMessage: HTMLElement = screen.getByText(message);
44
+ const messageWrapper: HTMLElement | null = displayedMessage.parentElement;
47
45
 
48
46
  expect(messageWrapper).toBeInTheDocument();
49
47
  expect(messageWrapper).toHaveStyle(`
@@ -64,17 +62,34 @@ describe('ErrorMessage Component', () => {
64
62
  });
65
63
 
66
64
  test('renders nothing if the message is an empty string', () => {
67
- const { container } = render(<ErrorMessage message="" />);
65
+ const { container }: { container: HTMLElement } = render(<ErrorMessage message="" />);
68
66
  expect(container.firstChild).toBeNull();
69
67
  });
70
68
 
71
69
  test('renders the correct element type for various elementType props', () => {
72
- const elementTypes = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'div'];
73
- elementTypes.forEach((elementType) => {
74
- const { container } = render(<ErrorMessage message={message} elementType={elementType} />);
75
- const displayedMessage = container.querySelector(elementType);
70
+ const elementTypes: ErrorMessageProps['elementType'][] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'div'];
71
+ elementTypes.forEach((elementType: ErrorMessageProps['elementType']) => {
72
+ const { container }: { container: HTMLElement } = render(<ErrorMessage message={message} elementType={elementType} />);
73
+ const displayedMessage: HTMLElement | null = container.querySelector(elementType as string);
76
74
  expect(displayedMessage).toBeInTheDocument();
77
- expect(displayedMessage.tagName).toBe(elementType.toUpperCase());
75
+ expect(displayedMessage?.tagName).toBe((elementType as string).toUpperCase());
78
76
  });
79
77
  });
78
+
79
+ test('renders the message as a div element when elementType is unknown', () => {
80
+ render(<ErrorMessage message={message} />);
81
+ const displayedMessage: HTMLElement = screen.getByText(message);
82
+ expect(displayedMessage.tagName).toBe('DIV');
83
+ expect(displayedMessage).toBeInTheDocument();
84
+ });
85
+
86
+ test('renders nothing if the message is null', () => {
87
+ const { container }: { container: HTMLElement } = render(<ErrorMessage />);
88
+ expect(container.firstChild).toBeNull();
89
+ });
90
+
91
+ test('renders nothing if the message is undefined', () => {
92
+ const { container }: { container: HTMLElement } = render(<ErrorMessage message={undefined} />);
93
+ expect(container.firstChild).toBeNull();
94
+ });
80
95
  });
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  const styles = {
4
4
  errorMessageWrapper: {
5
5
  display: 'flex',
6
- flexDirection: 'column',
6
+ flexDirection: 'column' as const,
7
7
  justifyContent: 'center',
8
8
  alignItems: 'center',
9
9
  height: '100%',
@@ -14,11 +14,11 @@ const styles = {
14
14
  backgroundColor: 'var(--neutral-layer-4)',
15
15
  borderColor: 'var(--error-color)',
16
16
  borderRadius: '7px',
17
- borderStyle: 'solid',
17
+ borderStyle: 'solid' as const,
18
18
  borderWidth: '4px',
19
19
  padding: '5px',
20
20
  margin: '15px',
21
- textAlign: 'center',
21
+ textAlign: 'center' as const,
22
22
  width: 'fit-content',
23
23
  alignSelf: 'center',
24
24
  height: 'auto',
@@ -26,7 +26,12 @@ const styles = {
26
26
  },
27
27
  };
28
28
 
29
- const ErrorMessage = ({ elementType = 'div', message = '' }) => {
29
+ export interface ErrorMessageProps {
30
+ elementType?: 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';
31
+ message?: string;
32
+ }
33
+
34
+ const ErrorMessage: React.FC<ErrorMessageProps> = ({ elementType = 'div', message = '' }) => {
30
35
  const ElementType = elementType;
31
36
 
32
37
  return message && message !== '' && (
@@ -1,11 +1,21 @@
1
- declare namespace JSX {
2
- interface IntrinsicElements {
3
- // Wildcard for all webcomponents:
4
- [elemName: string]: unknown;
5
- }
6
- }
1
+ import React, { useState, DOMAttributes } from 'react';
7
2
 
8
- declare module '*.module.css' {
9
- const classes: { [key: string]: string };
10
- export default classes;
3
+ type CustomElement<T = HTMLElement> = Partial<T & DOMAttributes<T> & { children: any }>;
4
+
5
+ declare module "react/jsx-runtime" {
6
+ namespace JSX {
7
+ interface IntrinsicElements {
8
+ 'entity-management': CustomElement;
9
+ 'foundation-form': CustomElement;
10
+ 'rapid-grid-pro': CustomElement;
11
+ 'grid-pro-genesis-datasource': CustomElement;
12
+ 'grid-pro-column': CustomElement;
13
+ 'rapid-g2plot-chart': CustomElement;
14
+ 'chart-datasource': CustomElement;
15
+ 'client-app-login': CustomElement;
16
+ 'rapid-layout': CustomElement;
17
+ 'rapid-layout-region': CustomElement;
18
+ 'rapid-layout-item': CustomElement;
19
+ }
20
+ }
11
21
  }
@@ -16,7 +16,7 @@ const AuthGuard: React.FC<AuthGuardProps> = ({ children }: AuthGuardProps) => {
16
16
  };
17
17
 
18
18
  verifyAuth();
19
- }, []);
19
+ }, [checkAuthStatus]);
20
20
 
21
21
  if (isLoading) {
22
22
  return <div>Loading...</div>; // Or some loading component
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import './styles/styles.css';
4
+ import App from './App';
5
+ import reportWebVitals from './reportWebVitals';
6
+
7
+ const rootElement = document.getElementById('root');
8
+
9
+ if (rootElement) {
10
+ const root = ReactDOM.createRoot(rootElement);
11
+ root.render(
12
+ <React.StrictMode>
13
+ <App />
14
+ </React.StrictMode>,
15
+ );
16
+
17
+ // If you want to start measuring performance in your app, pass a function
18
+ // to log results (for example: reportWebVitals(console.log))
19
+ // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
20
+ reportWebVitals();
21
+ }
@@ -0,0 +1,10 @@
1
+ import { render } from '@testing-library/react';
2
+ import AuthPage from './AuthPage';
3
+
4
+ test('renders AuthPage component', () => {
5
+ const { container } = render(<AuthPage />);
6
+ const authPageElement: Element | null = container.querySelector('.auth-page');
7
+ expect(authPageElement).toBeInTheDocument();
8
+ const clientAppLoginElement: Element | null = container.querySelector('client-app-login');
9
+ expect(clientAppLoginElement).toBeInTheDocument();
10
+ });
@@ -1,6 +1,7 @@
1
+ import React from 'react';
1
2
  import './AuthPage.css';
2
3
 
3
- const AuthPage = () => {
4
+ const AuthPage: React.FC = () => {
4
5
  return (
5
6
  <section className="auth-page">
6
7
  <client-app-login></client-app-login>
@@ -8,4 +9,4 @@ const AuthPage = () => {
8
9
  );
9
10
  };
10
11
 
11
- export default AuthPage;
12
+ export default AuthPage;
@@ -0,0 +1,17 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import NotPermittedPage from './NotPermittedPage';
3
+
4
+ jest.mock('../../components/ErrorMessage/ErrorMessage', () => {
5
+ return jest.fn((props: { message: string }) => <h1 data-testid="error-message">{props.message}</h1>);
6
+ });
7
+
8
+ describe('NotPermittedPage Component', () => {
9
+ test('renders the ErrorMessage component with correct props', () => {
10
+ render(<NotPermittedPage />);
11
+
12
+ const errorMessage: HTMLElement = screen.getByTestId('error-message');
13
+ expect(errorMessage).toBeInTheDocument();
14
+ expect(errorMessage.tagName).toBe('H1');
15
+ expect(errorMessage).toHaveTextContent('You do not have permission to access this part of the application, please contact your administrator.');
16
+ });
17
+ });
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import ErrorMessage from '../../components/ErrorMessage/ErrorMessage';
3
+ import './NotPermittedPage.css';
4
+
5
+ const NotPermittedPage: React.FC = () => {
6
+ return (
7
+ <ErrorMessage
8
+ elementType="h1"
9
+ message="You do not have permission to access this part of the application, please contact your administrator."
10
+ />
11
+ );
12
+ };
13
+
14
+ export default NotPermittedPage;
@@ -1,4 +1,4 @@
1
- const reportWebVitals = (onPerfEntry) => {
1
+ const reportWebVitals = onPerfEntry => {
2
2
  if (onPerfEntry && onPerfEntry instanceof Function) {
3
3
  import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4
4
  getCLS(onPerfEntry);
@@ -7,8 +7,6 @@
7
7
  "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
8
  "module": "ESNext",
9
9
  "skipLibCheck": true,
10
-
11
- /* Bundler mode */
12
10
  "moduleResolution": "bundler",
13
11
  "allowImportingTsExtensions": true,
14
12
  "resolveJsonModule": true,
@@ -16,13 +14,12 @@
16
14
  "moduleDetection": "force",
17
15
  "noEmit": true,
18
16
  "jsx": "react-jsx",
19
-
20
- /* Linting */
21
17
  "strict": true,
18
+ "esModuleInterop": true,
22
19
  "noUnusedLocals": true,
23
20
  "noUnusedParameters": true,
24
21
  "noFallthroughCasesInSwitch": true,
25
22
  "types": ["node", "react"]
26
23
  },
27
- "include": ["src"]
24
+ "include": ["src" , "src/**/*.d.ts"],
28
25
  }
@@ -7,5 +7,8 @@
7
7
  {
8
8
  "path": "./tsconfig.node.json"
9
9
  }
10
- ]
10
+ ],
11
+ "compilerOptions": {
12
+ "esModuleInterop": true,
13
+ }
11
14
  }
@@ -9,5 +9,5 @@
9
9
  "strict": true,
10
10
  "noEmit": true
11
11
  },
12
- "include": ["vite.config.js"]
12
+ "include": ["vite.config.ts"]
13
13
  }