Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions tests/routes/entry.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';

const e = vi.hoisted(() => ({
hydrateRoot: vi.fn(),
removeEdgeInjections: vi.fn(),
initThemeSentry: vi.fn(),
bootClient: vi.fn(),
createStart: vi.fn((factory: () => unknown) => factory()),
twilightMiddleware: vi.fn(() => 'twilight'),
earlyHintsMiddleware: vi.fn(() => 'early-hints'),
withThemeSentry: vi.fn((handler: unknown, name: string) => ({ handler, name })),
}));

vi.mock('react-dom/client', () => ({ hydrateRoot: e.hydrateRoot }));
vi.mock('@tanstack/react-start/client', () => ({ StartClient: () => null }));
vi.mock('@salla.sa/twilight-theme-engine/sentry/client', () => ({
initThemeSentry: e.initThemeSentry,
}));
vi.mock('@salla.sa/twilight-theme-engine/dom', () => ({
removeEdgeInjections: e.removeEdgeInjections,
}));
vi.mock('@salla.sa/twilight-theme-engine/boot', () => ({ bootClient: e.bootClient }));
vi.mock('@salla.sa/twilight-theme-engine/sentry/server', () => ({
withThemeSentry: e.withThemeSentry,
}));
vi.mock('@tanstack/react-start/server-entry', () => ({ default: 'server-handler' }));
vi.mock('@tanstack/react-start', () => ({ createStart: e.createStart }));
vi.mock('@salla.sa/twilight-theme-engine/tanstack', () => ({
twilightMiddleware: e.twilightMiddleware,
earlyHintsMiddleware: e.earlyHintsMiddleware,
}));
vi.mock('../../app/hydrate', () => ({ hydrate: 'hydrate-fn' }));
vi.mock('../../app/styles/app.css?url', () => ({ default: '/app.css' }));

beforeEach(() => {
vi.clearAllMocks();
vi.resetModules();
});

describe('client entry', () => {
it('boots the client with the app stylesheet and the lazily loaded hydrator', async () => {
await import('../../app/client');
const options = e.bootClient.mock.calls[0][0];
expect(options.stylesheet).toBe('/app.css');
expect((await options.load()).hydrate).toBe('hydrate-fn');
});
});

describe('hydrate', () => {
it('reports errors to the theme Sentry project', async () => {
await vi.importActual('../../app/hydrate');
expect(e.initThemeSentry).toHaveBeenCalledWith('raed');
});

it('strips edge-injected nodes, then hydrates the whole document', async () => {
const { hydrate } =
await vi.importActual<typeof import('../../app/hydrate')>('../../app/hydrate');
hydrate();
expect(e.removeEdgeInjections).toHaveBeenCalledTimes(1);
await vi.waitFor(() => expect(e.hydrateRoot).toHaveBeenCalledTimes(1));
expect(e.hydrateRoot.mock.calls[0][0]).toBe(document);
Comment on lines +59 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cleanup order is not tested

This test checks that both functions run, but not that removeEdgeInjections runs before hydrateRoot. Reversing those calls would still pass despite the test's “then hydrates” claim.

The repository requires assertions to check the claimed behavior. Before merging, compare their recorded call order to protect cleanup before hydration.

Rule Used: What: Reject assertions that don't actually validate the expected behavior or outcome. Why: Fake assertions give false confidence in test coverage and fail to catch real bugs. Good: ```python def test_user_creation(): user = create_user("John",... (source)

Knowledge Base Used: Runtime entrypoints

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/routes/entry.test.tsx
Line: 59-61

Comment:
**Cleanup order is not tested**

This test checks that both functions run, but not that `removeEdgeInjections` runs before `hydrateRoot`. Reversing those calls would still pass despite the test's “then hydrates” claim.

The repository requires assertions to check the claimed behavior. Before merging, compare their recorded call order to protect cleanup before hydration.

**Rule Used:** What: Reject assertions that don't actually validate the expected behavior or outcome.  Why: Fake assertions give false confidence in test coverage and fail to catch real bugs.  Good: ```python def test_user_creation():     user = create_user("John",... ([source](https://app.greptile.com/salla/-/custom-context?memory=4475f6ab-b5f0-46e4-98d5-1f1eb133c1df))

**Knowledge Base Used:** [Runtime entrypoints](https://app.greptile.com/salla/-/custom-context/knowledge-base/sallaapp/theme-raed-react/-/docs/runtime-entrypoints.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

});
});

describe('start and server entries', () => {
it('runs the twilight and early-hints middleware on every request', async () => {
const { startInstance } = await import('../../app/start');
expect(startInstance).toEqual({ requestMiddleware: ['twilight', 'early-hints'] });
});

it('wraps the server handler with theme Sentry', async () => {
const mod = await import('../../app/server');
expect(mod.default).toEqual({ handler: 'server-handler', name: 'raed' });
});
});

describe('routes manifest', () => {
it('declares no custom routes', async () => {
const { routes } = await import('../../app/routes');
expect(routes).toEqual([]);
});
});
54 changes: 53 additions & 1 deletion tests/routes/root.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
*/
import { describe, it, expect, vi } from 'vitest';
import type { ComponentType } from 'react';
import { renderToString } from 'react-dom/server';
import { renderToString, renderToPipeableStream } from 'react-dom/server';
import { Writable } from 'node:stream';
import type { ThemeStylesheetProps } from '@salla.sa/twilight-theme-engine/tanstack';
import { HOME_ROUTE_ID, PRODUCT_ROUTE_ID } from '../../app/lib/routeIds';

Expand All @@ -26,13 +27,35 @@ vi.mock('@salla.sa/twilight-theme-engine/tanstack', () => ({
},
ThemeHeadContent: () => null,
}));
vi.mock('@salla.sa/twilight-theme-engine/dev', () => ({
DevSettingsWidget: () => 'dev-settings-widget',
}));
vi.mock('virtual:twilight/theme-translations', () => ({ default: {} }));
vi.mock('virtual:twilight/schema', () => ({ default: {} }));
vi.mock('../../app/components/layout/ThemeLayout', () => ({ ThemeLayout: () => null }));
vi.mock('../../app/styles/app.css?url', () => ({ default: '/app.css' }));
vi.mock('../../app/styles/critical.scss?inline', () => ({ default: '.home{color:red}' }));
vi.mock('../../app/styles/critical-product.scss?inline', () => ({ default: '.pdp{color:blue}' }));

const renderWhenReady = async (Shell: ComponentType) => {
let html = '';
const sink = new Writable({
write(chunk, _enc, done) {
html += chunk.toString();
done();
},
});
await new Promise<void>((resolve) => {
const stream = renderToPipeableStream(<Shell />, {
onAllReady: () => {
stream.pipe(sink);
sink.on('finish', resolve);
},
});
});
return html;
};

describe('root head', () => {
it('paints the home and product pages from their own critical CSS', async () => {
const { Route } = await import('../../app/routes/__root');
Expand All @@ -46,4 +69,33 @@ describe('root head', () => {
[PRODUCT_ROUTE_ID]: '.pdp{color:blue}',
});
});

it('offers the live settings editor in development', async () => {
const { Route } = await import('../../app/routes/__root');
const Shell = (Route as unknown as { shellComponent: ComponentType }).shellComponent;

const html = await renderWhenReady(Shell);

expect(html).toContain('dev-settings-widget');
});

it('ships no critical CSS or settings editor in the client production bundle', async () => {
vi.stubEnv('DEV', false);
vi.stubEnv('SSR', false);
vi.resetModules();
try {
const { Route } = await import('../../app/routes/__root');
const Shell = (Route as unknown as { shellComponent: ComponentType }).shellComponent;

const html = await renderWhenReady(Shell);

expect(rendered.stylesheet?.critical).toEqual({
[HOME_ROUTE_ID]: '',
[PRODUCT_ROUTE_ID]: '',
});
expect(html).not.toContain('dev-settings-widget');
} finally {
vi.unstubAllEnvs();
}
});
});
Loading
Loading