import { describe, it, expect, vi, beforeEach } from 'vitest'; import { yarnSpinnerPlugin } from '../../src/plugins/esbuild'; import { resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); describe('yarnSpinnerPlugin (esbuild)', () => { // Fixtures are in tests/fixtures/, not tests/plugins/fixtures/ const projectPath = resolve(__dirname, '../fixtures/simple/.yarnproject'); it('should return an esbuild plugin with correct name', () => { const plugin = yarnSpinnerPlugin(); expect(plugin.name).toBe('yarn-spinner-loader'); }); it('should have a setup function', () => { const plugin = yarnSpinnerPlugin(); expect(plugin.setup).toBeDefined(); expect(typeof plugin.setup).toBe('function'); }); it('should register onLoad handler for .yarnproject files', () => { const plugin = yarnSpinnerPlugin(); const mockBuild = { onLoad: vi.fn((_options, callback) => { // Store the callback for testing (mockBuild as any)._onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); expect(mockBuild.onLoad).toHaveBeenCalledWith( { filter: /\.yarnproject$/ }, expect.any(Function), ); }); it('should load .yarnproject files and return correct content', async () => { const plugin = yarnSpinnerPlugin(); let onLoadCallback: Function | undefined; const mockBuild = { onLoad: vi.fn((_options, callback) => { onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); // Ensure callback was registered expect(onLoadCallback).toBeDefined(); // Simulate esbuild calling the callback const args = { path: projectPath }; const result = await (onLoadCallback as any)(args); expect(result).toBeDefined(); expect(result.contents).toContain('export default'); expect(result.contents).toContain('project'); expect(result.contents).toContain('yarnFiles'); expect(result.loader).toBe('js'); }); it('should handle errors by returning error object', async () => { const plugin = yarnSpinnerPlugin(); let onLoadCallback: Function | undefined; const mockBuild = { onLoad: vi.fn((_options, callback) => { onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); // Simulate esbuild calling the callback with non-existent file const args = { path: 'nonexistent/.yarnproject' }; const result = await (onLoadCallback as any)(args); expect(result.errors).toBeDefined(); expect(result.errors.length).toBeGreaterThan(0); expect(result.errors[0].text).toBeDefined(); expect(typeof result.errors[0].text).toBe('string'); }); it('should accept loadOptions and pass them to loadYarnProject', async () => { const plugin = yarnSpinnerPlugin({ loadOptions: { baseDir: resolve(__dirname, 'fixtures/simple'), }, }); let onLoadCallback: Function | undefined; const mockBuild = { onLoad: vi.fn((_options, callback) => { onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); const args = { path: projectPath }; const result = await (onLoadCallback as any)(args); expect(result.contents).toContain('export default'); expect(result.loader).toBe('js'); }); it('should correctly serialize the result as JSON with proper formatting', async () => { const plugin = yarnSpinnerPlugin(); let onLoadCallback: Function | undefined; const mockBuild = { onLoad: vi.fn((_options, callback) => { onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); const args = { path: projectPath }; const result = await (onLoadCallback as any)(args); // The contents should be properly formatted JavaScript code expect(result.contents).toMatch(/export default {[\s\S]*};/); expect(result.loader).toBe('js'); }); it('should handle non-Error objects in error handling', async () => { const plugin = yarnSpinnerPlugin(); let onLoadCallback: Function | undefined; const mockBuild = { onLoad: vi.fn((_options, callback) => { onLoadCallback = callback; }), }; plugin.setup(mockBuild as any); const args = { path: 'nonexistent/.yarnproject' }; const result = await (onLoadCallback as any)(args); expect(result.errors[0].text).toBeDefined(); expect(typeof result.errors[0].text).toBe('string'); }); });