|
1 | 1 | import fs from 'node:fs'; |
2 | 2 | import { PassThrough } from 'node:stream'; |
| 3 | +import * as ensureFolderExistsModule from '../../../../apps/shared/fs/ensure-folder-exists'; |
3 | 4 | import { streamFileToDisk } from './stream-file-to-disk'; |
4 | | -import { deepMocked } from '../../../../../tests/vitest/utils.helper'; |
| 5 | +import { call, calls, partialSpyOn } from '../../../../../tests/vitest/utils.helper'; |
5 | 6 |
|
6 | | -vi.mock(import('node:fs')); |
| 7 | +describe('stream-file-to-disk', () => { |
| 8 | + const createWriteStreamMock = partialSpyOn(fs, 'createWriteStream'); |
| 9 | + const ensureFolderExistsMock = partialSpyOn(ensureFolderExistsModule, 'ensureFolderExists'); |
7 | 10 |
|
8 | | -const fsMock = deepMocked(fs); |
9 | | - |
10 | | -describe('streamFileToDisk', () => { |
11 | 11 | let fakeWriteStream: PassThrough & { bytesWritten: number }; |
12 | 12 |
|
13 | 13 | beforeEach(() => { |
14 | 14 | fakeWriteStream = Object.assign(new PassThrough(), { bytesWritten: 0 }); |
15 | | - fsMock.createWriteStream.mockReturnValue(fakeWriteStream as any); |
| 15 | + createWriteStreamMock.mockReturnValue(fakeWriteStream as unknown as fs.WriteStream); |
16 | 16 | }); |
17 | 17 |
|
18 | | - it('should create a write stream at the given file path', () => { |
| 18 | + it('should ensure the destination folder exists before creating the stream', () => { |
| 19 | + // Given |
19 | 20 | const readable = new PassThrough(); |
20 | 21 |
|
21 | | - streamFileToDisk(readable, '/tmp/file', vi.fn()); |
| 22 | + // When |
| 23 | + streamFileToDisk(readable, '/home/dev/.config/internxt/downloaded/file-id', vi.fn()); |
22 | 24 |
|
23 | | - expect(fsMock.createWriteStream).toHaveBeenCalledWith('/tmp/file'); |
| 25 | + // Then |
| 26 | + call(ensureFolderExistsMock).toBe('/home/dev/.config/internxt/downloaded'); |
| 27 | + call(createWriteStreamMock).toBe('/home/dev/.config/internxt/downloaded/file-id'); |
24 | 28 | }); |
25 | 29 |
|
26 | 30 | it('should pipe the readable into the write stream', () => { |
| 31 | + // Given |
27 | 32 | const readable = new PassThrough(); |
28 | | - const pipeSpy = vi.spyOn(readable, 'pipe'); |
| 33 | + const pipeSpy = partialSpyOn(readable, 'pipe', false); |
29 | 34 |
|
| 35 | + // When |
30 | 36 | streamFileToDisk(readable, '/tmp/file', vi.fn()); |
31 | 37 |
|
32 | | - expect(pipeSpy).toHaveBeenCalledWith(fakeWriteStream); |
| 38 | + // Then |
| 39 | + call(pipeSpy).toBe(fakeWriteStream); |
33 | 40 | }); |
34 | 41 |
|
35 | 42 | it('should call onProgress with bytesWritten when data is received', () => { |
| 43 | + // Given |
36 | 44 | const readable = new PassThrough(); |
37 | 45 | const onProgress = vi.fn(); |
38 | 46 | fakeWriteStream.bytesWritten = 100; |
39 | 47 |
|
| 48 | + // When |
40 | 49 | streamFileToDisk(readable, '/tmp/file', onProgress); |
41 | 50 | readable.emit('data', Buffer.alloc(100)); |
42 | 51 |
|
43 | | - expect(onProgress).toHaveBeenCalledWith(100); |
| 52 | + // Then |
| 53 | + call(onProgress).toBe(100); |
44 | 54 | }); |
45 | 55 |
|
46 | 56 | it('should call onProgress with bytesWritten on drain', () => { |
| 57 | + // Given |
47 | 58 | const readable = new PassThrough(); |
48 | 59 | const onProgress = vi.fn(); |
49 | 60 | fakeWriteStream.bytesWritten = 200; |
50 | 61 |
|
| 62 | + // When |
51 | 63 | streamFileToDisk(readable, '/tmp/file', onProgress); |
52 | 64 | fakeWriteStream.emit('drain'); |
53 | 65 |
|
54 | | - expect(onProgress).toHaveBeenCalledWith(200); |
| 66 | + // Then |
| 67 | + call(onProgress).toBe(200); |
55 | 68 | }); |
56 | 69 |
|
57 | 70 | it('should return the write stream', () => { |
| 71 | + // Given |
58 | 72 | const readable = new PassThrough(); |
59 | 73 |
|
| 74 | + // When |
60 | 75 | const result = streamFileToDisk(readable, '/tmp/file', vi.fn()); |
61 | 76 |
|
| 77 | + // Then |
62 | 78 | expect(result.writeStream).toBe(fakeWriteStream); |
63 | 79 | }); |
64 | 80 |
|
65 | 81 | it('should return getBytesWritten that tracks progress', () => { |
| 82 | + // Given |
66 | 83 | const readable = new PassThrough(); |
67 | 84 |
|
| 85 | + // When |
68 | 86 | const result = streamFileToDisk(readable, '/tmp/file', vi.fn()); |
69 | 87 |
|
| 88 | + // Then |
70 | 89 | expect(result.getBytesWritten()).toBe(0); |
71 | 90 |
|
| 91 | + // Given |
72 | 92 | fakeWriteStream.bytesWritten = 500; |
| 93 | + |
| 94 | + // When |
73 | 95 | readable.emit('data', Buffer.alloc(500)); |
74 | 96 |
|
| 97 | + // Then |
75 | 98 | expect(result.getBytesWritten()).toBe(500); |
76 | 99 | }); |
| 100 | + |
| 101 | + it('should create the write stream once', () => { |
| 102 | + // Given |
| 103 | + const readable = new PassThrough(); |
| 104 | + |
| 105 | + // When |
| 106 | + streamFileToDisk(readable, '/tmp/file', vi.fn()); |
| 107 | + |
| 108 | + // Then |
| 109 | + calls(createWriteStreamMock).toHaveLength(1); |
| 110 | + }); |
77 | 111 | }); |
0 commit comments