import assert from 'node:assert/strict'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import vue from '@vitejs/plugin-vue'; import tailwind from '@tailwindcss/vite'; import { createServer } from 'vite'; import { createSSRApp, h } from 'vue'; import { renderToString } from 'vue/server-renderer'; import { createInertiaApp } from '@inertiajs/vue3'; const serve = process.argv.includes('--serve'); const server = await createServer({ configFile: false, cacheDir: 'node_modules/.vite/user-management-fixture', plugins: [vue(), ...(serve ? [tailwind()] : [])], resolve: { alias: { '@': fileURLToPath(new URL('../../resources/js', import.meta.url)), }, }, server: serve ? { host: '127.0.0.1', port: 4191, strictPort: true, hmr: false } : { middlewareMode: true, hmr: false, watch: null }, appType: 'custom', }); const admin = { id: 1, name: 'Alex Admin', email: 'alex@example.test', avatar: null, avatar_color: '#10B981', avatar_is_generated: true, email_verified_at: null, must_change_password_on_next_login: false, created_at: '2026-01-01T00:00:00Z', updated_at: '2026-01-01T00:00:00Z', }; const member = { ...admin, id: 2, name: 'Morgan Member', email: 'morgan@example.test', must_change_password_on_next_login: true, }; const shared = { name: 'KanbanGit', errors: {}, sidebarOpen: true, appearance: 'system', auth: { user: admin, permissions: { globalAdmin: true, projectCreate: true, canManageTeams: true, }, }, navigation: { project: null }, }; const pages = { index: { component: 'Index', url: '/admin/users', props: { ...shared, directPermissions: { 1: ['global:admin', 'project:create'], 2: [], }, permissionOptions: [ { value: 'global:admin', label: 'Global admin' }, { value: 'project:create', label: 'Create project' }, ], users: [admin, member], status: null, }, }, create: { component: 'Create', url: '/admin/users/create', props: shared, }, edit: { component: 'Edit', url: '/admin/users/2/edit', props: { ...shared, user: member }, }, }; function inertiaPage(page) { return { ...page, version: null, clearHistory: false, encryptHistory: false, }; } async function render(path, page) { const component = (await server.ssrLoadModule(path)).default; const { createLocalization } = await server.ssrLoadModule( '/resources/js/lib/localization.ts', ); const { createAppearance } = await server.ssrLoadModule( '/resources/js/composables/useAppearance.ts', ); return ( await createInertiaApp({ page: inertiaPage(page), resolve: () => component, render: renderToString, setup: ({ App, props, plugin }) => createSSRApp({ render: () => h(App, props) }) .use(plugin) .use(createLocalization()) .use(createAppearance()), }) ).body; } if (serve) { server.middlewares.use(async (request, response, next) => { if (!request.url.startsWith('/admin/users')) { return next(); } const pathname = new URL(request.url, 'http://localhost').pathname; const page = pathname.endsWith('/create') ? pages.create : pathname.endsWith('/edit') ? pages.edit : pages.index; const completePage = inertiaPage(page); response.setHeader('Vary', 'X-Inertia'); if (request.headers['x-inertia']) { response.setHeader('X-Inertia', 'true'); response.setHeader('Content-Type', 'application/json'); response.end(JSON.stringify(completePage)); return; } const escaped = JSON.stringify(completePage) .replaceAll('&', '&') .replaceAll('"', '"') .replaceAll('<', '<'); response.setHeader('Content-Type', 'text/html'); response.end( await server.transformIndexHtml( request.url, '
', ), ); }); await server.listen(); console.log('User management fixture ready.'); } else { try { const indexHtml = await render( '/resources/js/pages/admin/users/Index.vue', pages.index, ); assert.match(indexHtml, /Workspace administration/); assert.match(indexHtml, /User management/); assert.match(indexHtml, /Workspace users/); assert.match(indexHtml, /Global administrators/); assert.match(indexHtml, /Password changes pending/); assert.equal(indexHtml.match(/data-managed-user/g)?.length, 2); assert.match(indexHtml, /Alex Admin/); assert.match(indexHtml, /Morgan Member/); assert.match(indexHtml, /Manage access/); assert.match(indexHtml, /Edit account details for Morgan Member/); assert.match(indexHtml, /Password change required/); assert.match(indexHtml, /No direct global permissions/); const createHtml = await render( '/resources/js/pages/admin/users/Create.vue', pages.create, ); assert.match(createHtml, /Create user/); assert.match(createHtml, /Temporary password/); assert.match(createHtml, /Confirm password/); assert.match(createHtml, /Require a password change on next sign-in/); assert.match(createHtml, /data-test="managed-user-submit"/); assert.match(createHtml, /managed-user-password-confirmation-error/); const editHtml = await render( '/resources/js/pages/admin/users/Edit.vue', pages.edit, ); assert.match(editHtml, /Edit Morgan Member/); assert.match(editHtml, /morgan@example\.test/); assert.match(editHtml, /Leave both password fields empty/); assert.match(editHtml, /Review changes/); assert.match(editHtml, /value="Morgan Member"/); assert.match(editHtml, /value="morgan@example\.test"/); console.log('User management rendering checks passed.'); } finally { await server.close(); } }