Add unit tests for 'download-file' command

Reviewed By: mweststrate

Differential Revision: D32926830

fbshipit-source-id: fbd4dcb910ffdcdc365f5f0b4c401423f0256824
This commit is contained in:
Andrey Goncharov
2021-12-10 06:34:37 -08:00
committed by Facebook GitHub Bot
parent 6aa0cef927
commit 9436c32ce9
5 changed files with 244 additions and 3 deletions

View File

@@ -0,0 +1,220 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import axios from 'axios';
import MemoryStream from 'memorystream';
import {dirSync} from 'tmp';
import * as uuid from 'uuid';
import {commandDownloadFileStartFactory} from '../DownloadFile';
describe('commands', () => {
describe('DownloadFile', () => {
let commandDownloadFileStart: ReturnType<
typeof commandDownloadFileStartFactory
>;
let emit: jest.Mock<any>;
beforeEach(() => {
emit = jest.fn();
commandDownloadFileStart = commandDownloadFileStartFactory(emit);
});
test('downloads file and reports the progress', async () => {
const fakeDownloadStream = new MemoryStream();
const fakeFileSize = 10;
const fakeHeaders = {
'content-length': fakeFileSize.toString(),
};
const fakeStatus = 200;
const fakeStatusText = 'Flipper rocks';
const requestSpy = jest
.spyOn(axios, 'request')
.mockImplementation(async () => ({
headers: fakeHeaders,
status: fakeStatus,
statusText: fakeStatusText,
data: fakeDownloadStream,
}));
const {name: tmpDirName} = dirSync({
unsafeCleanup: true,
});
const dest = `${tmpDirName}/flipperTest`;
expect(requestSpy).toBeCalledTimes(0);
const fakeDownloadURL = 'https://flipper.rocks';
const fakeUuid = 'flipper42';
jest.spyOn(uuid, 'v4').mockImplementation(() => fakeUuid);
const downloadFileDescriptor = await commandDownloadFileStart(
fakeDownloadURL,
dest,
{
overwrite: true,
},
);
expect(requestSpy).toBeCalledTimes(1);
// Expect first argument of the first fn call to amtch object
expect(requestSpy.mock.calls[0][0]).toMatchObject({
method: 'GET',
url: fakeDownloadURL,
});
expect(downloadFileDescriptor.headers).toBe(fakeHeaders);
expect(downloadFileDescriptor.status).toBe(fakeStatus);
expect(downloadFileDescriptor.statusText).toBe(fakeStatusText);
expect(downloadFileDescriptor.id).toBe(fakeUuid);
expect(emit).toBeCalledTimes(0);
await new Promise((resolve) => fakeDownloadStream.write('Luke', resolve));
expect(emit).toBeCalledTimes(1);
expect(emit).toBeCalledWith('download-file-update', {
id: fakeUuid,
downloaded: 4,
totalSize: fakeFileSize,
status: 'downloading',
});
await new Promise((resolve) => fakeDownloadStream.write('Obi', resolve));
expect(emit).toBeCalledTimes(2);
expect(emit).toBeCalledWith('download-file-update', {
id: fakeUuid,
downloaded: 7,
totalSize: fakeFileSize,
status: 'downloading',
});
const lastFileUpdateCalled = new Promise((resolve) =>
emit.mockImplementationOnce(resolve),
);
fakeDownloadStream.end();
await lastFileUpdateCalled;
expect(emit).toBeCalledTimes(3);
expect(emit).toBeCalledWith('download-file-update', {
id: fakeUuid,
downloaded: 7,
totalSize: fakeFileSize,
status: 'success',
});
});
test('rejects "complete" promise if download file readable stream errors', async () => {
const fakeDownloadStream = new MemoryStream();
const fakeFileSize = 10;
const fakeHeaders = {
'content-length': fakeFileSize.toString(),
};
const fakeStatus = 200;
const fakeStatusText = 'Flipper rocks';
jest.spyOn(axios, 'request').mockImplementation(async () => ({
headers: fakeHeaders,
status: fakeStatus,
statusText: fakeStatusText,
data: fakeDownloadStream,
}));
const {name: tmpDirName} = dirSync({
unsafeCleanup: true,
});
const dest = `${tmpDirName}/flipperTest`;
const fakeDownloadURL = 'https://flipper.rocks';
const fakeUuid = 'flipper42';
jest.spyOn(uuid, 'v4').mockImplementation(() => fakeUuid);
await commandDownloadFileStart(fakeDownloadURL, dest, {
overwrite: true,
});
const lastFileUpdateCalled = new Promise((resolve) =>
emit.mockImplementationOnce(resolve),
);
const fakeError = new Error('Ooops');
fakeDownloadStream.destroy(fakeError);
await lastFileUpdateCalled;
expect(emit).toBeCalledTimes(1);
expect(emit).toBeCalledWith('download-file-update', {
id: fakeUuid,
downloaded: 0,
totalSize: fakeFileSize,
status: 'error',
message: 'Ooops',
stack: expect.anything(),
});
});
test('rejects "complete" promise if writeable stream errors', async () => {
const fakeDownloadStream = new MemoryStream();
const fakeFileSize = 10;
const fakeHeaders = {
'content-length': fakeFileSize.toString(),
};
const fakeStatus = 200;
const fakeStatusText = 'Flipper rocks';
jest.spyOn(axios, 'request').mockImplementation(async () => ({
headers: fakeHeaders,
status: fakeStatus,
statusText: fakeStatusText,
data: fakeDownloadStream,
}));
const {name: tmpDirName, removeCallback: removeTmpDir} = dirSync({
unsafeCleanup: true,
});
const dest = `${tmpDirName}/flipperTest`;
const fakeDownloadURL = 'https://flipper.rocks';
const fakeUuid = 'flipper42';
jest.spyOn(uuid, 'v4').mockImplementation(() => fakeUuid);
await commandDownloadFileStart(fakeDownloadURL, dest, {
overwrite: true,
});
const lastFileUpdateCalled = new Promise<void>((resolve) =>
emit.mockImplementation(
(_event, {status}) => status === 'error' && resolve(),
),
);
// We remove the end file to cause an error
removeTmpDir();
fakeDownloadStream.write('Obi');
await lastFileUpdateCalled;
expect(emit).toBeCalledTimes(2);
expect(emit).toHaveBeenNthCalledWith(1, 'download-file-update', {
id: fakeUuid,
downloaded: 3,
totalSize: fakeFileSize,
status: 'downloading',
});
expect(emit).toHaveBeenNthCalledWith(2, 'download-file-update', {
id: fakeUuid,
downloaded: 3,
totalSize: fakeFileSize,
status: 'error',
message: expect.stringContaining('ENOENT'),
stack: expect.anything(),
});
});
});
});