@genesislcap/blank-app-seed 5.22.1 → 5.23.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.
- package/.genx/configure.js +11 -1
- package/.genx/package.json +1 -1
- package/.genx/scripts/generate-test-apps.sh +124 -0
- package/.genx/templates/angular/chart.hbs +19 -7
- package/.genx/templates/angular/component/component.column.defs.hbs +16 -4
- package/.genx/templates/angular/component/component.create.form.hbs +10 -2
- package/.genx/templates/angular/component/component.events.config.hbs +31 -6
- package/.genx/templates/angular/component/component.filter.form.hbs +1 -2
- package/.genx/templates/angular/component/component.gridOptions.hbs +15 -3
- package/.genx/templates/angular/component/component.hbs +77 -46
- package/.genx/templates/angular/component/component.index.hbs +1 -1
- package/.genx/templates/angular/component/component.update.form.hbs +1 -1
- package/.genx/templates/angular/entityManager.hbs +6 -6
- package/{client-tmp/angular/src/app/utils/fdc3.ts → .genx/templates/angular/fdc3.ts.hbs} +6 -8
- package/.genx/templates/angular/form.hbs +9 -12
- package/.genx/templates/angular/grid.hbs +43 -40
- package/.genx/templates/angular/route.hbs +8 -2
- package/.genx/templates/angular/route.template.hbs +7 -7
- package/.genx/templates/angular/slices/eventing.slice.hbs +21 -10
- package/.genx/templates/angular/store.hbs +1 -5
- package/.genx/templates/angular/tabsPanel.hbs +2 -2
- package/.genx/templates/react/chart.hbs +6 -15
- package/.genx/templates/react/component/component.column.defs.hbs +16 -10
- package/.genx/templates/react/component/component.create.form.hbs +2 -2
- package/.genx/templates/react/component/component.events.config.hbs +32 -5
- package/.genx/templates/react/component/component.filter.form.hbs +1 -2
- package/.genx/templates/react/component/component.gridOptions.hbs +17 -11
- package/.genx/templates/react/component/component.hbs +84 -42
- package/.genx/templates/react/component/component.update.form.hbs +1 -1
- package/.genx/templates/react/entityManager.hbs +8 -16
- package/{client-tmp/react/src/utils/fdc3.ts → .genx/templates/react/fdc3.ts.hbs} +7 -8
- package/.genx/templates/react/form.hbs +1 -15
- package/.genx/templates/react/grid.hbs +11 -11
- package/.genx/templates/react/gridLayout.hbs +44 -4
- package/.genx/templates/react/horizontalLayout.hbs +10 -1
- package/.genx/templates/react/route.hbs +21 -14
- package/.genx/templates/react/slices/eventing.slice.hbs +19 -8
- package/.genx/templates/react/store.hbs +1 -5
- package/.genx/templates/react/tabsLayout.hbs +5 -1
- package/.genx/templates/web-components/chart.hbs +25 -25
- package/.genx/templates/web-components/component/component.column.defs.hbs +11 -3
- package/.genx/templates/web-components/component/component.create.form.hbs +11 -4
- package/.genx/templates/web-components/component/component.events.config.hbs +33 -6
- package/.genx/templates/web-components/component/component.filter.form.hbs +1 -2
- package/.genx/templates/web-components/component/component.gridOptions.hbs +12 -3
- package/.genx/templates/web-components/component/component.hbs +19 -20
- package/.genx/templates/web-components/component/component.index.hbs +1 -1
- package/.genx/templates/web-components/component/component.template.hbs +9 -13
- package/.genx/templates/web-components/component/component.update.form.hbs +1 -1
- package/.genx/templates/web-components/entityManager.hbs +92 -73
- package/{client-tmp/web-components/src/utils/fdc3.ts → .genx/templates/web-components/fdc3.ts.hbs} +6 -7
- package/.genx/templates/web-components/form.hbs +16 -15
- package/.genx/templates/web-components/grid.hbs +49 -41
- package/.genx/templates/web-components/gridLayout.hbs +32 -28
- package/.genx/templates/web-components/horizontalLayout.hbs +5 -5
- package/.genx/templates/web-components/route.template.hbs +4 -6
- package/.genx/templates/web-components/slices/eventing.slice.hbs +23 -15
- package/.genx/templates/web-components/store.hbs +1 -9
- package/.genx/templates/web-components/tabsLayout.hbs +5 -5
- package/.genx/tests/fixtures/routes-full.json +299 -0
- package/.genx/tests/fixtures/testapp/client/src/pages/Home/Home.tsx +12 -0
- package/.genx/utils/formatJSONValue.js +38 -2
- package/.genx/utils/formatRouteData.js +67 -18
- package/.genx/utils/generateTile.js +10 -1
- package/.genx/utils/gridSerializers.js +63 -23
- package/.genx/utils/registerPartials.js +15 -12
- package/.genx/utils/toJsStringLiteral.js +37 -0
- package/.github/workflows/build.yml +22 -1
- package/.github/workflows/release.yaml +96 -0
- package/.husky/pre-commit +8 -0
- package/.releaserc +1 -1
- package/CHANGELOG.md +23 -0
- package/client-tmp/angular/.oxfmtrc.json +32 -0
- package/client-tmp/angular/.oxlintrc.json +4 -0
- package/client-tmp/angular/README.md +4 -4
- package/client-tmp/angular/jest.config.js +1 -1
- package/client-tmp/angular/lint-css.js +24 -3
- package/client-tmp/angular/oxlint-staged.js +45 -0
- package/client-tmp/angular/package.json +19 -9
- package/client-tmp/angular/playwright.config.ts +12 -11
- package/client-tmp/angular/src/app/app.component.html +0 -1
- package/client-tmp/angular/src/app/app.component.ts +8 -9
- package/client-tmp/angular/src/app/app.config.ts +2 -2
- package/client-tmp/angular/src/app/app.module.ts +6 -5
- package/client-tmp/angular/src/app/components/error-message/error-message.component.html +29 -15
- package/client-tmp/angular/src/app/components/error-message/error-message.component.spec.ts +2 -2
- package/client-tmp/angular/src/app/components/error-message/error-message.component.ts +3 -5
- package/client-tmp/angular/src/app/directive/app-lazy-load.directive.ts +1 -0
- package/client-tmp/angular/src/app/guards/chained.guard.ts +19 -19
- package/client-tmp/angular/src/app/guards/connection.guard.ts +12 -12
- package/client-tmp/angular/src/app/layouts/blank/blank.layout.spec.ts +1 -1
- package/client-tmp/angular/src/app/layouts/blank/blank.layout.ts +1 -5
- package/client-tmp/angular/src/app/layouts/default/default.layout.html +3 -4
- package/client-tmp/angular/src/app/layouts/default/default.layout.spec.ts +4 -4
- package/client-tmp/angular/src/app/layouts/default/default.layout.ts +1 -1
- package/client-tmp/angular/src/app/pages/auth-login/auth-login.component.ts +1 -2
- package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.html +3 -3
- package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.scss +1 -1
- package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.spec.ts +5 -5
- package/client-tmp/angular/src/app/pages/not-permitted/not-permitted.component.ts +3 -4
- package/client-tmp/angular/src/app/services/route.service.ts +79 -74
- package/client-tmp/angular/src/app/share/foundation-auth.ts +7 -1
- package/client-tmp/angular/src/app/share/genesis-components.ts +66 -68
- package/client-tmp/angular/src/app/utils/index.ts +3 -1
- package/client-tmp/angular/src/app/utils/permissions.ts +7 -7
- package/client-tmp/angular/src/declaration.d.ts +1 -1
- package/client-tmp/angular/src/environments/environment.ts +1 -1
- package/client-tmp/angular/src/jest.setup.ts +8 -0
- package/client-tmp/angular/src/main.ts +2 -2
- package/client-tmp/angular/src/pbc/container.ts +28 -26
- package/client-tmp/angular/src/pbc/elementsRenderer.ts +49 -39
- package/client-tmp/angular/src/pbc/utils.ts +61 -60
- package/client-tmp/angular/src/styles/_mixins.scss +7 -8
- package/client-tmp/angular/src/styles/styles.css +6 -6
- package/client-tmp/angular/test/e2e/fixture.ts +2 -2
- package/client-tmp/angular/test/e2e/flows/001-protected.e2e.ts +1 -1
- package/client-tmp/angular/tsconfig.app.json +2 -8
- package/client-tmp/angular/tsconfig.json +1 -4
- package/client-tmp/angular/tsconfig.spec.json +4 -11
- package/client-tmp/angular/webpack.dev.config.js +3 -4
- package/client-tmp/angular/webpack.prod.config.js +3 -4
- package/client-tmp/angular/webpack.shared.config.js +20 -24
- package/client-tmp/react/.oxfmtrc.json +30 -0
- package/client-tmp/react/.oxlintrc.json +4 -0
- package/client-tmp/react/README.md +4 -4
- package/client-tmp/react/jest.config.ts +8 -4
- package/client-tmp/react/jest.setup.ts +85 -1
- package/client-tmp/react/oxlint-staged.js +45 -0
- package/client-tmp/react/package.json +24 -9
- package/client-tmp/react/playwright.config.ts +11 -10
- package/client-tmp/react/src/App.tsx +27 -29
- package/client-tmp/react/src/__mocks__/fileMock.js +1 -0
- package/client-tmp/react/src/components/ErrorMessage/ErrorMessage.test.tsx +16 -4
- package/client-tmp/react/src/components/ErrorMessage/ErrorMessage.tsx +32 -29
- package/client-tmp/react/src/components/error-boundary/ErrorBoundary.tsx +15 -6
- package/client-tmp/react/src/components/routes/AppRoutes.tsx +1 -1
- package/client-tmp/react/src/components/single-component/registry.ts +4 -0
- package/client-tmp/react/src/custom-elements.d.ts +4 -2
- package/client-tmp/react/src/helpers/hasPermissionHelper.tsx +1 -1
- package/client-tmp/react/src/helpers/isAuthenticatedHelper.tsx +1 -1
- package/client-tmp/react/src/helpers/isConnectedHelper.tsx +3 -3
- package/client-tmp/react/src/layouts/blank/BlankLayout.tsx +7 -11
- package/client-tmp/react/src/layouts/default/DefaultLayout.tsx +8 -8
- package/client-tmp/react/src/main.tsx +11 -11
- package/client-tmp/react/src/pages/AuthPage/AuthPage.test.tsx +13 -2
- package/client-tmp/react/src/pages/AuthPage/AuthPage.tsx +14 -13
- package/client-tmp/react/src/pages/NotFoundPage/NotFoundPage.tsx +2 -7
- package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.test.tsx +8 -4
- package/client-tmp/react/src/pages/NotPermittedPage/NotPermittedPage.tsx +1 -1
- package/client-tmp/react/src/pbc/container.tsx +9 -4
- package/client-tmp/react/src/pbc/elementsRenderer.tsx +13 -7
- package/client-tmp/react/src/pbc/utils.ts +60 -59
- package/client-tmp/react/src/services/auth.service.ts +1 -1
- package/client-tmp/react/src/services/store.service.ts +5 -3
- package/client-tmp/react/src/share/foundation-login.ts +2 -2
- package/client-tmp/react/src/share/genesis-components.ts +46 -47
- package/client-tmp/react/src/store/AuthContext.tsx +2 -10
- package/client-tmp/react/src/store/RoutesContext.test.tsx +99 -0
- package/client-tmp/react/src/store/RoutesContext.tsx +25 -5
- package/client-tmp/react/src/styles/styles.css +7 -7
- package/client-tmp/react/src/types/LayoutName.ts +1 -1
- package/client-tmp/react/src/utils/getLayoutNameByRoute.ts +1 -1
- package/client-tmp/react/src/utils/index.ts +2 -0
- package/client-tmp/react/src/utils/layout.ts +8 -1
- package/client-tmp/react/src/utils/permissions.ts +7 -7
- package/client-tmp/react/src/utils/useDocumentTitle.ts +5 -6
- package/client-tmp/react/test/e2e/fixture.ts +5 -2
- package/client-tmp/react/test/e2e/flows/001-protected.e2e.ts +3 -1
- package/client-tmp/react/tsconfig.app.json +1 -1
- package/client-tmp/react/tsconfig.json +1 -5
- package/client-tmp/web-components/.oxfmtrc.json +30 -0
- package/client-tmp/web-components/.oxlintrc.json +4 -0
- package/client-tmp/web-components/oxlint-staged.js +45 -0
- package/client-tmp/web-components/package.json +14 -22
- package/client-tmp/web-components/src/components/components.ts +9 -7
- package/client-tmp/web-components/src/main/main.css +1 -2
- package/client-tmp/web-components/src/main/main.ts +1 -1
- package/client-tmp/web-components/src/routes/config.ts +4 -0
- package/client-tmp/web-components/src/utils/index.ts +2 -0
- package/client-tmp/web-components/tsconfig.json +1 -4
- package/package.json +1 -1
- package/.genx/templates/angular/gridLayout.hbs +0 -30
- package/.genx/templates/angular/horizontalLayout.hbs +0 -7
- package/.genx/templates/angular/tabsLayout.hbs +0 -7
- package/.genx/tests/fixtures/testapp/client/src/routes/home/home.template.ts +0 -6
- package/.github/workflows/release.yml +0 -50
- package/client-tmp/react/.babelrc +0 -10
- package/client-tmp/react/.eslintrc.cjs +0 -21
- package/client-tmp/react/git +0 -0
- package/client-tmp/react/webpack.config.js +0 -121
- package/client-tmp/web-components/.prettierignore +0 -14
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a value as a JS/TS string literal, quotes included, in the exact shape
|
|
3
|
+
* oxfmt (`singleQuote: true`, prettier semantics) would print it — so generated
|
|
4
|
+
* code passes `oxfmt --check` without a reformat pass.
|
|
5
|
+
*
|
|
6
|
+
* Two things have to be right:
|
|
7
|
+
*
|
|
8
|
+
* 1. Escaping. Naively escaping only apostrophes breaks on backslashes
|
|
9
|
+
* (`back\` swallows the closing quote) and on newlines/tabs/control
|
|
10
|
+
* characters (an unterminated literal). `JSON.stringify` already escapes
|
|
11
|
+
* `\`, `"` and every control character exactly the way oxfmt prints them.
|
|
12
|
+
* 2. Quote choice. oxfmt prefers single quotes but flips to double quotes when
|
|
13
|
+
* the content contains strictly more apostrophes than double quotes (fewer
|
|
14
|
+
* escapes wins). Emitting `'Trader\'s Book'` would therefore be rewritten to
|
|
15
|
+
* `"Trader's Book"` by oxfmt and fail `--check`.
|
|
16
|
+
*
|
|
17
|
+
* @param {unknown} value value to render (coerced with String())
|
|
18
|
+
* @returns {string} the literal, including its enclosing quotes
|
|
19
|
+
*/
|
|
20
|
+
const toJsStringLiteral = (value) => {
|
|
21
|
+
const str = String(value);
|
|
22
|
+
const singleQuotes = (str.match(/'/g) || []).length;
|
|
23
|
+
const doubleQuotes = (str.match(/"/g) || []).length;
|
|
24
|
+
|
|
25
|
+
// JSON escaping, minus the enclosing double quotes.
|
|
26
|
+
const jsonBody = JSON.stringify(str).slice(1, -1);
|
|
27
|
+
|
|
28
|
+
if (singleQuotes > doubleQuotes) return `"${jsonBody}"`;
|
|
29
|
+
|
|
30
|
+
// Re-target the escaping at apostrophes: in a JSON body every `"` is escaped
|
|
31
|
+
// and every `'` is not, which is the mirror image of what a single-quoted
|
|
32
|
+
// literal needs.
|
|
33
|
+
const body = jsonBody.replace(/\\"/g, '"').replace(/'/g, "\\'");
|
|
34
|
+
return `'${body}'`;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = toJsStringLiteral;
|
|
@@ -10,6 +10,27 @@ concurrency:
|
|
|
10
10
|
cancel-in-progress: true
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
|
+
# The `build` job below covers React end to end (gradle build, lint, unit + e2e) for
|
|
14
|
+
# the defaults app. This job keeps every framework's generator honest: for each one it
|
|
15
|
+
# generates the defaults app, the full-routes fixture app and an FDC3-channels app,
|
|
16
|
+
# and runs the ox lint gates over all three.
|
|
17
|
+
generated-apps:
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
framework: [react, webcomponents, angular]
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Node
|
|
27
|
+
uses: actions/setup-node@v4
|
|
28
|
+
with:
|
|
29
|
+
node-version: 22
|
|
30
|
+
|
|
31
|
+
- name: Generate and lint ${{ matrix.framework }} apps (default + full + fdc3)
|
|
32
|
+
run: ./.genx/scripts/generate-test-apps.sh ${{ matrix.framework }}
|
|
33
|
+
|
|
13
34
|
build:
|
|
14
35
|
env:
|
|
15
36
|
genesisArtifactoryUser: ${{ secrets.JFROG_LIBS_RELEASE_CLIENT_RO_USER }}
|
|
@@ -40,7 +61,7 @@ jobs:
|
|
|
40
61
|
|
|
41
62
|
- name: Generate sample app
|
|
42
63
|
working-directory: /tmp
|
|
43
|
-
run: npx -y @genesislcap/genx@latest init testapp -s "${{github.workspace}}" -x --enableDeployPlugin
|
|
64
|
+
run: npx -y @genesislcap/genx@latest init testapp -s "${{github.workspace}}" -x --framework react --enableDeployPlugin
|
|
44
65
|
|
|
45
66
|
- name: Copy fixtures
|
|
46
67
|
run: cp -R ./.genx/tests/fixtures/testapp/* /tmp/testapp
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main, prerelease]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: deploy
|
|
12
|
+
concurrency:
|
|
13
|
+
group: publish-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
id-token: write
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
token: ${{secrets.GH_USER_TOKEN}}
|
|
22
|
+
|
|
23
|
+
- name: Set up Node
|
|
24
|
+
uses: actions/setup-node@v4
|
|
25
|
+
with:
|
|
26
|
+
node-version: 20
|
|
27
|
+
registry-url: https://registry.npmjs.org
|
|
28
|
+
|
|
29
|
+
- name: Upgrade npm for trusted publishing
|
|
30
|
+
run: npm install -g npm@^11.5.1
|
|
31
|
+
|
|
32
|
+
- name: Release
|
|
33
|
+
env:
|
|
34
|
+
GH_TOKEN: ${{secrets.GH_USER_TOKEN}}
|
|
35
|
+
run: |
|
|
36
|
+
touch /tmp/dist-tag # create a blank file, so it's always there even if we don't do a release
|
|
37
|
+
npm install
|
|
38
|
+
npm run release
|
|
39
|
+
|
|
40
|
+
- name: Set dist tag
|
|
41
|
+
id: dist-tag
|
|
42
|
+
run: |
|
|
43
|
+
NAME=$(node -p "require('./package.json').name")
|
|
44
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
45
|
+
|
|
46
|
+
TAG=$(cat /tmp/dist-tag)
|
|
47
|
+
if [ -z "$TAG" ]; then
|
|
48
|
+
# No release happened this run. Derive the tag the current
|
|
49
|
+
# package.json version would have released under, so a
|
|
50
|
+
# previous run's failed publish can still be retried below.
|
|
51
|
+
#
|
|
52
|
+
# NOTE: this assumes the version's prerelease identifier and the
|
|
53
|
+
# semantic-release channel are the same string. That only holds
|
|
54
|
+
# because .releaserc's "prerelease" branch has no explicit
|
|
55
|
+
# "channel", so semantic-release defaults both the preid and the
|
|
56
|
+
# channel to the branch name. If that branch config ever sets an
|
|
57
|
+
# explicit "channel" or a differing "prerelease" identifier, this
|
|
58
|
+
# derivation will diverge from the real channel and this retry
|
|
59
|
+
# path will publish under the wrong dist-tag.
|
|
60
|
+
case "$VERSION" in
|
|
61
|
+
*-*) TAG="${VERSION#*-}"; TAG="${TAG%%.*}" ;;
|
|
62
|
+
*) TAG="latest" ;;
|
|
63
|
+
esac
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Key the publish decision off the registry rather than off
|
|
67
|
+
# whether *this* run produced a release, so a flaky publish
|
|
68
|
+
# after semantic-release has already committed/tagged is
|
|
69
|
+
# retried on the next run instead of silently skipped.
|
|
70
|
+
# (stderr is captured separately so a stray npm notice on stderr
|
|
71
|
+
# can't masquerade as a real version and suppress the E404 check.)
|
|
72
|
+
if OUT=$(npm view "$NAME@$VERSION" version 2>/tmp/npm-view-err); then
|
|
73
|
+
[ -n "$OUT" ] && NEEDS_PUBLISH=false || NEEDS_PUBLISH=true
|
|
74
|
+
else
|
|
75
|
+
ERR=$(cat /tmp/npm-view-err)
|
|
76
|
+
case "$ERR" in
|
|
77
|
+
*E404*) NEEDS_PUBLISH=true ;;
|
|
78
|
+
*)
|
|
79
|
+
echo "::error::npm view failed unexpectedly: $ERR"
|
|
80
|
+
exit 1
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
echo "TAG=$TAG" >> "$GITHUB_OUTPUT"
|
|
86
|
+
echo "NEEDS_PUBLISH=$NEEDS_PUBLISH" >> "$GITHUB_OUTPUT"
|
|
87
|
+
|
|
88
|
+
- name: Generate .npmignore
|
|
89
|
+
run: cp .gitignore .npmignore && echo '!.gitignore' >> .npmignore && cat .npmignore
|
|
90
|
+
|
|
91
|
+
- name: NPM pack dry-run
|
|
92
|
+
run: npm pack --dry-run
|
|
93
|
+
|
|
94
|
+
- name: Publish
|
|
95
|
+
if: steps.dist-tag.outputs.NEEDS_PUBLISH == 'true'
|
|
96
|
+
run: npm publish --tag "${{ steps.dist-tag.outputs.TAG }}"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
#
|
|
3
|
+
# Git pre-commit hook. Enabled by `npm run git:setup` from the client directory,
|
|
4
|
+
# which points core.hooksPath at this directory (husky).
|
|
5
|
+
#
|
|
6
|
+
# Runs lint-staged in client/, where the oxlint/oxfmt binaries and the
|
|
7
|
+
# lint-staged config live.
|
|
8
|
+
cd client && npx --no lint-staged
|
package/.releaserc
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.23.0](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v5.22.1...v5.23.0) (2026-08-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* CI builds the react app; react jest stack repaired; store uses slice initial state [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 62db073
|
|
9
|
+
* oxlint/oxfmt as default linters [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 7ec4e78
|
|
10
|
+
* oxlint/oxfmt as default linters [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 6496554
|
|
11
|
+
* oxlint/oxfmt as default linters [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) (#575) b64f8b9
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* address code review - serializer robustness, permission semantics, tooling hardening [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 565c9ce
|
|
17
|
+
* address follow-up review - empty gridOptions, react CI coverage, husky invocation [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) c529d7e
|
|
18
|
+
* document-title fallback uses the app name, not 'React App' [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 5d099a7
|
|
19
|
+
* e2e tests actually navigate; template escaping and dead-code cleanups [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) b43ae68
|
|
20
|
+
* generated apps lint-clean out of the box for all frameworks, tiles and layouts [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) f8ee12f
|
|
21
|
+
* pre-commit lint fixes to convergence before gating [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) d9dc184
|
|
22
|
+
* quiet oxlint-staged fix passes and surface spawn failures [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 33ccf58
|
|
23
|
+
* schema import gating, FDC3 width pin, generated-dir glob alignment [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) dfbfd2a
|
|
24
|
+
* type-check and build cleanliness for generated apps [FUI-2489](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/2489) 8838670
|
|
25
|
+
|
|
3
26
|
## [5.22.1](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v5.22.0...v5.22.1) (2026-08-06)
|
|
4
27
|
|
|
5
28
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"semi": true,
|
|
3
|
+
"tabWidth": 2,
|
|
4
|
+
"singleQuote": true,
|
|
5
|
+
"bracketSpacing": true,
|
|
6
|
+
"printWidth": 100,
|
|
7
|
+
"htmlWhitespaceSensitivity": "ignore",
|
|
8
|
+
"sortPackageJson": false,
|
|
9
|
+
"ignorePatterns": [
|
|
10
|
+
"**/.git",
|
|
11
|
+
"**/.svn",
|
|
12
|
+
"**/.hg",
|
|
13
|
+
"**/node_modules",
|
|
14
|
+
"**/__tests__",
|
|
15
|
+
"**/__test__",
|
|
16
|
+
"**/.tmp",
|
|
17
|
+
"**/bootstrap",
|
|
18
|
+
"**/coverage",
|
|
19
|
+
"**/test-results",
|
|
20
|
+
"**/dist",
|
|
21
|
+
"**/.angular",
|
|
22
|
+
"**/out-tsc",
|
|
23
|
+
"**/temp",
|
|
24
|
+
"**/storybook-static",
|
|
25
|
+
"**/*.d.ts",
|
|
26
|
+
"**/*.md",
|
|
27
|
+
"**/*.hbs",
|
|
28
|
+
"**/.genx/**",
|
|
29
|
+
"**/src/generated/**",
|
|
30
|
+
"**/*.html"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -25,7 +25,8 @@ Run `npm run test:e2e` to execute the end-to-end tests via a platform of your ch
|
|
|
25
25
|
|
|
26
26
|
## Linting
|
|
27
27
|
|
|
28
|
-
Run `npm run lint` to lint the project.
|
|
28
|
+
Run `npm run lint` to lint the project (Oxlint → Oxfmt → Stylelint via `genx lint -l ox`).
|
|
29
|
+
Run `npm run lint:fix` to auto-fix lint findings and formatting.
|
|
29
30
|
|
|
30
31
|
## Styling
|
|
31
32
|
|
|
@@ -50,9 +51,8 @@ modes, and the selected mode is remembered across reloads.
|
|
|
50
51
|
- `npm run dev:intellij`: Serves the project in development mode (specific for IntelliJ).
|
|
51
52
|
- `npm run dev:https`: Serves the project in development mode with HTTPS.
|
|
52
53
|
- `npm run dev:webpack`: Serves the project in development mode (specific for webpack configuration).
|
|
53
|
-
- `npm run lint`: Lints the project
|
|
54
|
-
- `npm run lint:fix`: Fixes
|
|
55
|
-
- `npm run lint:eslint`: Lints the project using ESLint and the specified profile.
|
|
54
|
+
- `npm run lint`: Lints the project (Oxlint → Oxfmt → Stylelint).
|
|
55
|
+
- `npm run lint:fix`: Fixes lint findings and formatting.
|
|
56
56
|
- `npm run lint:stylelint`: Lints CSS using a custom script.
|
|
57
57
|
- `npm run test`: Runs unit tests.
|
|
58
58
|
- `npm run test:e2e`: Runs end-to-end tests.
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
-
const
|
|
2
|
+
const { readdirSync } = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
const IGNORED_DIRS = new Set([
|
|
6
|
+
'node_modules',
|
|
7
|
+
'dist',
|
|
8
|
+
'build',
|
|
9
|
+
'coverage',
|
|
10
|
+
'.angular',
|
|
11
|
+
'out-tsc',
|
|
12
|
+
'test-results',
|
|
13
|
+
'.git',
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
function findCssFiles(dir) {
|
|
17
|
+
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
return IGNORED_DIRS.has(entry.name) ? [] : findCssFiles(path.join(dir, entry.name));
|
|
20
|
+
}
|
|
21
|
+
return entry.isFile() && entry.name.endsWith('.css') ? [path.join(dir, entry.name)] : [];
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const cssFiles = findCssFiles(__dirname);
|
|
5
26
|
|
|
6
27
|
if (cssFiles.length === 0) {
|
|
7
28
|
console.log('No CSS files found.');
|
|
@@ -15,4 +36,4 @@ try {
|
|
|
15
36
|
} catch (error) {
|
|
16
37
|
console.error('Error running stylelint:', error);
|
|
17
38
|
process.exit(1);
|
|
18
|
-
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lints the staged files, fixing what can be fixed and failing on what cannot.
|
|
3
|
+
*
|
|
4
|
+
* `oxlint --fix` is not single-pass convergent: it applies at most one fix per
|
|
5
|
+
* overlapping span, so a file with several unused specifiers in one import
|
|
6
|
+
* statement still reports the rest afterwards. A single
|
|
7
|
+
* `oxlint --fix --deny-warnings` would therefore reject a commit whose findings
|
|
8
|
+
* are entirely auto-fixable, and lint-staged would revert the partial fix. There
|
|
9
|
+
* is no `--fix-passes` flag (oxlint 1.78), so the loop lives here; it can go
|
|
10
|
+
* back to one plain call once oxlint converges on its own.
|
|
11
|
+
*
|
|
12
|
+
* The fixing passes stay quiet so a remaining finding is reported once, by the
|
|
13
|
+
* final pass, rather than once per attempt.
|
|
14
|
+
*/
|
|
15
|
+
const { spawnSync } = require('node:child_process');
|
|
16
|
+
|
|
17
|
+
/** Convergence needs about log2(findings) passes; this is well clear of that. */
|
|
18
|
+
const MAX_PASSES = 10;
|
|
19
|
+
|
|
20
|
+
const files = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
const runOxlint = (args, quiet) =>
|
|
23
|
+
spawnSync('oxlint', [...args, ...files], {
|
|
24
|
+
stdio: quiet ? 'ignore' : 'inherit',
|
|
25
|
+
shell: process.platform === 'win32',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (files.length === 0) {
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (let pass = 0; pass < MAX_PASSES; pass += 1) {
|
|
33
|
+
const { status, error } = runOxlint(['--fix', '--deny-warnings'], true);
|
|
34
|
+
if (error) {
|
|
35
|
+
// Never fail silently: a missing binary must not look like a lint failure.
|
|
36
|
+
console.error(`oxlint-staged: could not run oxlint (${error.code})`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (status === 0) {
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Still not clean: report what is left (without touching the files again) and fail.
|
|
45
|
+
process.exit(runOxlint(['--deny-warnings'], false).status === 0 ? 0 : 1);
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"dev:intellij": "npm run dev",
|
|
29
29
|
"dev:https": "npm run dev -- --https",
|
|
30
30
|
"dev:webpack": "npm run dev",
|
|
31
|
-
"
|
|
32
|
-
"lint
|
|
33
|
-
"lint:
|
|
31
|
+
"git:setup": "cd .. && npx --no --prefix client husky install",
|
|
32
|
+
"lint": "genx lint -l ox",
|
|
33
|
+
"lint:fix": "genx lint -l ox --fix",
|
|
34
34
|
"lint:stylelint": "node lint-css.js",
|
|
35
35
|
"test": "jest",
|
|
36
36
|
"test:e2e": "genx test --e2e",
|
|
@@ -39,39 +39,49 @@
|
|
|
39
39
|
"test:coverage": "ng test --no-watch --code-coverage",
|
|
40
40
|
"test:unit:watch": "ng test --watch"
|
|
41
41
|
},
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
42
|
+
"lint-staged": {
|
|
43
|
+
"*.{ts,js,tsx,jsx}": [
|
|
44
|
+
"node oxlint-staged.js",
|
|
45
|
+
"oxfmt --write"
|
|
46
|
+
],
|
|
47
|
+
"*.{mjs,cjs}": [
|
|
48
|
+
"oxfmt --write"
|
|
49
|
+
]
|
|
45
50
|
},
|
|
46
51
|
"stylelint": {
|
|
47
52
|
"extends": "@genesislcap/stylelint-config"
|
|
48
53
|
},
|
|
49
|
-
"prettier": "@genesislcap/prettier-config",
|
|
50
54
|
"devDependencies": {
|
|
51
55
|
"@angular-builders/custom-webpack": "^18.0.0",
|
|
52
56
|
"@angular-devkit/build-angular": "^18.0.4",
|
|
53
57
|
"@angular/cli": "^18.0.4",
|
|
54
58
|
"@angular/compiler-cli": "^18.0.4",
|
|
55
59
|
"@genesislcap/design-system-configurator": "{{versions.UI}}",
|
|
56
|
-
"@genesislcap/eslint-config": "{{versions.UI}}",
|
|
57
|
-
"@genesislcap/prettier-config": "{{versions.UI}}",
|
|
58
60
|
"@genesislcap/foundation-testing": "{{versions.UI}}",
|
|
59
61
|
"@genesislcap/genx": "{{versions.UI}}",
|
|
60
62
|
"@genesislcap/event-type-codegen": "{{versions.UI}}",
|
|
61
63
|
"@genesislcap/build-kit": "{{versions.UI}}",
|
|
64
|
+
"@genesislcap/oxlint-config": "{{versions.UI}}",
|
|
65
|
+
"@genesislcap/stylelint-config": "{{versions.UI}}",
|
|
62
66
|
"@types/jasmine": "~5.1.0",
|
|
63
67
|
"@types/jest": "^29.5.13",
|
|
64
68
|
"@types/numeral": "^2.0.5",
|
|
65
69
|
"file-loader": "^6.2.0",
|
|
70
|
+
"husky": "^7.0.4",
|
|
66
71
|
"jasmine-core": "~5.1.0",
|
|
67
72
|
"jest": "^29.7.0",
|
|
68
73
|
"jest-environment-jsdom": "^29.7.0",
|
|
69
74
|
"jest-preset-angular": "^14.2.4",
|
|
70
75
|
"jest-transform-stub": "^2.0.0",
|
|
76
|
+
"lint-staged": "^12.4.1",
|
|
77
|
+
"oxfmt": "^0.44.0",
|
|
78
|
+
"oxlint": "^1.77.0",
|
|
71
79
|
"svg-url-loader": "^8.0.0",
|
|
80
|
+
"ts-jest": "^29.2.5",
|
|
72
81
|
"typescript": "~5.4.5",
|
|
73
82
|
"ts-node": "10.9.2",
|
|
74
83
|
"dotenv": "16.4.5",
|
|
84
|
+
"webpack": "5.94.0",
|
|
75
85
|
"@types/node": "20.14.11"
|
|
76
86
|
},
|
|
77
87
|
"dependencies": {
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { configDefaults } from '@genesislcap/foundation-testing/e2e';
|
|
2
|
-
import { environment } from './src/environments/environment';
|
|
3
2
|
import * as dotenv from 'dotenv';
|
|
3
|
+
import { environment } from './src/environments/environment';
|
|
4
4
|
|
|
5
5
|
dotenv.config();
|
|
6
6
|
|
|
7
7
|
const PROTOCOL = process.env['PROTOCOL'] || environment.PROTOCOL || 'http';
|
|
8
8
|
const HOST = process.env['HOST'] || environment.HOST || 'localhost';
|
|
9
|
+
// oxlint-disable-next-line no-magic-numbers -- 4200 is the standard Angular dev server port
|
|
9
10
|
const PORT = process.env['PORT'] || environment.PORT || 4200;
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
13
|
+
...configDefaults,
|
|
14
|
+
webServer: {
|
|
15
|
+
...configDefaults.webServer,
|
|
16
|
+
url: `${PROTOCOL}://${HOST}:${PORT}`,
|
|
17
|
+
},
|
|
18
|
+
use: {
|
|
19
|
+
...configDefaults.use,
|
|
20
|
+
baseURL: `${PROTOCOL}://${HOST}:${PORT}`,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
|
2
2
|
import { Router, NavigationEnd } from '@angular/router';
|
|
3
3
|
import { Connect } from '@genesislcap/foundation-comms';
|
|
4
|
-
import
|
|
5
|
-
import type { LayoutComponentName } from './types/layout';
|
|
4
|
+
import { customEventFactory, registerStylesTarget } from '../pbc/utils';
|
|
6
5
|
import { configureFoundationAuth } from './share/foundation-auth';
|
|
7
6
|
import { registerComponents } from './share/genesis-components';
|
|
8
7
|
import { getStore } from './store/foundation-store';
|
|
9
|
-
import {
|
|
8
|
+
import type { LayoutComponentName } from './types/layout';
|
|
10
9
|
{{#if FDC3.channels.length}}
|
|
11
10
|
import { listenToChannel, onFDC3Ready } from './utils';
|
|
12
11
|
{{/if}}
|
|
12
|
+
import getLayoutNameByRoute from './utils/getLayoutNameByRoute';
|
|
13
13
|
|
|
14
14
|
@Component({
|
|
15
15
|
selector: '{{rootElement}}',
|
|
@@ -30,7 +30,7 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|
|
30
30
|
) {
|
|
31
31
|
// @ts-ignore
|
|
32
32
|
configureFoundationAuth({ router, connectService: this.connect });
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
// Set layout componet based on route
|
|
35
35
|
router.events.subscribe((event: any) => {
|
|
36
36
|
if (event instanceof NavigationEnd) {
|
|
@@ -76,22 +76,21 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|
|
76
76
|
this.el.nativeElement.dispatchEvent(customEventFactory(type, detail));
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
{{#if FDC3.channels.length}}
|
|
80
80
|
ngAfterViewInit() {
|
|
81
|
-
{{#if FDC3.channels.length}}
|
|
82
81
|
onFDC3Ready(this.FDC3ReadyHandler);
|
|
83
|
-
{{/if}}
|
|
84
82
|
}
|
|
85
83
|
|
|
86
|
-
{{#if FDC3.channels.length}}
|
|
87
84
|
FDC3ReadyHandler = () => {
|
|
88
85
|
{{#each FDC3.channels}}
|
|
89
86
|
listenToChannel('{{this.name}}', '{{this.type}}', (result) => {
|
|
90
|
-
console.log('Received FDC3
|
|
87
|
+
console.log('Received FDC3 message on {{this.name}} ({{this.type}})', result);
|
|
91
88
|
// TODO: Add your listener logic here
|
|
92
89
|
// E.g. open a modal or route to specific page: Route.path.push(`[Route name]`);
|
|
93
90
|
});
|
|
94
91
|
{{/each}}
|
|
95
92
|
};
|
|
93
|
+
{{else}}
|
|
94
|
+
ngAfterViewInit() {}
|
|
96
95
|
{{/if}}
|
|
97
96
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LayoutComponentName } from './types/layout';
|
|
2
2
|
|
|
3
|
-
export const AUTH_PATH = 'login'
|
|
4
|
-
export const NOT_PERMITTED_PATH = 'not-permitted'
|
|
3
|
+
export const AUTH_PATH = 'login';
|
|
4
|
+
export const NOT_PERMITTED_PATH = 'not-permitted';
|
|
5
5
|
|
|
6
6
|
export const layoutComponentName = {
|
|
7
7
|
default: 'DefaultLayoutComponent',
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, APP_INITIALIZER } from '@angular/core';
|
|
2
|
-
import { BrowserModule } from '@angular/platform-browser';
|
|
3
2
|
import { FormsModule } from '@angular/forms';
|
|
3
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
4
4
|
import { Router, RouterModule } from '@angular/router';
|
|
5
|
+
import { provideRedux } from '@reduxjs/angular-redux';
|
|
5
6
|
import { PBCContainer } from '../pbc/container';
|
|
6
7
|
import { PBCElementsRenderer } from '../pbc/elementsRenderer';
|
|
7
8
|
import { AppComponent } from './app.component';
|
|
8
|
-
import { DefaultLayoutComponent } from './layouts/default/default.layout';
|
|
9
|
-
import { BlankLayoutComponent } from './layouts/blank/blank.layout';
|
|
10
9
|
import { LayoutLazyLoadDirective } from './directive/app-lazy-load.directive';
|
|
10
|
+
import { BlankLayoutComponent } from './layouts/blank/blank.layout';
|
|
11
|
+
import { DefaultLayoutComponent } from './layouts/default/default.layout';
|
|
11
12
|
import { RouteService } from './services/route.service';
|
|
12
|
-
import { provideRedux } from '@reduxjs/angular-redux';
|
|
13
13
|
import { reduxStore } from './store/store';
|
|
14
14
|
|
|
15
15
|
@NgModule({
|
|
@@ -31,7 +31,8 @@ import { reduxStore } from './store/store';
|
|
|
31
31
|
provideRedux({ store: reduxStore }),
|
|
32
32
|
{
|
|
33
33
|
provide: APP_INITIALIZER,
|
|
34
|
-
useFactory: (service: RouteService, router: Router) => () =>
|
|
34
|
+
useFactory: (service: RouteService, router: Router) => () =>
|
|
35
|
+
router.resetConfig(service.allRoutes()),
|
|
35
36
|
deps: [RouteService, Router],
|
|
36
37
|
multi: true,
|
|
37
38
|
},
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
<section class="error-message-wrapper">
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
<section class="error-message-wrapper">
|
|
2
|
+
<div
|
|
3
|
+
class="error-message"
|
|
4
|
+
style="
|
|
5
|
+
color: var(--neutral-foreground-rest);
|
|
6
|
+
background-color: var(--neutral-layer-4);
|
|
7
|
+
border-color: var(--error-color);
|
|
8
|
+
border-radius: 7px;
|
|
9
|
+
border-style: solid;
|
|
10
|
+
border-width: 4px;
|
|
11
|
+
padding: 5px;
|
|
12
|
+
margin: 15px;
|
|
13
|
+
text-align: center;
|
|
14
|
+
width: fit-content;
|
|
15
|
+
"
|
|
16
|
+
>
|
|
17
|
+
<ng-container [ngSwitch]="elementType">
|
|
18
|
+
<h1 *ngSwitchCase="'h1'">\{{ message }}</h1>
|
|
19
|
+
<h2 *ngSwitchCase="'h2'">\{{ message }}</h2>
|
|
20
|
+
<h3 *ngSwitchCase="'h3'">\{{ message }}</h3>
|
|
21
|
+
<h4 *ngSwitchCase="'h4'">\{{ message }}</h4>
|
|
22
|
+
<h5 *ngSwitchCase="'h5'">\{{ message }}</h5>
|
|
23
|
+
<h6 *ngSwitchCase="'h6'">\{{ message }}</h6>
|
|
24
|
+
<p *ngSwitchCase="'p'">\{{ message }}</p>
|
|
25
|
+
<span *ngSwitchCase="'span'">\{{ message }}</span>
|
|
26
|
+
<div *ngSwitchDefault>\{{ message }}</div>
|
|
27
|
+
</ng-container>
|
|
28
|
+
</div>
|
|
29
|
+
</section>
|
|
@@ -66,9 +66,9 @@ describe('ErrorMessageComponent', () => {
|
|
|
66
66
|
component.elementType = 'h2';
|
|
67
67
|
component.message = 'Testing class application.';
|
|
68
68
|
fixture.detectChanges();
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
const compiled = fixture.nativeElement;
|
|
71
71
|
const element = compiled.querySelector('.error-message');
|
|
72
72
|
expect(element).toBeTruthy();
|
|
73
73
|
});
|
|
74
|
-
});
|
|
74
|
+
});
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { Component, Input } from '@angular/core';
|
|
2
1
|
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
@Component({
|
|
5
5
|
selector: 'app-error-message',
|
|
6
6
|
templateUrl: './error-message.component.html',
|
|
7
7
|
standalone: true,
|
|
8
|
-
imports: [
|
|
9
|
-
CommonModule,
|
|
10
|
-
],
|
|
8
|
+
imports: [CommonModule],
|
|
11
9
|
})
|
|
12
10
|
export class ErrorMessageComponent {
|
|
13
11
|
@Input() elementType: string = 'div';
|
|
14
12
|
@Input() message: string = '';
|
|
15
|
-
}
|
|
13
|
+
}
|