mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 09:36:27 +00:00
Fixed deleting files that are not open in the editor.
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
- Fixed deleting files that are not open in the editor.
|
||||
|
||||
## [2.0.0-beta.3] - 2022-07-06
|
||||
|
||||
### Changed
|
||||
|
||||
+38
-21
@@ -14,6 +14,7 @@ import {
|
||||
editorDidFailToActivateFile,
|
||||
} from '../editor/actions';
|
||||
import { EditorError } from '../editor/error';
|
||||
import { UUID } from '../fileStorage';
|
||||
import {
|
||||
fileStorageCopyFile,
|
||||
fileStorageDeleteFile,
|
||||
@@ -471,31 +472,47 @@ describe('handleExplorerDeleteFile', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('accepted', () => {
|
||||
beforeEach(async () => {
|
||||
saga.put(deleteFileAlertDidAccept());
|
||||
describe.each([false, true])(
|
||||
'accepted, file is open: %o',
|
||||
(fileIsOpenInEditor: boolean) => {
|
||||
beforeEach(async () => {
|
||||
if (fileIsOpenInEditor) {
|
||||
const openFileUuids: readonly UUID[] = [uuid(0)];
|
||||
saga.updateState({ editor: { openFileUuids } });
|
||||
}
|
||||
|
||||
// should close the editor first
|
||||
await expect(saga.take()).resolves.toEqual(editorCloseFile(uuid(0)));
|
||||
saga.put(editorDidCloseFile(uuid(0)));
|
||||
saga.put(deleteFileAlertDidAccept());
|
||||
|
||||
// then delete the file
|
||||
await expect(saga.take()).resolves.toEqual(fileStorageDeleteFile(testFile));
|
||||
});
|
||||
if (fileIsOpenInEditor) {
|
||||
// should close the editor first
|
||||
await expect(saga.take()).resolves.toEqual(
|
||||
editorCloseFile(uuid(0)),
|
||||
);
|
||||
saga.put(editorDidCloseFile(uuid(0)));
|
||||
}
|
||||
|
||||
it('should propagate error', async () => {
|
||||
const testError = new Error('test error');
|
||||
saga.put(fileStorageDidFailToDeleteFile(testFile, testError));
|
||||
await expect(saga.take()).resolves.toEqual(
|
||||
explorerDidFailToDeleteFile(testFile, testError),
|
||||
);
|
||||
});
|
||||
// then delete the file
|
||||
await expect(saga.take()).resolves.toEqual(
|
||||
fileStorageDeleteFile(testFile),
|
||||
);
|
||||
});
|
||||
|
||||
it('should succeed', async () => {
|
||||
saga.put(fileStorageDidDeleteFile(testFile));
|
||||
await expect(saga.take()).resolves.toEqual(explorerDidDeleteFile(testFile));
|
||||
});
|
||||
});
|
||||
it('should propagate error', async () => {
|
||||
const testError = new Error('test error');
|
||||
saga.put(fileStorageDidFailToDeleteFile(testFile, testError));
|
||||
await expect(saga.take()).resolves.toEqual(
|
||||
explorerDidFailToDeleteFile(testFile, testError),
|
||||
);
|
||||
});
|
||||
|
||||
it('should succeed', async () => {
|
||||
saga.put(fileStorageDidDeleteFile(testFile));
|
||||
await expect(saga.take()).resolves.toEqual(
|
||||
explorerDidDeleteFile(testFile),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
afterEach(async () => {
|
||||
await saga.end();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { fileOpen, fileSave } from 'browser-fs-access';
|
||||
import JSZip from 'jszip';
|
||||
import { call, put, race, take, takeEvery } from 'typed-redux-saga/macro';
|
||||
import { call, put, race, select, take, takeEvery } from 'typed-redux-saga/macro';
|
||||
import { alertsShowAlert } from '../alerts/actions';
|
||||
import {
|
||||
editorActivateFile,
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
pythonFileMimeType,
|
||||
validateFileName,
|
||||
} from '../pybricksMicropython/lib';
|
||||
import { RootState } from '../reducers';
|
||||
import { defined, ensureError, timestamp } from '../utils';
|
||||
import {
|
||||
explorerArchiveAllFiles,
|
||||
@@ -405,9 +406,13 @@ function* handleExplorerDeleteFile(action: ReturnType<typeof explorerDeleteFile>
|
||||
|
||||
// at this point we know the user accepted
|
||||
|
||||
const openUuids = yield* select((s: RootState) => s.editor.openFileUuids);
|
||||
|
||||
// have to close editor before deleting, otherwise we get "in use" error
|
||||
yield* put(editorCloseFile(action.uuid));
|
||||
yield* take(editorDidCloseFile.when((a) => a.uuid === action.uuid));
|
||||
if (openUuids.includes(action.uuid)) {
|
||||
yield* put(editorCloseFile(action.uuid));
|
||||
yield* take(editorDidCloseFile.when((a) => a.uuid === action.uuid));
|
||||
}
|
||||
|
||||
yield* put(fileStorageDeleteFile(action.fileName));
|
||||
|
||||
|
||||
+2
-7
@@ -9,12 +9,7 @@ import userEvent from '@testing-library/user-event';
|
||||
import type { UserEvent } from '@testing-library/user-event/dist/types/setup';
|
||||
import React, { ReactElement } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import {
|
||||
AnyAction,
|
||||
DeepPartial,
|
||||
PreloadedState,
|
||||
legacy_createStore as createStore,
|
||||
} from 'redux';
|
||||
import { AnyAction, PreloadedState, legacy_createStore as createStore } from 'redux';
|
||||
import { END, MulticastChannel, Saga, Task, runSaga, stdChannel } from 'redux-saga';
|
||||
import { UUID } from '../src/fileStorage';
|
||||
import { RootState, rootReducer } from '../src/reducers';
|
||||
@@ -81,7 +76,7 @@ export class AsyncSaga {
|
||||
return Promise.resolve(next);
|
||||
}
|
||||
|
||||
public updateState(state: DeepPartial<RootState>): void {
|
||||
public updateState(state: PreloadedState<RootState>): void {
|
||||
for (const key of Object.keys(state) as Array<keyof RootState>) {
|
||||
// @ts-expect-error: writing to readonly for testing
|
||||
this.state[key] = { ...this.state[key], ...state[key] };
|
||||
|
||||
Reference in New Issue
Block a user