|
| 1 | +import { describe, it, expect } from 'vitest'; |
| 2 | +import path from 'path'; |
| 3 | +import { pathToFileURL } from 'url'; |
| 4 | + |
| 5 | +// Reproduce the path logic from vite-plugin.ts in a testable helper |
| 6 | +function computeClientImport(options: { projectRoot: string; clientFsPath: string }) { |
| 7 | + const { projectRoot, clientFsPath } = options; |
| 8 | + let clientImport = clientFsPath; |
| 9 | + try { |
| 10 | + const rel = path.relative(projectRoot, clientFsPath); |
| 11 | + const relPosix = rel.replace(/\\/g, '/'); |
| 12 | + |
| 13 | + if (path.isAbsolute(rel)) { |
| 14 | + clientImport = pathToFileURL(clientFsPath).toString(); |
| 15 | + } else { |
| 16 | + clientImport = (relPosix.startsWith('.') ? relPosix : `/${relPosix}`).replace(/\/+/g, '/'); |
| 17 | + } |
| 18 | + } catch { |
| 19 | + clientImport = clientFsPath.replace(/\\/g, '/'); |
| 20 | + } |
| 21 | + return clientImport; |
| 22 | +} |
| 23 | + |
| 24 | +describe('ns-hmr-client vite plugin path handling', () => { |
| 25 | + it('keeps a clean project-relative POSIX path on POSIX-like roots', () => { |
| 26 | + const projectRoot = '/Users/test/app'; |
| 27 | + const clientFsPath = '/Users/test/app/node_modules/@nativescript/vite/hmr/client/index.js'; |
| 28 | + |
| 29 | + const result = computeClientImport({ projectRoot, clientFsPath }); |
| 30 | + |
| 31 | + expect(result).toBe('/node_modules/@nativescript/vite/hmr/client/index.js'); |
| 32 | + }); |
| 33 | + |
| 34 | + it('falls back to file URL when relative becomes absolute (Windows-like different drive)', () => { |
| 35 | + // Simulate a scenario where projectRoot and clientFsPath are on different drives. |
| 36 | + // On real Windows, path.relative('C:/proj', 'D:/lib/file.js') is an absolute path |
| 37 | + // starting with the target drive (e.g. 'D:/lib/file.js'). |
| 38 | + const projectRoot = 'C:/project/root'; |
| 39 | + const clientFsPath = 'D:/ns-vite-demo/node_modules/@nativescript/vite/hmr/client/index.js'; |
| 40 | + |
| 41 | + const result = computeClientImport({ projectRoot, clientFsPath }); |
| 42 | + |
| 43 | + // On non-Windows hosts, Node's path.relative may not simulate the |
| 44 | + // cross-drive behavior. The important contract is: when the computed |
| 45 | + // relative path is absolute, we do NOT generate an import like '/D:/...' |
| 46 | + // that would later resolve to 'D:\\D:\\...'. In that case we use a |
| 47 | + // file URL; otherwise we leave the relative specifier alone. |
| 48 | + if (path.sep === '\\') { |
| 49 | + // Windows: expect file URL behavior |
| 50 | + expect(result.startsWith('file://')).toBe(true); |
| 51 | + } |
| 52 | + expect(result.includes('nativescript/vite/hmr/client/index.js')).toBe(true); |
| 53 | + }); |
| 54 | + |
| 55 | + it('handles Windows-style same-drive paths as project-relative POSIX', () => { |
| 56 | + const projectRoot = 'D:/ns-vite-demo'; |
| 57 | + const clientFsPath = 'D:/ns-vite-demo/node_modules/@nativescript/vite/hmr/client/index.js'; |
| 58 | + |
| 59 | + const result = computeClientImport({ projectRoot, clientFsPath }); |
| 60 | + |
| 61 | + // When on the same drive, relative path should be node_modules/... and we normalize to POSIX. |
| 62 | + expect(result).toBe('/node_modules/@nativescript/vite/hmr/client/index.js'); |
| 63 | + }); |
| 64 | +}); |
0 commit comments