Layout.test.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * Tests for the Layout component.
  3. */
  4. import { describe, it, expect, beforeEach } from 'vitest';
  5. import { screen, waitFor } from '@testing-library/react';
  6. import { render } from '../utils';
  7. import { Layout } from '../../components/Layout';
  8. import { http, HttpResponse } from 'msw';
  9. import { server } from '../mocks/server';
  10. describe('Layout', () => {
  11. beforeEach(() => {
  12. server.use(
  13. http.get('/api/v1/printers/', () => {
  14. return HttpResponse.json([
  15. { id: 1, name: 'X1 Carbon', model: 'X1C', enabled: true },
  16. ]);
  17. }),
  18. http.get('/api/v1/printers/:id/status', () => {
  19. return HttpResponse.json({
  20. connected: true,
  21. state: 'IDLE',
  22. });
  23. }),
  24. http.get('/api/v1/version', () => {
  25. return HttpResponse.json({ version: '0.1.6', build: 'test' });
  26. }),
  27. http.get('/api/v1/settings/', () => {
  28. return HttpResponse.json({
  29. check_updates: false,
  30. auto_archive: true,
  31. });
  32. }),
  33. http.get('/api/v1/external-links/', () => {
  34. return HttpResponse.json([]);
  35. }),
  36. http.get('/api/v1/smart-plugs/', () => {
  37. return HttpResponse.json([]);
  38. }),
  39. http.get('/api/v1/support/debug-logging', () => {
  40. return HttpResponse.json({ enabled: false });
  41. }),
  42. http.get('/api/v1/queue/', () => {
  43. return HttpResponse.json([]);
  44. }),
  45. http.get('/api/v1/pending-uploads/count', () => {
  46. return HttpResponse.json({ count: 0 });
  47. }),
  48. http.get('/api/v1/updates/check', () => {
  49. return HttpResponse.json({ update_available: false });
  50. })
  51. );
  52. });
  53. describe('rendering', () => {
  54. it('renders the sidebar', async () => {
  55. render(<Layout />);
  56. // Layout renders as a flex container with sidebar
  57. await waitFor(() => {
  58. const sidebar = document.querySelector('aside');
  59. expect(sidebar).toBeInTheDocument();
  60. });
  61. });
  62. it('renders navigation links', async () => {
  63. render(<Layout />);
  64. await waitFor(() => {
  65. // Navigation links should be present
  66. const links = document.querySelectorAll('a');
  67. expect(links.length).toBeGreaterThan(0);
  68. });
  69. });
  70. });
  71. describe('navigation', () => {
  72. it('has navigation items', async () => {
  73. render(<Layout />);
  74. await waitFor(() => {
  75. // Should have multiple navigation links
  76. const navLinks = document.querySelectorAll('a[href]');
  77. expect(navLinks.length).toBeGreaterThan(0);
  78. });
  79. });
  80. it('includes settings link', async () => {
  81. render(<Layout />);
  82. await waitFor(() => {
  83. // Settings link should exist (route /settings)
  84. const settingsLink = document.querySelector('a[href="/settings"]');
  85. expect(settingsLink).toBeInTheDocument();
  86. });
  87. });
  88. });
  89. describe('version display', () => {
  90. it('shows version info', async () => {
  91. render(<Layout />);
  92. await waitFor(() => {
  93. // Version info is displayed in sidebar
  94. expect(document.body).toBeInTheDocument();
  95. });
  96. });
  97. });
  98. describe('theme toggle', () => {
  99. it('has theme toggle button', async () => {
  100. render(<Layout />);
  101. await waitFor(() => {
  102. // Theme toggle should be present
  103. const buttons = document.querySelectorAll('button');
  104. expect(buttons.length).toBeGreaterThan(0);
  105. });
  106. });
  107. });
  108. });