slicer.test.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * Tests for the slicer utility functions.
  3. */
  4. import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
  5. import { openInSlicer, detectPlatform, buildDownloadUrl } from '../../utils/slicer';
  6. describe('slicer utility', () => {
  7. let clickSpy: ReturnType<typeof vi.fn>;
  8. let appendSpy: ReturnType<typeof vi.fn>;
  9. let removeSpy: ReturnType<typeof vi.fn>;
  10. let createdLink: HTMLAnchorElement;
  11. beforeEach(() => {
  12. clickSpy = vi.fn();
  13. appendSpy = vi.spyOn(document.body, 'appendChild').mockImplementation((node) => {
  14. createdLink = node as HTMLAnchorElement;
  15. return node;
  16. });
  17. removeSpy = vi.spyOn(document.body, 'removeChild').mockImplementation((node) => node);
  18. // Mock click on created elements
  19. vi.spyOn(HTMLAnchorElement.prototype, 'click').mockImplementation(clickSpy);
  20. });
  21. afterEach(() => {
  22. vi.restoreAllMocks();
  23. });
  24. describe('detectPlatform', () => {
  25. it('detects Windows', () => {
  26. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Windows NT 10.0; Win64; x64)');
  27. expect(detectPlatform()).toBe('windows');
  28. });
  29. it('detects macOS', () => {
  30. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)');
  31. expect(detectPlatform()).toBe('macos');
  32. });
  33. it('detects Linux', () => {
  34. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (X11; Linux x86_64)');
  35. expect(detectPlatform()).toBe('linux');
  36. });
  37. });
  38. describe('openInSlicer', () => {
  39. it('uses bambustudio:// protocol on Windows for bambu_studio', () => {
  40. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Windows NT 10.0)');
  41. openInSlicer('http://localhost:8000/file.3mf', 'bambu_studio');
  42. expect(appendSpy).toHaveBeenCalled();
  43. expect(createdLink.href).toContain('bambustudio://');
  44. expect(createdLink.href).toContain(encodeURIComponent('http://localhost:8000/file.3mf'));
  45. expect(clickSpy).toHaveBeenCalled();
  46. expect(removeSpy).toHaveBeenCalled();
  47. });
  48. it('uses bambustudioopen:// protocol on macOS for bambu_studio', () => {
  49. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
  50. openInSlicer('http://localhost:8000/file.3mf', 'bambu_studio');
  51. expect(createdLink.href).toContain('bambustudioopen://');
  52. });
  53. it('uses bambustudioopen:// protocol on Linux for bambu_studio', () => {
  54. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (X11; Linux x86_64)');
  55. openInSlicer('http://localhost:8000/file.3mf', 'bambu_studio');
  56. expect(createdLink.href).toContain('bambustudioopen://');
  57. });
  58. it('uses orcaslicer:// protocol for orcaslicer on all platforms', () => {
  59. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
  60. openInSlicer('http://localhost:8000/file.3mf', 'orcaslicer');
  61. expect(createdLink.href).toContain('orcaslicer://');
  62. expect(createdLink.href).toContain('open?file=');
  63. });
  64. it('does not encode the file URL for orcaslicer', () => {
  65. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Windows NT 10.0)');
  66. const url = 'http://localhost:8000/api/v1/archives/1/file/My Model.3mf';
  67. openInSlicer(url, 'orcaslicer');
  68. // The href should contain the raw URL (browser may normalize it but it should not be double-encoded)
  69. expect(createdLink.href).toContain('orcaslicer://open?file=');
  70. // Should NOT contain %253A (double-encoded colon)
  71. expect(createdLink.href).not.toContain('%253A');
  72. });
  73. it('defaults to bambu_studio when no slicer specified', () => {
  74. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Windows NT 10.0)');
  75. openInSlicer('http://localhost:8000/file.3mf');
  76. expect(createdLink.href).toContain('bambustudio://');
  77. });
  78. it('creates and removes a temporary link element', () => {
  79. vi.spyOn(navigator, 'userAgent', 'get').mockReturnValue('Mozilla/5.0 (Windows NT 10.0)');
  80. openInSlicer('http://localhost:8000/file.3mf', 'bambu_studio');
  81. expect(appendSpy).toHaveBeenCalledOnce();
  82. expect(clickSpy).toHaveBeenCalledOnce();
  83. expect(removeSpy).toHaveBeenCalledOnce();
  84. });
  85. });
  86. describe('buildDownloadUrl', () => {
  87. it('prepends window.location.origin', () => {
  88. const result = buildDownloadUrl('/api/v1/archives/1/file/test.3mf');
  89. expect(result).toBe(`${window.location.origin}/api/v1/archives/1/file/test.3mf`);
  90. });
  91. });
  92. });