@igstack/app-catalog-frontend-core 0.6.1 → 0.6.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.
- package/dist/esm/__tests__/integration/notFoundRoute.integration.test.d.ts +0 -0
- package/dist/esm/modules/auth/AuthContext.js +1 -1
- package/dist/esm/modules/auth/AuthModalContext.js +1 -1
- package/dist/esm/routes/__root.js +8 -2
- package/dist/esm/routes/__root.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/integration/harness/given.tsx +8 -1
- package/src/__tests__/integration/notFoundRoute.integration.test.tsx +34 -0
- package/src/routes/__root.tsx +16 -2
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useEffect, useMemo, createContext, use } from "react";
|
|
3
3
|
const AuthContext = createContext(void 0);
|
|
4
4
|
const STORAGE_KEY = "ac_auth_user";
|
|
5
5
|
function AuthProvider({ children }) {
|
|
@@ -3,11 +3,17 @@ import { createRootRouteWithContext, Outlet } from "@tanstack/react-router";
|
|
|
3
3
|
import { RootErrorPage } from "../ui/components/error/RootErrorPage.js";
|
|
4
4
|
import { NotFoundError } from "../ui/error/NotFoundError.js";
|
|
5
5
|
import { LoadingScreen } from "../ui/layout/LoadingScreen.js";
|
|
6
|
+
import { TopLevelProvidersForErrors } from "../ui/layout/TopLevelProvidersForErrors.js";
|
|
6
7
|
const Route = createRootRouteWithContext()({
|
|
7
8
|
component: RootRoute,
|
|
8
9
|
errorComponent: RootErrorPage,
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
// These fallbacks render MainLayout → Header → useAuth(), so they must be
|
|
11
|
+
// wrapped in the providers (Auth + AuthModal + Theme + Tooltip). The router
|
|
12
|
+
// renders pending/notFound OUTSIDE the route-component subtree, i.e. outside
|
|
13
|
+
// the app's TopLevelProviders — without this wrap they throw
|
|
14
|
+
// "useAuth must be used within AuthProvider" (see #6/#7).
|
|
15
|
+
pendingComponent: () => /* @__PURE__ */ jsx(TopLevelProvidersForErrors, { children: /* @__PURE__ */ jsx(LoadingScreen, { label: "root pending" }) }),
|
|
16
|
+
notFoundComponent: () => /* @__PURE__ */ jsx(TopLevelProvidersForErrors, { children: /* @__PURE__ */ jsx(NotFoundError, {}) }),
|
|
11
17
|
wrapInSuspense: true
|
|
12
18
|
});
|
|
13
19
|
function RootRoute() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"__root.js","sources":["../../../src/routes/__root.tsx"],"sourcesContent":["import { Outlet, createRootRouteWithContext } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\nimport type { AcRouterContext } from '~/types/types'\nimport { RootErrorPage } from '~/ui/components/error/RootErrorPage'\nimport { NotFoundError } from '~/ui/error/NotFoundError'\nimport { LoadingScreen } from '~/ui/layout/LoadingScreen'\n\nexport const Route = createRootRouteWithContext<AcRouterContext>()({\n component: RootRoute,\n errorComponent: RootErrorPage,\n pendingComponent: () => <LoadingScreen label=\"root pending\"
|
|
1
|
+
{"version":3,"file":"__root.js","sources":["../../../src/routes/__root.tsx"],"sourcesContent":["import { Outlet, createRootRouteWithContext } from '@tanstack/react-router'\nimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'\nimport type { AcRouterContext } from '~/types/types'\nimport { RootErrorPage } from '~/ui/components/error/RootErrorPage'\nimport { NotFoundError } from '~/ui/error/NotFoundError'\nimport { LoadingScreen } from '~/ui/layout/LoadingScreen'\nimport { TopLevelProvidersForErrors } from '~/ui/layout/TopLevelProvidersForErrors'\n\nexport const Route = createRootRouteWithContext<AcRouterContext>()({\n component: RootRoute,\n errorComponent: RootErrorPage,\n // These fallbacks render MainLayout → Header → useAuth(), so they must be\n // wrapped in the providers (Auth + AuthModal + Theme + Tooltip). The router\n // renders pending/notFound OUTSIDE the route-component subtree, i.e. outside\n // the app's TopLevelProviders — without this wrap they throw\n // \"useAuth must be used within AuthProvider\" (see #6/#7).\n pendingComponent: () => (\n <TopLevelProvidersForErrors>\n <LoadingScreen label=\"root pending\" />\n </TopLevelProvidersForErrors>\n ),\n notFoundComponent: () => (\n <TopLevelProvidersForErrors>\n <NotFoundError />\n </TopLevelProvidersForErrors>\n ),\n wrapInSuspense: true,\n})\n\nfunction RootRoute() {\n return (\n <div className=\"min-h-screen bg-base-200\">\n <Outlet />\n {import.meta.env.MODE === 'dev' ? <TanStackRouterDevtools /> : null}\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;AAQO,MAAM,QAAQ,6BAA8C;AAAA,EACjE,WAAW;AAAA,EACX,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,kBAAkB,MAChB,oBAAC,4BAAA,EACC,8BAAC,eAAA,EAAc,OAAM,eAAA,CAAe,GACtC;AAAA,EAEF,mBAAmB,MACjB,oBAAC,4BAAA,EACC,UAAA,oBAAC,iBAAc,GACjB;AAAA,EAEF,gBAAgB;AAClB,CAAC;AAED,SAAS,YAAY;AACnB,SACE,qBAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAO;AAAA,IACuD;AAAA,EAAA,GACjE;AAEJ;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igstack/app-catalog-frontend-core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Frontend core library for App Catalog",
|
|
5
5
|
"homepage": "https://github.com/lislon/app-catalog",
|
|
6
6
|
"repository": {
|
|
@@ -134,8 +134,8 @@
|
|
|
134
134
|
"vite-plugin-static-copy": "^3.1.4",
|
|
135
135
|
"vite-plugin-svgr": "^4.2.0",
|
|
136
136
|
"vitest": "^4.1.2",
|
|
137
|
-
"@igstack/app-catalog-backend-core": "0.6.
|
|
138
|
-
"@igstack/app-catalog-shared-core": "0.6.
|
|
137
|
+
"@igstack/app-catalog-backend-core": "0.6.2",
|
|
138
|
+
"@igstack/app-catalog-shared-core": "0.6.2"
|
|
139
139
|
},
|
|
140
140
|
"peerDependencies": {
|
|
141
141
|
"react": "19.1.2",
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
"vite": "^6.3.5",
|
|
145
145
|
"vite-plugin-svgr": "^4.2.0"
|
|
146
146
|
},
|
|
147
|
-
"gitHead": "
|
|
147
|
+
"gitHead": "dcc2b0acf435e115ec42861ec79064c6394b1ada",
|
|
148
148
|
"scripts": {
|
|
149
149
|
"build": "vite build",
|
|
150
150
|
"build:lenient": "vite build --mode lenient",
|
|
@@ -174,7 +174,14 @@ export async function given(
|
|
|
174
174
|
const hasTanstackError = document.body.textContent.includes(
|
|
175
175
|
'Something went wrong',
|
|
176
176
|
)
|
|
177
|
-
|
|
177
|
+
const hasNotFound = document.body.textContent.includes('404 Not Found')
|
|
178
|
+
if (
|
|
179
|
+
!hasAlert &&
|
|
180
|
+
!hasTable &&
|
|
181
|
+
!hasSearchbox &&
|
|
182
|
+
!hasTanstackError &&
|
|
183
|
+
!hasNotFound
|
|
184
|
+
) {
|
|
178
185
|
throw new Error('Still loading...')
|
|
179
186
|
}
|
|
180
187
|
},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { screen, waitFor } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom/vitest'
|
|
4
|
+
|
|
5
|
+
import { given } from './harness/given'
|
|
6
|
+
import { magazine } from './mock-backend/magazines'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Regression for #7 (root cause in #6): the root route's `notFoundComponent`
|
|
10
|
+
* (`NotFoundError`) renders `MainLayout → Header → useAuth()`. Before the fix
|
|
11
|
+
* the fallback rendered OUTSIDE `AuthProvider`, so any unknown URL threw
|
|
12
|
+
* `useAuth must be used within AuthProvider` and the app showed its "Ooops!"
|
|
13
|
+
* error page instead of a clean 404.
|
|
14
|
+
*/
|
|
15
|
+
describe('Unknown URL renders NotFound without a useAuth error', () => {
|
|
16
|
+
it('shows the 404 page (not the useAuth error) for a bogus URL', async () => {
|
|
17
|
+
const { ui } = await given(magazine.full(), {
|
|
18
|
+
initialRoute: '/nonexistent-xyz',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
// The clean NotFound UI is rendered.
|
|
22
|
+
await waitFor(() => {
|
|
23
|
+
expect(screen.getByText('404 Not Found')).toBeInTheDocument()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// And crucially: NO useAuth error surfaced. The header (which calls
|
|
27
|
+
// useAuth) must render inside a provider, so the global error page must
|
|
28
|
+
// not appear at all.
|
|
29
|
+
expect(
|
|
30
|
+
screen.queryByText(/useAuth must be used within AuthProvider/),
|
|
31
|
+
).not.toBeInTheDocument()
|
|
32
|
+
expect(() => ui.globalError()).toThrow(/No global error found/)
|
|
33
|
+
})
|
|
34
|
+
})
|
package/src/routes/__root.tsx
CHANGED
|
@@ -4,12 +4,26 @@ import type { AcRouterContext } from '~/types/types'
|
|
|
4
4
|
import { RootErrorPage } from '~/ui/components/error/RootErrorPage'
|
|
5
5
|
import { NotFoundError } from '~/ui/error/NotFoundError'
|
|
6
6
|
import { LoadingScreen } from '~/ui/layout/LoadingScreen'
|
|
7
|
+
import { TopLevelProvidersForErrors } from '~/ui/layout/TopLevelProvidersForErrors'
|
|
7
8
|
|
|
8
9
|
export const Route = createRootRouteWithContext<AcRouterContext>()({
|
|
9
10
|
component: RootRoute,
|
|
10
11
|
errorComponent: RootErrorPage,
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
// These fallbacks render MainLayout → Header → useAuth(), so they must be
|
|
13
|
+
// wrapped in the providers (Auth + AuthModal + Theme + Tooltip). The router
|
|
14
|
+
// renders pending/notFound OUTSIDE the route-component subtree, i.e. outside
|
|
15
|
+
// the app's TopLevelProviders — without this wrap they throw
|
|
16
|
+
// "useAuth must be used within AuthProvider" (see #6/#7).
|
|
17
|
+
pendingComponent: () => (
|
|
18
|
+
<TopLevelProvidersForErrors>
|
|
19
|
+
<LoadingScreen label="root pending" />
|
|
20
|
+
</TopLevelProvidersForErrors>
|
|
21
|
+
),
|
|
22
|
+
notFoundComponent: () => (
|
|
23
|
+
<TopLevelProvidersForErrors>
|
|
24
|
+
<NotFoundError />
|
|
25
|
+
</TopLevelProvidersForErrors>
|
|
26
|
+
),
|
|
13
27
|
wrapInSuspense: true,
|
|
14
28
|
})
|
|
15
29
|
|