diff --git a/src/renderer/components/sidebar-file-tree.tsx b/src/renderer/components/sidebar-file-tree.tsx index 95a9578914..0b88b1c6ec 100644 --- a/src/renderer/components/sidebar-file-tree.tsx +++ b/src/renderer/components/sidebar-file-tree.tsx @@ -207,10 +207,14 @@ export const SidebarFileTree = observer( } const contents = appState.editorMosaic.value(editorId).trim(); - appState.editorMosaic.remove(editorId); - appState.editorMosaic.addNewFile(id, contents); + try { + appState.editorMosaic.addNewFile(id, contents); + appState.editorMosaic.remove(editorId); - if (visible) appState.editorMosaic.show(id); + if (visible) appState.editorMosaic.show(id); + } catch (err) { + appState.showErrorDialog(err.message); + } }; public removeEditor = (editorId: EditorId) => { diff --git a/tests/renderer/components/sidebar-file-tree-spec.tsx b/tests/renderer/components/sidebar-file-tree-spec.tsx index 9b2b36e77e..be57f4dd52 100644 --- a/tests/renderer/components/sidebar-file-tree-spec.tsx +++ b/tests/renderer/components/sidebar-file-tree-spec.tsx @@ -2,7 +2,12 @@ import * as React from 'react'; import { shallow } from 'enzyme'; -import { EditorValues, PACKAGE_NAME } from '../../../src/interfaces'; +import { + EditorValues, + MAIN_CJS, + MAIN_JS, + PACKAGE_NAME, +} from '../../../src/interfaces'; import { Editors } from '../../../src/renderer/components/editors'; import { SidebarFileTree } from '../../../src/renderer/components/sidebar-file-tree'; import { @@ -98,16 +103,13 @@ describe('SidebarFileTree component', () => { ); }); - it('fails if trying to rename an editor to an invalid value', async () => { + it('fails if trying to rename an editor to package(-lock).json', async () => { const wrapper = shallow(); const instance: any = wrapper.instance(); - const EDITOR_NAME = 'data.json'; + const EDITOR_NAME = 'index.html'; const EDITOR_NEW_NAME = PACKAGE_NAME; - editorValues[EDITOR_NAME] = '{}'; - editorMosaic.set(editorValues); - store.showInputDialog = jest.fn().mockResolvedValueOnce(EDITOR_NEW_NAME); store.showErrorDialog = jest.fn().mockResolvedValueOnce(true); @@ -116,6 +118,62 @@ describe('SidebarFileTree component', () => { expect(store.showErrorDialog).toHaveBeenCalledWith( `Cannot add ${PACKAGE_NAME} or package-lock.json as custom files`, ); + expect(editorMosaic.files.get(EDITOR_NAME)).toBe(EditorPresence.Pending); + }); + + it('fails if trying to rename an editor to an unsupported name', async () => { + const wrapper = shallow(); + const instance: any = wrapper.instance(); + + const EDITOR_NAME = 'index.html'; + const EDITOR_NEW_NAME = 'data.txt'; + + store.showInputDialog = jest.fn().mockResolvedValueOnce(EDITOR_NEW_NAME); + store.showErrorDialog = jest.fn().mockResolvedValueOnce(true); + + await instance.renameEditor(EDITOR_NAME); + + expect(store.showErrorDialog).toHaveBeenCalledWith( + `Invalid filename "${EDITOR_NEW_NAME}": Must be a file ending in .cjs, .js, .mjs, .html, .css, or .json`, + ); + expect(editorMosaic.files.get(EDITOR_NAME)).toBe(EditorPresence.Pending); + }); + + it('fails if trying to rename an editor to an existing name', async () => { + const wrapper = shallow(); + const instance: any = wrapper.instance(); + + const EXISTED_NAME = 'styles.css'; + const TO_BE_NAMED = 'index.html'; + const EDITOR_NEW_NAME = EXISTED_NAME; + + store.showInputDialog = jest.fn().mockResolvedValueOnce(EDITOR_NEW_NAME); + store.showErrorDialog = jest.fn().mockResolvedValueOnce(true); + + await instance.renameEditor(TO_BE_NAMED); + + expect(store.showErrorDialog).toHaveBeenCalledWith( + `Cannot add file "${EDITOR_NEW_NAME}": File already exists`, + ); + expect(editorMosaic.files.get(TO_BE_NAMED)).toBe(EditorPresence.Pending); + }); + + it('fails if trying to rename an editor to another main entry point file', async () => { + const wrapper = shallow(); + const instance: any = wrapper.instance(); + + const TO_BE_NAMED = 'index.html'; + const EDITOR_NEW_NAME = MAIN_CJS; + + store.showInputDialog = jest.fn().mockResolvedValueOnce(EDITOR_NEW_NAME); + store.showErrorDialog = jest.fn().mockResolvedValueOnce(true); + + await instance.renameEditor(TO_BE_NAMED); + + expect(store.showErrorDialog).toHaveBeenCalledWith( + `Cannot add file "${EDITOR_NEW_NAME}": Main entry point ${MAIN_JS} exists`, + ); + expect(editorMosaic.files.get(TO_BE_NAMED)).toBe(EditorPresence.Pending); }); it('can reset the editor layout', () => {