fileStorage: implement delete action

This commit is contained in:
David Lechner
2022-03-10 01:02:18 -06:00
parent 03d12feb89
commit 41fc961661
4 changed files with 60 additions and 44 deletions
+2 -1
View File
@@ -16,6 +16,7 @@ import React, { forwardRef, useImperativeHandle, useMemo, useState } from 'react
import { useDispatch } from 'react-redux';
import {
fileStorageArchiveAllFiles,
fileStorageDeleteFile,
fileStorageExportFile,
} from '../fileStorage/actions';
import { useSelector } from '../reducers';
@@ -92,7 +93,7 @@ const FileActionButtonGroup = forwardRef<
icon="trash"
toolTipId={ExplorerStringId.TreeItemDeleteTooltip}
toolTipReplacements={{ fileName: props.fileName }}
onClick={() => alert('not implemented')}
onClick={() => dispatch(fileStorageDeleteFile(props.fileName))}
/>
</ButtonGroup>
);
+6
View File
@@ -78,6 +78,12 @@ export const fileStorageDidFailToWriteFile = createAction(
}),
);
/** Request to delete a file from storage. */
export const fileStorageDeleteFile = createAction((fileName: string) => ({
type: 'fileStorage.action.deleteFile',
fileName,
}));
/**
* Request to export (download) a file.
* @param fileName The name of the file.
+38 -43
View File
@@ -6,6 +6,7 @@ import { mock } from 'jest-mock-extended';
import { AsyncSaga } from '../../test';
import {
fileStorageArchiveAllFiles,
fileStorageDeleteFile,
fileStorageDidArchiveAllFiles,
fileStorageDidChangeItem,
fileStorageDidExportFile,
@@ -14,6 +15,7 @@ import {
fileStorageDidFailToReadFile,
fileStorageDidInitialize,
fileStorageDidReadFile,
fileStorageDidRemoveItem,
fileStorageDidWriteFile,
fileStorageExportFile,
fileStorageReadFile,
@@ -29,6 +31,29 @@ beforeEach(() => {
localStorage.clear();
});
/**
* helper function that writes test file to storage for later use in a test
* @param saga The saga.
* @returns The test file name and test file contents.
*/
async function setUpTestFile(saga: AsyncSaga): Promise<[string, string]> {
const testFileName = 'test.file';
const testFileContents = 'test file contents';
const action0 = await saga.take();
expect(action0).toEqual(fileStorageDidInitialize([]));
saga.put(fileStorageWriteFile(testFileName, testFileContents));
const action1 = await saga.take();
expect(action1).toEqual(fileStorageDidWriteFile(testFileName));
const action2 = await saga.take();
expect(action2).toEqual(fileStorageDidChangeItem(testFileName));
return [testFileName, testFileContents];
}
it('should migrate old program from local storage during initialization', async () => {
const oldProgramKey = 'program';
const oldProgramContents = '# test program';
@@ -94,30 +119,20 @@ it('should dispatch fail action if file does not exist', async () => {
await saga.end();
});
it('should delete files', async () => {
const saga = new AsyncSaga(fileStorage);
const [testFileName] = await setUpTestFile(saga);
saga.put(fileStorageDeleteFile(testFileName));
const action = await saga.take();
expect(action).toEqual(fileStorageDidRemoveItem(testFileName));
await saga.end();
});
describe('export', () => {
/**
* helper function that writes test file to storage for later use in a test
* @param saga The saga.
* @returns The test file name and test file contents.
*/
async function setUpTestFile(saga: AsyncSaga): Promise<[string, string]> {
const testFileName = 'test.file';
const testFileContents = 'test file contents';
const action0 = await saga.take();
expect(action0).toEqual(fileStorageDidInitialize([]));
saga.put(fileStorageWriteFile(testFileName, testFileContents));
const action1 = await saga.take();
expect(action1).toEqual(fileStorageDidWriteFile(testFileName));
const action2 = await saga.take();
expect(action2).toEqual(fileStorageDidChangeItem(testFileName));
return [testFileName, testFileContents];
}
it('should fail if file does not exist', async () => {
const testFileName = 'test.file';
@@ -236,26 +251,6 @@ describe('export', () => {
});
describe('archive', () => {
/**
* helper function that writes test file to storage for later use in a test
* @param saga The saga.
*/
async function setUpTestFile(saga: AsyncSaga): Promise<void> {
const testFileName = 'test.file';
const testFileContents = 'test file contents';
const action0 = await saga.take();
expect(action0).toEqual(fileStorageDidInitialize([]));
saga.put(fileStorageWriteFile(testFileName, testFileContents));
const action1 = await saga.take();
expect(action1).toEqual(fileStorageDidWriteFile(testFileName));
const action2 = await saga.take();
expect(action2).toEqual(fileStorageDidChangeItem(testFileName));
}
it('should archive file with web file system api', async () => {
const saga = new AsyncSaga(fileStorage);
+14
View File
@@ -12,6 +12,7 @@ import { EditorType } from '../editor/Editor';
import { ensureError, timestamp } from '../utils';
import {
fileStorageArchiveAllFiles,
fileStorageDeleteFile,
fileStorageDidArchiveAllFiles,
fileStorageDidChangeItem,
fileStorageDidExportFile,
@@ -146,6 +147,18 @@ function* handleExportFile(
yield* put(fileStorageDidExportFile(action.fileName));
}
/**
* Deletes a file from storage.
* @param files The localForage instance.
* @param action The action that triggered this saga.
*/
function* handleDeleteFile(
files: LocalForage,
action: ReturnType<typeof fileStorageDeleteFile>,
) {
yield* call(() => files.removeItem(action.fileName));
}
function* handleArchiveAllFiles(files: LocalForage): Generator {
try {
const zip = new JSZip();
@@ -242,6 +255,7 @@ function* initialize(): Generator {
yield* takeEvery(localForageChannel, handleFileStorageDidChange);
yield* takeEvery(fileStorageReadFile, handleReadFile, files);
yield* takeEvery(fileStorageWriteFile, handleWriteFile, files);
yield* takeEvery(fileStorageDeleteFile, handleDeleteFile, files);
yield* takeEvery(fileStorageExportFile, handleExportFile, files);
yield* takeEvery(fileStorageArchiveAllFiles, handleArchiveAllFiles, files);