From b2a6952cc018c14c1729aeaabe470929355b5009 Mon Sep 17 00:00:00 2001
From: Dan Halson <danhalson@users.noreply.github.com>
Date: Tue, 30 May 2023 15:50:38 +0100
Subject: [PATCH] Add eslintrc (#502)

closes #510

Adds basic eslintrc using prettier
Adds editorconfig
---
 .devcontainer/devcontainer.json               |  14 +-
 .editorconfig                                 |  18 +
 .eslintrc.json                                |  47 +
 CHANGELOG.md                                  |   2 +
 package.json                                  |  13 +-
 src/App.test.js                               | 162 +--
 src/Icons.js                                  |   4 +-
 src/app/ComponentStore.js                     |   6 +-
 src/app/store.js                              |  21 +-
 src/components/AppRoutes.js                   |  72 +-
 .../AstroPiControls/AstroPiControls.js        |  71 +-
 .../AstroPiControls/AstroPiControls.test.js   |  87 +-
 .../AstroPiModel/AstroPiControls/Input.js     |  34 +-
 .../AstroPiControls/Input.test.js             |  34 +-
 .../AstroPiControls/MotionInput.js            |  70 +-
 .../AstroPiControls/MotionInput.test.js       | 186 ++--
 .../AstroPiControls/SliderInput.js            |  43 +-
 .../AstroPiControls/SliderInput.test.js       |  39 +-
 .../AstroPiModel/AstroPiControls/Stopwatch.js |  82 +-
 .../AstroPiControls/Stopwatch.test.js         |  34 +-
 src/components/AstroPiModel/AstroPiModel.js   | 114 ++-
 .../AstroPiModel/AstroPiModel.test.js         |  61 +-
 .../AstroPiModel/DefaultMZCriteria.js         |   4 +-
 src/components/AstroPiModel/FlightCase.js     |  76 +-
 .../AstroPiModel/FlightCase.test.js           |   8 +-
 src/components/AstroPiModel/Lighting.js       |  53 +-
 src/components/AstroPiModel/Lighting.test.js  |   6 +-
 .../OrientationPanel/OrientationPanel.js      |  36 +-
 .../OrientationPanel/OrientationPanel.test.js |  21 +-
 .../OrientationPanel/OrientationReading.js    |  18 +-
 .../OrientationReading.test.js                |  14 +-
 .../OrientationResetButton.js                 |  19 +-
 .../OrientationResetButton.test.js            |  16 +-
 src/components/AstroPiModel/Simulator.js      |  74 +-
 src/components/AstroPiModel/Simulator.test.js |  36 +-
 src/components/BetaBanner/BetaBanner.js       |  67 +-
 src/components/BetaBanner/BetaBanner.test.js  |  57 +-
 src/components/Callback.js                    |  24 +-
 .../Editor/DraggableTabs/DraggableTab.js      |  62 +-
 .../Editor/DraggableTabs/DraggableTab.test.js |  88 +-
 .../Editor/DraggableTabs/DroppableTabList.js  |  30 +-
 .../DraggableTabs/DroppableTabList.test.js    |  14 +-
 src/components/Editor/Editor.js               |  25 +-
 .../Editor/EditorInput/EditorInput.js         | 179 ++--
 .../Editor/EditorInput/EditorInput.test.js    | 143 +--
 .../Editor/EditorPanel/EditorPanel.js         |  89 +-
 .../Editor/EditorPanel/EditorPanel.test.js    |  63 +-
 src/components/Editor/EditorSlice.js          |  58 +-
 src/components/Editor/EditorSlice.test.js     | 928 ++++++++++--------
 .../Editor/ErrorMessage/ErrorMessage.js       |  12 +-
 .../Editor/ErrorMessage/ErrorMessage.test.js  |  49 +-
 .../Editor/ErrorMessage/NameErrorMessage.js   |   8 +-
 .../FontSizeSelector/FontSizeSelector.js      |  71 +-
 .../FontSizeSelector/FontSizeSelector.test.js |  58 +-
 .../Editor/Hooks/useEmbeddedMode.js           |   6 +-
 src/components/Editor/Hooks/useProject.js     |   4 +-
 .../Editor/Hooks/useProject.test.js           |   6 +-
 .../Editor/Hooks/useRequiresUser.js           |  13 +-
 .../ImageUploadButton/ImageUploadButton.js    | 158 +--
 .../ImageUploadButton.test.js                 |  58 +-
 .../NewComponentButton/NewComponentButton.js  |  44 +-
 .../NewComponentButton.test.js                |  50 +-
 .../NewInputPanelButton.js                    |  18 +-
 src/components/Editor/Output/Output.js        |  14 +-
 src/components/Editor/Output/Output.test.js   |  34 +-
 src/components/Editor/Project/Project.js      | 213 ++--
 src/components/Editor/Project/Project.test.js | 739 ++++++++------
 .../ProjectComponentLoader.test.js            |  77 +-
 .../Editor/Runners/HtmlRunner/HtmlRunner.js   |  18 +-
 .../Runners/HtmlRunner/HtmlRunner.test.js     |  18 +-
 .../Runners/PythonRunner/OutputViewToggle.js  |  56 +-
 .../PythonRunner/OutputViewToggle.test.js     | 296 +++---
 .../Runners/PythonRunner/PythonRunner.js      | 443 +++++----
 .../Runners/PythonRunner/PythonRunner.test.js | 832 +++++++++-------
 .../Runners/PythonRunner/VisualOutputPane.js  |  82 +-
 .../PythonRunner/VisualOutputPane.test.js     | 115 ++-
 .../Editor/Runners/RunnerFactory.js           |  17 +-
 src/components/Editor/editorDarkTheme.js      |  79 +-
 src/components/Editor/editorLightTheme.js     |  47 +-
 .../EmbeddedControls/EmbeddedControls.js      |  16 +-
 .../EmbeddedViewer/EmbeddedViewer.test.js     |  31 +-
 src/components/ExternalFiles/ExternalFiles.js |  29 +-
 .../ExternalFiles/ExternalFiles.test.js       |  46 +-
 src/components/Footer/Footer.js               |  44 +-
 src/components/Footer/Footer.test.js          |  52 +-
 src/components/GlobalNav/GlobalNav.js         |  33 +-
 src/components/GlobalNav/GlobalNav.test.js    |  76 +-
 src/components/Header/Autosave.js             |  57 +-
 src/components/Header/DownloadButton.js       |  50 +-
 src/components/Header/DownloadButton.test.js  | 177 ++--
 src/components/Header/Header.js               | 146 +--
 src/components/Header/Header.test.js          | 339 ++++---
 src/components/Header/ProjectName.js          |  91 +-
 src/components/Header/ProjectName.test.js     | 154 +--
 .../LocaleLayout/LocaleLayout.test.js         |   6 +-
 src/components/Login/LoginButton.js           |  32 +-
 src/components/Login/LoginButton.test.js      | 188 ++--
 src/components/Login/LoginMenu.js             |  43 +-
 src/components/Login/LoginMenu.test.js        | 113 ++-
 src/components/Login/LogoutButton.js          |  32 +-
 src/components/Login/LogoutButton.test.js     |  60 +-
 .../Menus/ContextMenu/ContextMenu.js          |  75 +-
 .../Menus/ContextMenu/ContextMenu.test.js     |  67 +-
 src/components/Menus/Dropdown/Dropdown.js     |  50 +-
 .../Menus/Dropdown/Dropdown.test.js           |  57 +-
 src/components/Menus/FileMenu/FileMenu.js     |  42 +-
 .../Menus/FileMenu/FileMenu.test.js           |  74 +-
 .../ProjectActionsMenu/ProjectActionsMenu.js  |  47 +-
 .../ProjectActionsMenu.test.js                |  66 +-
 .../Menus/SettingsMenu/SettingsMenu.js        |  25 +-
 .../Menus/SettingsMenu/SettingsMenu.test.js   |  12 +-
 .../Menus/SideMenu/FilePane/FilePane.js       |  29 +-
 .../Menus/SideMenu/FilePane/FilePane.test.js  |  84 +-
 .../Menus/SideMenu/FilePane/FilesList.js      |  55 +-
 .../Menus/SideMenu/FilePane/FilesList.test.js | 223 +++--
 .../FilePane/ProjectImages/ProjectImages.js   |  34 +-
 .../ProjectImages/ProjectImages.test.js       |  52 +-
 src/components/Menus/SideMenu/MenuSideBar.js  |  66 +-
 .../Menus/SideMenu/MenuSideBar.test.js        |  24 +-
 .../Menus/SideMenu/MenuSideBarOption.js       |  30 +-
 .../Menus/SideMenu/MenuSidebarOption.test.js  |  24 +-
 src/components/Menus/SideMenu/SideMenu.js     |  79 +-
 .../Menus/SideMenu/SideMenu.test.js           |  44 +-
 .../Modals/AccessDeniedNoAuthModal.js         |  45 +-
 .../Modals/AccessDeniedNoAuthModal.test.js    |  66 +-
 .../Modals/AccessDeniedWithAuthModal.js       |  51 +-
 .../Modals/AccessDeniedWithAuthModal.test.js  |  84 +-
 src/components/Modals/BetaModal.js            |  26 +-
 src/components/Modals/BetaModal.test.js       |  54 +-
 src/components/Modals/DeleteProjectModal.js   |  46 +-
 .../Modals/DeleteProjectModal.test.js         |  99 +-
 src/components/Modals/ErrorModal.test.js      |  14 +-
 src/components/Modals/GeneralModal.js         |  79 +-
 src/components/Modals/GeneralModal.test.js    |  50 +-
 src/components/Modals/InputModal.js           |  34 +-
 src/components/Modals/InputModal.test.js      |  48 +-
 src/components/Modals/LoginToSaveModal.js     |  43 +-
 .../Modals/LoginToSaveModal.test.js           |  56 +-
 src/components/Modals/NewFileModal.js         |  75 +-
 src/components/Modals/NewFileModal.test.js    |  99 +-
 src/components/Modals/NotFoundModal.js        |  45 +-
 src/components/Modals/NotFoundModal.test.js   | 116 ++-
 src/components/Modals/RenameFile.js           |  77 +-
 src/components/Modals/RenameFile.test.js      | 112 ++-
 src/components/Modals/RenameProjectModal.js   |  51 +-
 .../Modals/RenameProjectModal.test.js         | 155 +--
 src/components/ProjectIndex/ProjectIndex.js   |   6 +-
 .../ProjectIndex/ProjectIndex.test.js         |   4 +-
 .../ProjectIndexPagination.test.js            |  24 +-
 .../ProjectIndexHeader/ProjectIndexHeader.js  |  25 +-
 .../ProjectListItem/ProjectListItem.js        |   2 +-
 .../ProjectListItem/ProjectListItem.test.js   |  56 +-
 .../ProjectListTable/ProjectListTable.js      |  36 +-
 .../ProjectListTable/ProjectListTable.test.js |  68 +-
 src/components/ProjectViewer/ProjectViewer.js |  25 +-
 src/components/RunButton/RunBar.js            |  10 +-
 src/components/RunButton/RunBar.test.js       |  28 +-
 src/components/RunButton/RunButton.js         |  21 +-
 src/components/RunButton/RunButton.test.js    |  22 +-
 src/components/RunButton/RunnerControls.js    |  35 +-
 .../RunButton/RunnerControls.test.js          |  58 +-
 src/components/RunButton/StopButton.js        |  39 +-
 src/components/RunButton/StopButton.test.js   |  66 +-
 src/components/SilentRenew.js                 |  12 +-
 src/components/ThemeToggle/ThemeToggle.js     |  63 +-
 .../ThemeToggle/ThemeToggle.test.js           | 108 +-
 .../Project/WebComponentProject.js            |  91 +-
 .../WebComponentLoader/WebComponentLoader.js  |  28 +-
 .../WebComponent/WebComponentSlice.js         |  18 +-
 src/hooks/useUserFont.js                      |  12 +-
 src/i18n.js                                   |  13 +-
 src/index.js                                  |  61 +-
 src/reportWebVitals.js                        |   4 +-
 src/sentry.js                                 |  17 +-
 src/settings.js                               |  12 +-
 src/utils/Geometry.js                         | 131 ++-
 src/utils/Notifications.js                    |  59 +-
 src/utils/Notifications.test.js               |  61 +-
 src/utils/Orientation.js                      |  63 +-
 src/utils/ResizableWithHandle.js              |  65 +-
 src/utils/ResizableWithHandle.test.js         |  36 +-
 src/utils/ToastCloseButton.js                 |  11 +-
 src/utils/ToastCloseButton.test.js            |  22 +-
 src/utils/apiCallHandler.js                   |  97 +-
 src/utils/apiCallHandler.test.js              | 220 +++--
 src/utils/apolloCache.js                      |   4 +-
 src/utils/componentNameValidation.js          |  70 +-
 src/utils/containerQueries.js                 |   4 +-
 src/utils/defaultProjects.js                  |  37 +-
 src/utils/login.js                            |  27 +-
 src/utils/projectHelpers.js                   |   8 +-
 src/utils/projectHelpers.test.js              | 106 +-
 src/web-component.js                          |  34 +-
 yarn.lock                                     |  29 +
 194 files changed, 7910 insertions(+), 5794 deletions(-)
 create mode 100644 .editorconfig
 create mode 100644 .eslintrc.json

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f863e6244..69cf95aa5 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -64,10 +64,20 @@
         "github.remotehub",
         "circleci.circleci",
         "stylelint.vscode-stylelint",
-        "Orta.vscode-jest"
+        "Orta.vscode-jest",
+        "christian-kohler.path-intellisense",
+        "esbenp.prettier-vscode",
+        "avraammavridis.vsc-react-documentation",
+        "ofhumanbondage.react-proptypes-intellisense",
+        "syler.sass-indented",
+        "codezombiech.gitignore"
       ],
       "settings": {
-        "terminal.integrated.defaultProfile.linux": "zsh"
+        "terminal.integrated.defaultProfile.linux": "zsh",
+        "jest.autoRun": {
+          "watch": false,
+          "onSave": "test-src-file"
+        }
       }
     }
   },
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..d7638731d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = 0
+trim_trailing_whitespace = false
+
+[COMMIT_EDITMSG]
+max_line_length = 0
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 000000000..530cfa5e8
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,47 @@
+{
+  "root": true,
+  "extends": [
+    "react-app",
+    "react-app/jest",
+    "plugin:prettier/recommended"
+  ],
+  "plugins": [
+    "prettier",
+    "react",
+    "jsx-a11y",
+    "jest"
+  ],
+  "settings": {
+    "react": {
+      "version": "18.1.0"
+    }
+  },
+  "parser": "babel-eslint",
+  "parserOptions": {
+    "sourceType": "module",
+    "ecmaFeatures": {
+      "modules": true,
+      "jsx": true
+    }
+  },
+  "env": {
+    "amd": true,
+    "browser": true,
+    "es6": true,
+    "jquery": false,
+    "node": true
+  },
+  "rules": {
+    "prettier/prettier": [
+      "error",
+      {
+        "singleQuote": false,
+        "jsxSingleQuote": false,
+        "trailingComma": "all",
+        "semi": true,
+        "bracketSpacing": true,
+        "arrowParens": "always"
+      }
+    ]
+  }
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f479d28d5..ffa0376ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 ### Added
 
 ### Changed
+- Move eslint config to `.eslintrc.json` with prettier support
+- Add `.editorconfig`
 
 ### Fixed
 
diff --git a/package.json b/package.json
index d9707aa92..f15d75b8e 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
     "codemirror": "^6.0.1",
     "container-query-polyfill": "^1.0.2",
     "date-fns": "^2.29.3",
+    "eslint-config-prettier": "^8.8.0",
     "file-saver": "^2.0.5",
     "fs-extra": "^9.0.1",
     "graphql": "^16.6.0",
@@ -76,7 +77,9 @@
     "build": "node scripts/build.js",
     "build:dev": "yarn run build-storybook && node scripts/build.js",
     "build-storybook": "cd ./storybook && yarn install && yarn run build-storybook -- -o ../public/storybook --loglevel warn",
-    "lint": "eslint src/. --ext .js",
+    "lint": "eslint src/**/*.{js,jsx,json}",
+    "lint:fix": "eslint --fix src/**/*.{js,jsx,json}",
+    "format": "prettier --write src/**/*.{js,jsx,css,md,json,scss} --config ./.prettierrc",
     "stylelint": "stylelint --syntax=scss src/**/*.scss",
     "test": "node scripts/test.js --transformIgnorePatterns 'node_modules/(?!three)/'",
     "test:integration": "cd e2e; docker compose up --exit-code-from cypress",
@@ -86,12 +89,6 @@
     "build:wc": "NODE_ENV=production BABEL_ENV=production webpack build -c ./webpack.component.config.js",
     "heroku-postbuild": "export PUBLIC_URL='' && yarn build && yarn build:wc"
   },
-  "eslintConfig": {
-    "extends": [
-      "react-app",
-      "react-app/jest"
-    ]
-  },
   "browserslist": {
     "production": [
       ">0.2%",
@@ -135,6 +132,7 @@
     "eslint-plugin-import": "^2.22.1",
     "eslint-plugin-jest": "^24.1.0",
     "eslint-plugin-jsx-a11y": "^6.3.1",
+    "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-react": "^7.21.5",
     "eslint-plugin-react-hooks": "^4.2.0",
     "eslint-plugin-testing-library": "^3.9.2",
@@ -160,6 +158,7 @@
     "postcss-normalize": "8.0.1",
     "postcss-preset-env": "6.7.0",
     "postcss-safe-parser": "5.0.2",
+    "prettier": "^2.8.8",
     "react-dev-utils": "^11.0.3",
     "react-test-renderer": "^17.0.2",
     "redux-mock-store": "^1.5.4",
diff --git a/src/App.test.js b/src/App.test.js
index 9283d3432..2794faf73 100644
--- a/src/App.test.js
+++ b/src/App.test.js
@@ -1,21 +1,21 @@
-import App from './App';
-import { Provider } from 'react-redux'
-import React from 'react';
-import { act, render, screen } from '@testing-library/react';
-import { Cookies, CookiesProvider } from 'react-cookie';
-import configureStore from 'redux-mock-store';
-
-jest.mock('./utils/Notifications')
-jest.mock('./components/Editor/EditorSlice', () => {
-  const actual = jest.requireActual('./components/Editor/EditorSlice')
+import App from "./App";
+import { Provider } from "react-redux";
+import React from "react";
+import { act, render, screen } from "@testing-library/react";
+import { Cookies, CookiesProvider } from "react-cookie";
+import configureStore from "redux-mock-store";
+
+jest.mock("./utils/Notifications");
+jest.mock("./components/Editor/EditorSlice", () => {
+  const actual = jest.requireActual("./components/Editor/EditorSlice");
   return {
     ...actual,
-    saveProject: jest.fn()
-  }
-})
+    saveProject: jest.fn(),
+  };
+});
 
-describe('Browser prefers light mode', () => {
-  let store
+describe("Browser prefers light mode", () => {
+  let store;
   let cookies;
 
   beforeEach(() => {
@@ -28,49 +28,49 @@ describe('Browser prefers light mode', () => {
       addEventListener: jest.fn(),
       removeEventListener: jest.fn(),
       dispatchEvent: jest.fn(),
-    })
+    });
 
-    cookies = new Cookies()
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    cookies = new Cookies();
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {},
-      auth: {}
-    }
+      auth: {},
+    };
     store = mockStore(initialState);
-  })
+  });
 
-  test('Light mode class name added if no cookie', () => {
+  test("Light mode class name added if no cookie", () => {
     const appContainer = render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(appContainer.container.querySelector('#app')).toHaveClass("--light")
-  })
+      </CookiesProvider>,
+    );
+    expect(appContainer.container.querySelector("#app")).toHaveClass("--light");
+  });
 
-  test('Dark mode class name added if cookie specifies dark theme', () => {
-    cookies.set('theme', 'dark')
+  test("Dark mode class name added if cookie specifies dark theme", () => {
+    cookies.set("theme", "dark");
     const appContainer = render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(appContainer.container.querySelector('#app')).toHaveClass("--dark")
-  })
+      </CookiesProvider>,
+    );
+    expect(appContainer.container.querySelector("#app")).toHaveClass("--dark");
+  });
 
   afterEach(() => {
-    act(() => cookies.remove('theme'))
-  })
-})
+    act(() => cookies.remove("theme"));
+  });
+});
 
-describe('Browser prefers dark mode', () => {
+describe("Browser prefers dark mode", () => {
   let cookies;
-  let store
+  let store;
 
   beforeEach(() => {
     window.matchMedia = (query) => ({
@@ -82,84 +82,84 @@ describe('Browser prefers dark mode', () => {
       addEventListener: jest.fn(),
       removeEventListener: jest.fn(),
       dispatchEvent: jest.fn(),
-    })
+    });
     cookies = new Cookies();
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {},
-      auth: {}
-    }
+      auth: {},
+    };
     store = mockStore(initialState);
-  })
+  });
 
-  test('Dark mode class name added if no cookie', () => {
+  test("Dark mode class name added if no cookie", () => {
     const appContainer = render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(appContainer.container.querySelector('#app')).toHaveClass("--dark")
-  })
+      </CookiesProvider>,
+    );
+    expect(appContainer.container.querySelector("#app")).toHaveClass("--dark");
+  });
 
-  test('Light mode class name added if cookie specifies light theme', () => {
-    cookies.set('theme', 'light')
+  test("Light mode class name added if cookie specifies light theme", () => {
+    cookies.set("theme", "light");
     const appContainer = render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(appContainer.container.querySelector('#app')).toHaveClass("--light")
-  })
+      </CookiesProvider>,
+    );
+    expect(appContainer.container.querySelector("#app")).toHaveClass("--light");
+  });
 
   afterEach(() => {
-    act(() => cookies.remove('theme'))
-  })
-})
+    act(() => cookies.remove("theme"));
+  });
+});
 
-describe('Beta banner', () => {
-  let cookies
-  let store
+describe("Beta banner", () => {
+  let cookies;
+  let store;
 
   beforeEach(() => {
-    cookies = new Cookies()
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    cookies = new Cookies();
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {},
-      auth: {}
-    }
+      auth: {},
+    };
     store = mockStore(initialState);
-  })
+  });
 
-  test('Renders beta banner if betaBannerDismissed cookie not set', () => {
+  test("Renders beta banner if betaBannerDismissed cookie not set", () => {
     render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(screen.queryByText('betaBanner.message')).toBeInTheDocument()
-  })
+      </CookiesProvider>,
+    );
+    expect(screen.queryByText("betaBanner.message")).toBeInTheDocument();
+  });
 
-  test('Does not render beta banner if betaBannerDismissed cookie is true', () => {
-    cookies.set('betaBannerDismissed', 'true')
+  test("Does not render beta banner if betaBannerDismissed cookie is true", () => {
+    cookies.set("betaBannerDismissed", "true");
     render(
       <CookiesProvider cookies={cookies}>
         <Provider store={store}>
           <App />
         </Provider>
-      </CookiesProvider>
-    )
-    expect(screen.queryByText('betaBanner.message')).not.toBeInTheDocument()
-  })
+      </CookiesProvider>,
+    );
+    expect(screen.queryByText("betaBanner.message")).not.toBeInTheDocument();
+  });
 
   afterEach(() => {
-    act(() => cookies.remove('betaBannerDismissed'))
-  })
-})
+    act(() => cookies.remove("betaBannerDismissed"));
+  });
+});
diff --git a/src/Icons.js b/src/Icons.js
index 7279eaf6c..d22681f41 100644
--- a/src/Icons.js
+++ b/src/Icons.js
@@ -432,7 +432,7 @@ export const RunIcon = () => {
       fill="none"
       xmlns="http://www.w3.org/2000/svg"
     >
-      <path d="M0 14V0L11 7L0 14Z"/>
+      <path d="M0 14V0L11 7L0 14Z" />
     </svg>
   );
 };
@@ -480,7 +480,7 @@ export const StopIcon = () => {
       fill="none"
       xmlns="http://www.w3.org/2000/svg"
     >
-      <path d="M0 12V0H12V12H0Z"/>
+      <path d="M0 12V0H12V12H0Z" />
     </svg>
   );
 };
diff --git a/src/app/ComponentStore.js b/src/app/ComponentStore.js
index d7c8ed823..f6bd2325f 100644
--- a/src/app/ComponentStore.js
+++ b/src/app/ComponentStore.js
@@ -1,10 +1,10 @@
-import { configureStore } from '@reduxjs/toolkit'
-import EditorReducer from '../components/Editor/EditorSlice'
+import { configureStore } from "@reduxjs/toolkit";
+import EditorReducer from "../components/Editor/EditorSlice";
 
 const ComponentStore = configureStore({
   reducer: {
     editor: EditorReducer,
   },
-})
+});
 
 export default ComponentStore;
diff --git a/src/app/store.js b/src/app/store.js
index d91ee01f4..55cffeec9 100644
--- a/src/app/store.js
+++ b/src/app/store.js
@@ -1,7 +1,7 @@
-import { configureStore } from '@reduxjs/toolkit'
-import EditorReducer from '../components/Editor/EditorSlice'
-import { reducer, loadUser } from 'redux-oidc'
-import userManager from '../utils/userManager'
+import { configureStore } from "@reduxjs/toolkit";
+import EditorReducer from "../components/Editor/EditorSlice";
+import { reducer, loadUser } from "redux-oidc";
+import userManager from "../utils/userManager";
 
 const store = configureStore({
   reducer: {
@@ -11,11 +11,14 @@ const store = configureStore({
   middleware: (getDefaultMiddleware) =>
     getDefaultMiddleware({
       serializableCheck: {
-        ignoredActions: ['redux-oidc/USER_FOUND', 'redux-odic/SILENT_RENEW_ERROR'],
-        ignoredPaths: ['auth.user'],
-    },
-  }),
-})
+        ignoredActions: [
+          "redux-oidc/USER_FOUND",
+          "redux-odic/SILENT_RENEW_ERROR",
+        ],
+        ignoredPaths: ["auth.user"],
+      },
+    }),
+});
 
 loadUser(store, userManager);
 
diff --git a/src/components/AppRoutes.js b/src/components/AppRoutes.js
index 2c41de761..dfa671a85 100644
--- a/src/components/AppRoutes.js
+++ b/src/components/AppRoutes.js
@@ -1,40 +1,40 @@
-import { React } from 'react'
-import { Route, Routes, Navigate, useParams } from 'react-router-dom'
+import { React } from "react";
+import { Route, Routes, Navigate, useParams } from "react-router-dom";
 import * as Sentry from "@sentry/react";
 
-import ProjectComponentLoader from './Editor/ProjectComponentLoader/ProjectComponentLoader'
-import ProjectIndex from './ProjectIndex/ProjectIndex'
-import EmbeddedViewer from './EmbeddedViewer/EmbeddedViewer'
-import Callback from './Callback'
-import SilentRenew from './SilentRenew'
-import LocaleLayout from './LocaleLayout/LocaleLayout';
+import ProjectComponentLoader from "./Editor/ProjectComponentLoader/ProjectComponentLoader";
+import ProjectIndex from "./ProjectIndex/ProjectIndex";
+import EmbeddedViewer from "./EmbeddedViewer/EmbeddedViewer";
+import Callback from "./Callback";
+import SilentRenew from "./SilentRenew";
+import LocaleLayout from "./LocaleLayout/LocaleLayout";
 
-const projectLinkRedirects = ['/null/projects/:identifier', '/projects/:identifier']
-const localeRedirects = ['/', '/projects']
+const projectLinkRedirects = [
+  "/null/projects/:identifier",
+  "/projects/:identifier",
+];
+const localeRedirects = ["/", "/projects"];
 
 const ProjectsRedirect = () => {
   const { identifier } = useParams();
-  return <Navigate replace to={`/en/projects/${identifier}`} />
-}
+  return <Navigate replace to={`/en/projects/${identifier}`} />;
+};
 
-const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes)
+const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
 
 const AppRoutes = () => (
   <SentryRoutes>
-    <Route
-      path="/auth/callback"
-      element={<Callback/>}
-    />
+    <Route path="/auth/callback" element={<Callback />} />
 
-    <Route
-      path="/auth/silent_renew"
-      element={<SilentRenew/>}
-    />
-    <Route path={":locale"} element={<LocaleLayout/>}>
+    <Route path="/auth/silent_renew" element={<SilentRenew />} />
+    <Route path={":locale"} element={<LocaleLayout />}>
       <Route index element={<ProjectComponentLoader />} />
       <Route path={"projects"} element={<ProjectIndex />} />
-      <Route path={"projects/:identifier"} element={<ProjectComponentLoader />} />
-      <Route path="embed/viewer/:identifier" element={<EmbeddedViewer/>} />
+      <Route
+        path={"projects/:identifier"}
+        element={<ProjectComponentLoader />}
+      />
+      <Route path="embed/viewer/:identifier" element={<EmbeddedViewer />} />
     </Route>
 
     <Route
@@ -44,14 +44,20 @@ const AppRoutes = () => (
 
     {/* Redirects will be moved into a cloudflare worker. This is just interim */}
 
-    { projectLinkRedirects.map(link => {
-      return <Route key={link} path={link} element={<ProjectsRedirect />} />
-    }) }
-
-    { localeRedirects.map(link => {
-      return <Route key={link} path={link} element={<Navigate replace to={`/en${link}`} />} />
-    }) }
+    {projectLinkRedirects.map((link) => {
+      return <Route key={link} path={link} element={<ProjectsRedirect />} />;
+    })}
+
+    {localeRedirects.map((link) => {
+      return (
+        <Route
+          key={link}
+          path={link}
+          element={<Navigate replace to={`/en${link}`} />}
+        />
+      );
+    })}
   </SentryRoutes>
-)
+);
 
-export default AppRoutes
+export default AppRoutes;
diff --git a/src/components/AstroPiModel/AstroPiControls/AstroPiControls.js b/src/components/AstroPiModel/AstroPiControls/AstroPiControls.js
index 02dff4224..3ca189fc4 100644
--- a/src/components/AstroPiModel/AstroPiControls/AstroPiControls.js
+++ b/src/components/AstroPiModel/AstroPiControls/AstroPiControls.js
@@ -1,34 +1,65 @@
-import React from 'react';
-import Input from './Input';
-import MotionInput from './MotionInput';
-import SliderInput from './SliderInput';
-import '../AstroPiModel.scss';
-import Stopwatch from './Stopwatch';
-import { HumidityIcon, PressureIcon, TemperatureIcon } from '../../../Icons';
-import { useTranslation } from 'react-i18next';
+import React from "react";
+import Input from "./Input";
+import MotionInput from "./MotionInput";
+import SliderInput from "./SliderInput";
+import "../AstroPiModel.scss";
+import Stopwatch from "./Stopwatch";
+import { HumidityIcon, PressureIcon, TemperatureIcon } from "../../../Icons";
+import { useTranslation } from "react-i18next";
 
 const AstroPiControls = (props) => {
-  const {temperature, pressure, humidity, colour, motion} = props
-  const { t } = useTranslation()
+  const { temperature, pressure, humidity, colour, motion } = props;
+  const { t } = useTranslation();
 
   return (
-    <div className='sense-hat-controls'>
-      <h2 className='sense-hat-controls-heading'>{t('output.senseHat.controls.name')}</h2>
+    <div className="sense-hat-controls">
+      <h2 className="sense-hat-controls-heading">
+        {t("output.senseHat.controls.name")}
+      </h2>
       <div className="sense-hat-controls-panel">
-        <div className='sense-hat-controls-panel__sliders'>
-          <SliderInput name="temperature" label={t('output.senseHat.controls.temperature')} unit="°C" min={-40} max={120} defaultValue={temperature} Icon={TemperatureIcon} />
-          <SliderInput name="pressure" label={t('output.senseHat.controls.pressure')} unit="hPa" min={260} max={1260} defaultValue={pressure} Icon={PressureIcon}/>
-          <SliderInput name="humidity" label={t('output.senseHat.controls.humidity')} unit="%" min={0} max={100} defaultValue={humidity} Icon={HumidityIcon}/>
+        <div className="sense-hat-controls-panel__sliders">
+          <SliderInput
+            name="temperature"
+            label={t("output.senseHat.controls.temperature")}
+            unit="°C"
+            min={-40}
+            max={120}
+            defaultValue={temperature}
+            Icon={TemperatureIcon}
+          />
+          <SliderInput
+            name="pressure"
+            label={t("output.senseHat.controls.pressure")}
+            unit="hPa"
+            min={260}
+            max={1260}
+            defaultValue={pressure}
+            Icon={PressureIcon}
+          />
+          <SliderInput
+            name="humidity"
+            label={t("output.senseHat.controls.humidity")}
+            unit="%"
+            min={0}
+            max={100}
+            defaultValue={humidity}
+            Icon={HumidityIcon}
+          />
         </div>
-      
+
         <div className="sense-hat-controls-panel__control sense-hat-controls-panel__control-last">
-          <Input name="colour" label={t('output.senseHat.controls.colour')} type="color" defaultValue={colour} />
+          <Input
+            name="colour"
+            label={t("output.senseHat.controls.colour")}
+            type="color"
+            defaultValue={colour}
+          />
           <MotionInput defaultValue={motion} />
           <Stopwatch />
         </div>
       </div>
     </div>
-  )
+  );
 };
 
-export default AstroPiControls
+export default AstroPiControls;
diff --git a/src/components/AstroPiModel/AstroPiControls/AstroPiControls.test.js b/src/components/AstroPiModel/AstroPiControls/AstroPiControls.test.js
index 12c23ea6c..36a4e94c0 100644
--- a/src/components/AstroPiModel/AstroPiControls/AstroPiControls.test.js
+++ b/src/components/AstroPiModel/AstroPiControls/AstroPiControls.test.js
@@ -1,64 +1,73 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import AstroPiControls from "./AstroPiControls";
-import Sk from 'skulpt';
+import Sk from "skulpt";
 
 let container;
 let store;
 
 beforeEach(() => {
-  Sk.sense_hat={
+  Sk.sense_hat = {
     mz_criteria: {},
     rtimu: {
-      temperature: [0,0],
-      pressure: [0,0],
-      humidity: [0,0]
-    }
-  }
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        codeRunTriggered: false
-      },
-    }
-    store = mockStore(initialState);
-    container = render(<Provider store={store}><AstroPiControls temperature={65} pressure={456} humidity={37} motion={true} colour="#e01010"/></Provider>)
-})
+      temperature: [0, 0],
+      pressure: [0, 0],
+      humidity: [0, 0],
+    },
+  };
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      codeRunTriggered: false,
+    },
+  };
+  store = mockStore(initialState);
+  container = render(
+    <Provider store={store}>
+      <AstroPiControls
+        temperature={65}
+        pressure={456}
+        humidity={37}
+        motion={true}
+        colour="#e01010"
+      />
+    </Provider>,
+  );
+});
 
 test("Renders temperature with units", () => {
-  expect(container.queryByText("65°C")).not.toBeNull()
-})
+  expect(container.queryByText("65°C")).not.toBeNull();
+});
 
 test("Renders pressure with units", () => {
-  expect(container.getByText("456hPa")).not.toBeNull()
-})
+  expect(container.getByText("456hPa")).not.toBeNull();
+});
 
 test("Renders humidity with units", () => {
-  expect(container.getByText("37%")).not.toBeNull()
-})
+  expect(container.getByText("37%")).not.toBeNull();
+});
 
 test("Renders temperature input with correct value", () => {
-  expect(container.queryByDisplayValue(65)).not.toBeNull()
-})
+  expect(container.queryByDisplayValue(65)).not.toBeNull();
+});
 
 test("Renders pressure input with correct value", () => {
-  expect(container.queryByDisplayValue(456)).not.toBeNull()
-})
+  expect(container.queryByDisplayValue(456)).not.toBeNull();
+});
 
 test("Renders humidity input with correct value", () => {
-  expect(container.queryByDisplayValue(37)).not.toBeNull()
-})
+  expect(container.queryByDisplayValue(37)).not.toBeNull();
+});
 
 test("Renders motion input with correct value", () => {
-  expect(container.queryByLabelText('output.senseHat.controls.motion').checked).toBe(true)
-})
+  expect(
+    container.queryByLabelText("output.senseHat.controls.motion").checked,
+  ).toBe(true);
+});
 
 test("Renders colour input with correct value", () => {
-  expect(container.queryByDisplayValue("#e01010")).not.toBeNull()
-})
-
-
-
+  expect(container.queryByDisplayValue("#e01010")).not.toBeNull();
+});
diff --git a/src/components/AstroPiModel/AstroPiControls/Input.js b/src/components/AstroPiModel/AstroPiControls/Input.js
index f8b7ec9a2..39b448452 100644
--- a/src/components/AstroPiModel/AstroPiControls/Input.js
+++ b/src/components/AstroPiModel/AstroPiControls/Input.js
@@ -1,24 +1,34 @@
-import React from 'react';
-import { useEffect, useState } from 'react';
-import Sk from 'skulpt';
-import '../AstroPiModel.scss';
+import React from "react";
+import { useEffect, useState } from "react";
+import Sk from "skulpt";
+import "../AstroPiModel.scss";
 
 const Input = (props) => {
-  const { name, label, type, defaultValue} = props;
+  const { name, label, type, defaultValue } = props;
   const [value, setValue] = useState(defaultValue);
 
   useEffect(() => {
     if (Sk.sense_hat) {
-      Sk.sense_hat[name] = value
+      Sk.sense_hat[name] = value;
     }
-  }, [name, value])
+  }, [name, value]);
 
   return (
-    <div className='sense-hat-controls-panel__container'>
-      <label className='sense-hat-controls-panel__control-name' htmlFor={`sense_hat_${name}`}>{label}</label>
-      <input type={type} id={`sense_hat_${name}`} defaultValue={value} onChange={e => setValue(e.target.value)} />
+    <div className="sense-hat-controls-panel__container">
+      <label
+        className="sense-hat-controls-panel__control-name"
+        htmlFor={`sense_hat_${name}`}
+      >
+        {label}
+      </label>
+      <input
+        type={type}
+        id={`sense_hat_${name}`}
+        defaultValue={value}
+        onChange={(e) => setValue(e.target.value)}
+      />
     </div>
-  )
+  );
 };
 
-export default Input
+export default Input;
diff --git a/src/components/AstroPiModel/AstroPiControls/Input.test.js b/src/components/AstroPiModel/AstroPiControls/Input.test.js
index 01eec23e1..318d4d233 100644
--- a/src/components/AstroPiModel/AstroPiControls/Input.test.js
+++ b/src/components/AstroPiModel/AstroPiControls/Input.test.js
@@ -1,27 +1,35 @@
 import React from "react";
-import { render } from "@testing-library/react"
+import { render } from "@testing-library/react";
 import Input from "./Input";
-import Sk from 'skulpt';
+import Sk from "skulpt";
 
 let inputComponent;
 
 beforeEach(() => {
-  Sk.sense_hat={}
-  inputComponent = render(<Input name="foo" label="bar" type="color" defaultValue="#e01010"/>)
-})
+  Sk.sense_hat = {};
+  inputComponent = render(
+    <Input name="foo" label="bar" type="color" defaultValue="#e01010" />,
+  );
+});
 
 test("Renders as expected", () => {
-  expect(inputComponent.queryByText(/bar/)).not.toBeNull()
-})
+  expect(inputComponent.queryByText(/bar/)).not.toBeNull();
+});
 
 test("Creates input of correct type", () => {
-  expect(inputComponent.queryByLabelText(/bar/)).toHaveAttribute("type", "color")
-})
+  expect(inputComponent.queryByLabelText(/bar/)).toHaveAttribute(
+    "type",
+    "color",
+  );
+});
 
 test("Creates input with correct value", () => {
-  expect(inputComponent.queryByLabelText(/bar/)).toHaveAttribute("value", "#e01010")
-})
+  expect(inputComponent.queryByLabelText(/bar/)).toHaveAttribute(
+    "value",
+    "#e01010",
+  );
+});
 
 test("Sets skulpt value correctly", () => {
-  expect(Sk.sense_hat.foo).toEqual("#e01010")
-})
+  expect(Sk.sense_hat.foo).toEqual("#e01010");
+});
diff --git a/src/components/AstroPiModel/AstroPiControls/MotionInput.js b/src/components/AstroPiModel/AstroPiControls/MotionInput.js
index cddec8972..eb5e5ba3c 100644
--- a/src/components/AstroPiModel/AstroPiControls/MotionInput.js
+++ b/src/components/AstroPiModel/AstroPiControls/MotionInput.js
@@ -1,42 +1,60 @@
-import React from 'react';
-import { useEffect, useState } from 'react';
-import { useSelector } from 'react-redux';
-import Toggle from 'react-toggle';
-import Sk from 'skulpt';
-import '../AstroPiModel.scss';
-import "react-toggle/style.css"
-import { useTranslation } from 'react-i18next';
+import React from "react";
+import { useEffect, useState } from "react";
+import { useSelector } from "react-redux";
+import Toggle from "react-toggle";
+import Sk from "skulpt";
+import "../AstroPiModel.scss";
+import "react-toggle/style.css";
+import { useTranslation } from "react-i18next";
 
 const MotionInput = (props) => {
-  const {defaultValue} = props;
+  const { defaultValue } = props;
   const [value, setValue] = useState(defaultValue);
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered);
-  const { t } = useTranslation()
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
+  const { t } = useTranslation();
 
   useEffect(() => {
     if (!codeRunTriggered) {
-      Sk.sense_hat.start_motion_callback = () => {}
-      Sk.sense_hat.stop_motion_callback = () => {}
+      Sk.sense_hat.start_motion_callback = () => {};
+      Sk.sense_hat.stop_motion_callback = () => {};
     }
-  }, [codeRunTriggered])
+  }, [codeRunTriggered]);
 
   useEffect(() => {
     if (Sk.sense_hat) {
-      Sk.sense_hat.motion = value
+      Sk.sense_hat.motion = value;
     }
-    value ? Sk.sense_hat.start_motion_callback() : Sk.sense_hat.stop_motion_callback()
-  }, [value])
+    value
+      ? Sk.sense_hat.start_motion_callback()
+      : Sk.sense_hat.stop_motion_callback();
+  }, [value]);
 
   return (
-  <div className="sense-hat-controls-panel__container">
-    <label className='sense-hat-controls-panel__control-name' htmlFor={`sense_hat_motion`}>{t('output.senseHat.controls.motion')}</label>
-    <div className='sense-hat-controls-panel__control-toggle'>
-      <label htmlFor={`sense_hat_motion`} >{t('output.senseHat.controls.motionSensorOptions.no')}</label>
-      <Toggle id='sense_hat_motion' icons={false} checked={value} onChange={e => setValue(e.target.checked)}/>
-      <label htmlFor={`sense_hat_motion`} >{t('output.senseHat.controls.motionSensorOptions.yes')}</label>
+    <div className="sense-hat-controls-panel__container">
+      <label
+        className="sense-hat-controls-panel__control-name"
+        htmlFor={`sense_hat_motion`}
+      >
+        {t("output.senseHat.controls.motion")}
+      </label>
+      <div className="sense-hat-controls-panel__control-toggle">
+        <label htmlFor={`sense_hat_motion`}>
+          {t("output.senseHat.controls.motionSensorOptions.no")}
+        </label>
+        <Toggle
+          id="sense_hat_motion"
+          icons={false}
+          checked={value}
+          onChange={(e) => setValue(e.target.checked)}
+        />
+        <label htmlFor={`sense_hat_motion`}>
+          {t("output.senseHat.controls.motionSensorOptions.yes")}
+        </label>
+      </div>
     </div>
-  </div>
-  )
+  );
 };
 
-export default MotionInput
+export default MotionInput;
diff --git a/src/components/AstroPiModel/AstroPiControls/MotionInput.test.js b/src/components/AstroPiModel/AstroPiControls/MotionInput.test.js
index c41cf64f6..61f154f13 100644
--- a/src/components/AstroPiModel/AstroPiControls/MotionInput.test.js
+++ b/src/components/AstroPiModel/AstroPiControls/MotionInput.test.js
@@ -1,115 +1,135 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import MotionInput from "./MotionInput";
-import Sk from 'skulpt';
+import Sk from "skulpt";
 
 let container;
 let store;
-const start_motion_function = jest.fn()
-const stop_motion_function = jest.fn()
+const start_motion_function = jest.fn();
+const stop_motion_function = jest.fn();
 
 describe("No motion and code running", () => {
   beforeEach(() => {
-    Sk.sense_hat={
+    Sk.sense_hat = {
       start_motion_callback: start_motion_function,
-      stop_motion_callback: stop_motion_function
-    }
-    const middlewares = []
-      const mockStore = configureStore(middlewares)
-      const initialState = {
-        editor: {
-          codeRunTriggered: true
-        },
-      }
-      store = mockStore(initialState);
-      container = render(<Provider store={store}><MotionInput defaultValue={false}/></Provider>)
-  })
-  
+      stop_motion_callback: stop_motion_function,
+    };
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
+    const initialState = {
+      editor: {
+        codeRunTriggered: true,
+      },
+    };
+    store = mockStore(initialState);
+    container = render(
+      <Provider store={store}>
+        <MotionInput defaultValue={false} />
+      </Provider>,
+    );
+  });
+
   test("Displays checkbox with correct value", () => {
-    expect(container.queryByLabelText('output.senseHat.controls.motion').checked).toBe(false)
-  })
-  
+    expect(
+      container.queryByLabelText("output.senseHat.controls.motion").checked,
+    ).toBe(false);
+  });
+
   test("Stop motion function has been called", () => {
-    expect(stop_motion_function).toHaveBeenCalledTimes(1)
-  })
-  
+    expect(stop_motion_function).toHaveBeenCalledTimes(1);
+  });
+
   test("Skulpt sense hat motion set to false", () => {
-    expect(Sk.sense_hat.motion).toBe(false)
-  })
-})
+    expect(Sk.sense_hat.motion).toBe(false);
+  });
+});
 
 describe("Motion and code running", () => {
   beforeEach(() => {
-    Sk.sense_hat={
+    Sk.sense_hat = {
       start_motion_callback: start_motion_function,
-      stop_motion_callback: stop_motion_function
-    }
-    const middlewares = []
-      const mockStore = configureStore(middlewares)
-      const initialState = {
-        editor: {
-          codeRunTriggered: true
-        },
-      }
-      store = mockStore(initialState);
-      container = render(<Provider store={store}><MotionInput defaultValue={true}/></Provider>)
-  })
-  
+      stop_motion_callback: stop_motion_function,
+    };
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
+    const initialState = {
+      editor: {
+        codeRunTriggered: true,
+      },
+    };
+    store = mockStore(initialState);
+    container = render(
+      <Provider store={store}>
+        <MotionInput defaultValue={true} />
+      </Provider>,
+    );
+  });
+
   test("Displays checkbox with correct value", () => {
-    expect(container.queryByLabelText('output.senseHat.controls.motion').checked).toBe(true)
-  })
-  
+    expect(
+      container.queryByLabelText("output.senseHat.controls.motion").checked,
+    ).toBe(true);
+  });
+
   test("Stop motion function has been called", () => {
-    expect(start_motion_function).toHaveBeenCalledTimes(1)
-  })
+    expect(start_motion_function).toHaveBeenCalledTimes(1);
+  });
 
   test("Skulpt sense hat motion set to true", () => {
-    expect(Sk.sense_hat.motion).toBe(true)
-  })
-})
+    expect(Sk.sense_hat.motion).toBe(true);
+  });
+});
 
 describe("No motion and code not running", () => {
   beforeEach(() => {
-    Sk.sense_hat={
+    Sk.sense_hat = {
       start_motion_callback: start_motion_function,
-      stop_motion_callback: stop_motion_function
-    }
-    const middlewares = []
-      const mockStore = configureStore(middlewares)
-      const initialState = {
-        editor: {
-          codeRunTriggered: false
-        },
-      }
-      store = mockStore(initialState);
-      container = render(<Provider store={store}><MotionInput defaultValue={false}/></Provider>)
-  })
+      stop_motion_callback: stop_motion_function,
+    };
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
+    const initialState = {
+      editor: {
+        codeRunTriggered: false,
+      },
+    };
+    store = mockStore(initialState);
+    container = render(
+      <Provider store={store}>
+        <MotionInput defaultValue={false} />
+      </Provider>,
+    );
+  });
 
   test("Stop motion function not called", () => {
-    expect(stop_motion_function).not.toHaveBeenCalled()
-  })
-})
+    expect(stop_motion_function).not.toHaveBeenCalled();
+  });
+});
 
 describe("Motion and code not running", () => {
   beforeEach(() => {
-    Sk.sense_hat={
+    Sk.sense_hat = {
       start_motion_callback: start_motion_function,
-      stop_motion_callback: stop_motion_function
-    }
-    const middlewares = []
-      const mockStore = configureStore(middlewares)
-      const initialState = {
-        editor: {
-          codeRunTriggered: false
-        },
-      }
-      store = mockStore(initialState);
-      container = render(<Provider store={store}><MotionInput defaultValue={true}/></Provider>)
-  })
+      stop_motion_callback: stop_motion_function,
+    };
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
+    const initialState = {
+      editor: {
+        codeRunTriggered: false,
+      },
+    };
+    store = mockStore(initialState);
+    container = render(
+      <Provider store={store}>
+        <MotionInput defaultValue={true} />
+      </Provider>,
+    );
+  });
 
   test("Start motion function not called", () => {
-    expect(start_motion_function).not.toHaveBeenCalled()
-  })
-})
+    expect(start_motion_function).not.toHaveBeenCalled();
+  });
+});
diff --git a/src/components/AstroPiModel/AstroPiControls/SliderInput.js b/src/components/AstroPiModel/AstroPiControls/SliderInput.js
index 8444184d5..03277016f 100644
--- a/src/components/AstroPiModel/AstroPiControls/SliderInput.js
+++ b/src/components/AstroPiModel/AstroPiControls/SliderInput.js
@@ -1,28 +1,45 @@
-import React from 'react';
-import { useEffect, useState } from 'react';
-import '../AstroPiModel.scss';
-import Sk from 'skulpt';
+import React from "react";
+import { useEffect, useState } from "react";
+import "../AstroPiModel.scss";
+import Sk from "skulpt";
 
 const SliderInput = (props) => {
-  const { name, label, unit, min, max, defaultValue, Icon} = props;
+  const { name, label, unit, min, max, defaultValue, Icon } = props;
   const [value, setValue] = useState(defaultValue);
-  
+
   useEffect(() => {
     if (Sk.sense_hat) {
-      Sk.sense_hat.rtimu[name][1] = value+Math.random()-0.5
+      Sk.sense_hat.rtimu[name][1] = value + Math.random() - 0.5;
     }
-  }, [name, value])
+  }, [name, value]);
 
   return (
     <div className="sense-hat-controls-panel__control">
-      <label className='sense-hat-controls-panel__control-name' htmlFor={`sense_hat_${name}`}>{label}</label>
-      <input id={`sense_hat_${name}`} className="sense-hat-controls-panel__control-input" type="range" min={min} max={max} step="1" defaultValue={value} onChange={e => setValue(parseFloat(e.target.value))}/>
+      <label
+        className="sense-hat-controls-panel__control-name"
+        htmlFor={`sense_hat_${name}`}
+      >
+        {label}
+      </label>
+      <input
+        id={`sense_hat_${name}`}
+        className="sense-hat-controls-panel__control-input"
+        type="range"
+        min={min}
+        max={max}
+        step="1"
+        defaultValue={value}
+        onChange={(e) => setValue(parseFloat(e.target.value))}
+      />
       <div className="sense-hat-controls-panel__control-reading">
         {Icon ? <Icon /> : null}
-        <span className='sense-hat-controls-panel__control-value'>{value}{unit}</span>
+        <span className="sense-hat-controls-panel__control-value">
+          {value}
+          {unit}
+        </span>
       </div>
     </div>
-  )
+  );
 };
 
-export default SliderInput
+export default SliderInput;
diff --git a/src/components/AstroPiModel/AstroPiControls/SliderInput.test.js b/src/components/AstroPiModel/AstroPiControls/SliderInput.test.js
index 7f1cd1163..3924bbf9e 100644
--- a/src/components/AstroPiModel/AstroPiControls/SliderInput.test.js
+++ b/src/components/AstroPiModel/AstroPiControls/SliderInput.test.js
@@ -1,29 +1,36 @@
 import React from "react";
-import { render } from "@testing-library/react"
+import { render } from "@testing-library/react";
 import SliderInput from "./SliderInput";
-import Sk from 'skulpt';
+import Sk from "skulpt";
 
 let container;
-Sk.sense_hat={
+Sk.sense_hat = {
   rtimu: {
-    "foo": [0,0]
-  }
-}
+    foo: [0, 0],
+  },
+};
 
 beforeEach(() => {
-  container = render(<SliderInput name="foo" unit="bar" max={2000} min={0} defaultValue={1234}/>)
-
-})
+  container = render(
+    <SliderInput
+      name="foo"
+      unit="bar"
+      max={2000}
+      min={0}
+      defaultValue={1234}
+    />,
+  );
+});
 
 test("Renders with correct unit and value", () => {
-  expect(container.queryByText("1234bar")).not.toBeNull()
-})
+  expect(container.queryByText("1234bar")).not.toBeNull();
+});
 
 test("Renders slider input with correct value", () => {
-  expect(container.queryByDisplayValue(1234)).not.toBeNull()
-})
+  expect(container.queryByDisplayValue(1234)).not.toBeNull();
+});
 
 test("Correct skulpt value when renders", () => {
-  expect(Sk.sense_hat.rtimu["foo"][1]).toBeLessThan(1234.5)
-  expect(Sk.sense_hat.rtimu["foo"][1]).toBeGreaterThanOrEqual(1233.5)
-})
+  expect(Sk.sense_hat.rtimu["foo"][1]).toBeLessThan(1234.5);
+  expect(Sk.sense_hat.rtimu["foo"][1]).toBeGreaterThanOrEqual(1233.5);
+});
diff --git a/src/components/AstroPiModel/AstroPiControls/Stopwatch.js b/src/components/AstroPiModel/AstroPiControls/Stopwatch.js
index d4f99a8d9..c36191bb0 100644
--- a/src/components/AstroPiModel/AstroPiControls/Stopwatch.js
+++ b/src/components/AstroPiModel/AstroPiControls/Stopwatch.js
@@ -1,47 +1,63 @@
-import React, { useEffect, useState } from 'react'
-import { useTranslation } from 'react-i18next';
-import { useSelector } from 'react-redux';
-import { useStopwatch } from 'react-timer-hook';
-import Sk from 'skulpt'
+import React, { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
+import { useStopwatch } from "react-timer-hook";
+import Sk from "skulpt";
 
 const Stopwatch = () => {
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered)
-  const {
-    seconds,
-    minutes,
-    isRunning,
-    pause,
-    reset
-  } = useStopwatch({ autoStart: false })
-  const [hasLostFocus, setHasLostFocus] = useState(false)
-  const { t } = useTranslation()
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
+  const { seconds, minutes, isRunning, pause, reset } = useStopwatch({
+    autoStart: false,
+  });
+  const [hasLostFocus, setHasLostFocus] = useState(false);
+  const { t } = useTranslation();
 
   useEffect(() => {
-    window.addEventListener('blur', () => {
-      setHasLostFocus(true)
-    })
-  }, [])
+    window.addEventListener("blur", () => {
+      setHasLostFocus(true);
+    });
+  }, []);
 
   useEffect(() => {
     if (codeRunTriggered && !isRunning) {
-      setHasLostFocus(false)
-      reset()
+      setHasLostFocus(false);
+      reset();
     }
-    if (!codeRunTriggered && isRunning){
-      pause()
-      Sk.sense_hat.mz_criteria.duration = hasLostFocus ? null : minutes * 60 + seconds
+    if (!codeRunTriggered && isRunning) {
+      pause();
+      Sk.sense_hat.mz_criteria.duration = hasLostFocus
+        ? null
+        : minutes * 60 + seconds;
     }
-  }, [codeRunTriggered, hasLostFocus, minutes, seconds, isRunning, pause, reset])
-
+  }, [
+    codeRunTriggered,
+    hasLostFocus,
+    minutes,
+    seconds,
+    isRunning,
+    pause,
+    reset,
+  ]);
 
   return (
-    <div className='sense-hat-controls-panel__container sense-hat-controls-panel__container-timer'>
-      <label className='sense-hat-controls-panel__control-name' htmlFor='sense_hat_timer'>{t('output.senseHat.controls.timer')}</label>
-      <span className='sense-hat-controls-panel__control-reading sense-hat-controls-panel__control-reading-timer' id='sense_hat_timer'>
-        <span>{String(minutes).padStart(2, '0')}</span>:<span>{String(seconds).padStart(2, '0')}</span>
+    <div className="sense-hat-controls-panel__container sense-hat-controls-panel__container-timer">
+      <label
+        className="sense-hat-controls-panel__control-name"
+        htmlFor="sense_hat_timer"
+      >
+        {t("output.senseHat.controls.timer")}
+      </label>
+      <span
+        className="sense-hat-controls-panel__control-reading sense-hat-controls-panel__control-reading-timer"
+        id="sense_hat_timer"
+      >
+        <span>{String(minutes).padStart(2, "0")}</span>:
+        <span>{String(seconds).padStart(2, "0")}</span>
       </span>
     </div>
-  )
-}
+  );
+};
 
-export default Stopwatch
+export default Stopwatch;
diff --git a/src/components/AstroPiModel/AstroPiControls/Stopwatch.test.js b/src/components/AstroPiModel/AstroPiControls/Stopwatch.test.js
index af9ecf7d5..63cc0b13b 100644
--- a/src/components/AstroPiModel/AstroPiControls/Stopwatch.test.js
+++ b/src/components/AstroPiModel/AstroPiControls/Stopwatch.test.js
@@ -1,23 +1,27 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
-import Sk from 'skulpt';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
+import Sk from "skulpt";
 import Stopwatch from "./Stopwatch";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 const initialState = {
   editor: {
-    codeRunTriggered: false
+    codeRunTriggered: false,
   },
-}
+};
 const store = mockStore(initialState);
-Sk.sense_hat={
-  mz_criteria: {}
-}
+Sk.sense_hat = {
+  mz_criteria: {},
+};
 
-test("Stopwatch renders in form mm:ss", () =>{
-  const { getAllByText } = render(<Provider store = {store}><Stopwatch /></Provider>)
-  expect(getAllByText("00")).toHaveLength(2)
-})
+test("Stopwatch renders in form mm:ss", () => {
+  const { getAllByText } = render(
+    <Provider store={store}>
+      <Stopwatch />
+    </Provider>,
+  );
+  expect(getAllByText("00")).toHaveLength(2);
+});
diff --git a/src/components/AstroPiModel/AstroPiModel.js b/src/components/AstroPiModel/AstroPiModel.js
index 956ca669f..f14de8729 100644
--- a/src/components/AstroPiModel/AstroPiModel.js
+++ b/src/components/AstroPiModel/AstroPiModel.js
@@ -1,77 +1,97 @@
-import React from 'react';
-import './AstroPiModel.scss';
-import Simulator from './Simulator';
-import Sk from 'skulpt';
-import AstroPiControls from './AstroPiControls/AstroPiControls';
-import OrientationPanel from './OrientationPanel/OrientationPanel';
-import { useEffect, useState } from 'react';
-import { resetModel, updateRTIMU } from '../../utils/Orientation';
-import { useSelector } from 'react-redux';
-import { defaultMZCriteria } from './DefaultMZCriteria';
+import React from "react";
+import "./AstroPiModel.scss";
+import Simulator from "./Simulator";
+import Sk from "skulpt";
+import AstroPiControls from "./AstroPiControls/AstroPiControls";
+import OrientationPanel from "./OrientationPanel/OrientationPanel";
+import { useEffect, useState } from "react";
+import { resetModel, updateRTIMU } from "../../utils/Orientation";
+import { useSelector } from "react-redux";
+import { defaultMZCriteria } from "./DefaultMZCriteria";
 
 const AstroPiModel = () => {
-  const project = useSelector((state) => state.editor.project)
-  const [orientation, setOrientation] = useState([0,90,0])
+  const project = useSelector((state) => state.editor.project);
+  const [orientation, setOrientation] = useState([0, 90, 0]);
   const resetOrientation = (e) => {
-    resetModel(e)
-    setOrientation([0,90,0])
-  }
+    resetModel(e);
+    setOrientation([0, 90, 0]);
+  };
 
-  const defaultPressure = 1013
-  const defaultTemperature = 13
-  const defaultHumidity = 45
+  const defaultPressure = 1013;
+  const defaultTemperature = 13;
+  const defaultHumidity = 45;
 
-  if (!Sk.sense_hat){
+  if (!Sk.sense_hat) {
     Sk.sense_hat = {
       colour: "#FF00A4",
-      gamma: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+      gamma: [
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+      ],
       low_light: false,
       motion: false,
-      mz_criteria: {...defaultMZCriteria},
+      mz_criteria: { ...defaultMZCriteria },
       pixels: [],
       rtimu: {
-        pressure: [1, defaultPressure+Math.random()-0.5], /* isValid, pressure*/
-        temperature: [1, defaultTemperature+Math.random()-0.5], /* isValid, temperature */
-        humidity: [1, defaultHumidity+Math.random()-0.5], /* isValid, humidity */
-        gyro: [0, 0, 0], /* all 3 gyro values */
-        accel: [0, 0, 0], /* all 3 accel values */
-        compass: [0, 0, 33], /* all compass values */
-        raw_orientation: [0, 90, 0]
+        pressure: [
+          1,
+          defaultPressure + Math.random() - 0.5,
+        ] /* isValid, pressure*/,
+        temperature: [
+          1,
+          defaultTemperature + Math.random() - 0.5,
+        ] /* isValid, temperature */,
+        humidity: [
+          1,
+          defaultHumidity + Math.random() - 0.5,
+        ] /* isValid, humidity */,
+        gyro: [0, 0, 0] /* all 3 gyro values */,
+        accel: [0, 0, 0] /* all 3 accel values */,
+        compass: [0, 0, 33] /* all compass values */,
+        raw_orientation: [0, 90, 0],
       },
       sensestick: {
         _eventQueue: [],
         off: () => {},
-        once: () => {}
+        once: () => {},
       },
       start_motion_callback: () => {},
       stop_motion_callback: () => {},
-    }
+    };
     for (var i = 0; i < 64; i++) {
       Sk.sense_hat.pixels.push([0, 0, 0]);
     }
   }
 
   useEffect(() => {
-    Sk.sense_hat.mz_criteria = {...defaultMZCriteria}
+    Sk.sense_hat.mz_criteria = { ...defaultMZCriteria };
   }, [project]);
 
   useEffect(() => {
-    Sk.sense_hat.rtimu.raw_orientation = orientation
-    updateRTIMU()
-  }, [orientation])
+    Sk.sense_hat.rtimu.raw_orientation = orientation;
+    updateRTIMU();
+  }, [orientation]);
 
-    return (
-      <div className='sense-hat'>
-        <div className='sense-hat-model'>
-          <Simulator updateOrientation={setOrientation}/>
-          <OrientationPanel orientation={orientation} resetOrientation={resetOrientation}/>
-        </div>
+  return (
+    <div className="sense-hat">
+      <div className="sense-hat-model">
+        <Simulator updateOrientation={setOrientation} />
+        <OrientationPanel
+          orientation={orientation}
+          resetOrientation={resetOrientation}
+        />
+      </div>
 
-        {/* <!-- Full sensor controls --> */}
-        <AstroPiControls pressure={defaultPressure} temperature={defaultTemperature} humidity={defaultHumidity} colour={Sk.sense_hat.colour} motion={Sk.sense_hat.motion} />
+      {/* <!-- Full sensor controls --> */}
+      <AstroPiControls
+        pressure={defaultPressure}
+        temperature={defaultTemperature}
+        humidity={defaultHumidity}
+        colour={Sk.sense_hat.colour}
+        motion={Sk.sense_hat.motion}
+      />
+    </div>
+  );
+};
 
-      </div>
-    )
-  };
-  
-  export default AstroPiModel;
+export default AstroPiModel;
diff --git a/src/components/AstroPiModel/AstroPiModel.test.js b/src/components/AstroPiModel/AstroPiModel.test.js
index d3c36df7e..8ca5e791b 100644
--- a/src/components/AstroPiModel/AstroPiModel.test.js
+++ b/src/components/AstroPiModel/AstroPiModel.test.js
@@ -1,41 +1,46 @@
 import React from "react";
-import { fireEvent, render } from "@testing-library/react"
-import { Provider } from 'react-redux';
+import { fireEvent, render } from "@testing-library/react";
+import { Provider } from "react-redux";
 import AstroPiModel from "./AstroPiModel";
-import configureStore from 'redux-mock-store';
-import Sk from 'skulpt';
+import configureStore from "redux-mock-store";
+import Sk from "skulpt";
 
 let container;
 let store;
 
 beforeEach(() => {
-  Sk.sense_hat={
+  Sk.sense_hat = {
     mz_criteria: {},
     rtimu: {
-      temperature: [0,0],
-      pressure: [0,0],
-      humidity: [0,0]
-    }
-  }
-  window.mod={
-    rotation: {}
-  }
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        codeRunTriggered: false
-      },
-    }
-    store = mockStore(initialState);
-    container = render(<Provider store={store}> <AstroPiModel/> </Provider>)
-})
+      temperature: [0, 0],
+      pressure: [0, 0],
+      humidity: [0, 0],
+    },
+  };
+  window.mod = {
+    rotation: {},
+  };
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      codeRunTriggered: false,
+    },
+  };
+  store = mockStore(initialState);
+  container = render(
+    <Provider store={store}>
+      {" "}
+      <AstroPiModel />{" "}
+    </Provider>,
+  );
+});
 
 test("Component renders", () => {
-  expect(container).not.toBeNull()
-})
+  expect(container).not.toBeNull();
+});
 
 test("Update orientation function resets the model", () => {
-  fireEvent.click(container.getByRole("button"))
-  expect(window.mod.rotation).toStrictEqual({x: 0, y: 0, z:0})
-})
+  fireEvent.click(container.getByRole("button"));
+  expect(window.mod.rotation).toStrictEqual({ x: 0, y: 0, z: 0 });
+});
diff --git a/src/components/AstroPiModel/DefaultMZCriteria.js b/src/components/AstroPiModel/DefaultMZCriteria.js
index 96d355881..d8f0b47f4 100644
--- a/src/components/AstroPiModel/DefaultMZCriteria.js
+++ b/src/components/AstroPiModel/DefaultMZCriteria.js
@@ -5,5 +5,5 @@ export const defaultMZCriteria = {
   readHumidity: false,
   readPressure: false,
   readTemperature: false,
-  usedLEDs: false
-}
+  usedLEDs: false,
+};
diff --git a/src/components/AstroPiModel/FlightCase.js b/src/components/AstroPiModel/FlightCase.js
index 160ce76aa..b229e2d69 100644
--- a/src/components/AstroPiModel/FlightCase.js
+++ b/src/components/AstroPiModel/FlightCase.js
@@ -1,73 +1,77 @@
-import React from 'react';
-import * as THREE from 'three';
-import { useGLTF } from '@react-three/drei';
+import React from "react";
+import * as THREE from "three";
+import { useGLTF } from "@react-three/drei";
 import Sk from "skulpt";
-import { invalidate } from '@react-three/fiber';
+import { invalidate } from "@react-three/fiber";
 
 const FlightCase = () => {
+  const { scene } = useGLTF(
+    `${process.env.PUBLIC_URL}/models/raspi-compressed.glb`,
+  );
+  window.mod = scene;
 
-  const { scene } = useGLTF(`${process.env.PUBLIC_URL}/models/raspi-compressed.glb`)
-  window.mod = scene
-
-  const blankLED = new THREE.MeshStandardMaterial({color: `rgb(0,0,0)`})
+  const blankLED = new THREE.MeshStandardMaterial({ color: `rgb(0,0,0)` });
   var leds = {
-    '0_0_0': blankLED
-  }
+    "0_0_0": blankLED,
+  };
 
-  function setPixel(ledIndex,r,g,b) {
+  function setPixel(ledIndex, r, g, b) {
     var x = ledIndex % 8;
     var y = Math.floor(ledIndex / 8);
-    let ledMaterial
+    let ledMaterial;
     if (`${r}_${g}_${b}` in leds) {
-      ledMaterial = leds[`${r}_${g}_${b}`]
+      ledMaterial = leds[`${r}_${g}_${b}`];
     } else {
-      ledMaterial = new THREE.MeshStandardMaterial({color: `rgb(${r},${g},${b})`});
-      leds[`${r}_${g}_${b}`] = ledMaterial
+      ledMaterial = new THREE.MeshStandardMaterial({
+        color: `rgb(${r},${g},${b})`,
+      });
+      leds[`${r}_${g}_${b}`] = ledMaterial;
     }
-    var object = scene.getObjectByName(`circle${x}_${7-y}-1`);
+    var object = scene.getObjectByName(`circle${x}_${7 - y}-1`);
 
-    if(object != null){
+    if (object != null) {
       object.material = ledMaterial;
     }
   }
 
   function setPixels(indexes, pix) {
-    if(indexes == null){
-      indexes = Array.from(Array(8*8).keys())
+    if (indexes == null) {
+      indexes = Array.from(Array(8 * 8).keys());
     }
 
     var i = 0;
-    for (const ledIndex of indexes){
-      setPixel(ledIndex, pix[i][0], pix[i][1], pix[i][2])
+    for (const ledIndex of indexes) {
+      setPixel(ledIndex, pix[i][0], pix[i][1], pix[i][2]);
       i += 1;
     }
   }
 
-  Sk.sense_hat_emit = function(event, data) {
-
-    if (event && event === 'setpixel') {
+  Sk.sense_hat_emit = function (event, data) {
+    if (event && event === "setpixel") {
       // change the led
       const ledIndex = data;
-      const ledData  = Sk.sense_hat.pixels[ledIndex];
+      const ledData = Sk.sense_hat.pixels[ledIndex];
 
       // Convert LED-RGB to RGB565 // and then to RGB555
       Sk.sense_hat.pixels[ledIndex] = [
         ledData[0] & ~7,
         ledData[1] & ~3,
-        ledData[2] & ~7
+        ledData[2] & ~7,
       ];
 
-      setPixel(ledIndex, parseInt(ledData[0]*255), parseInt(ledData[1]*255), parseInt(ledData[2]*255));
-    }
-    else if (event && event === 'setpixels') {
+      setPixel(
+        ledIndex,
+        parseInt(ledData[0] * 255),
+        parseInt(ledData[1] * 255),
+        parseInt(ledData[2] * 255),
+      );
+    } else if (event && event === "setpixels") {
       setPixels(data, Sk.sense_hat.pixels);
     }
-    invalidate()
-  }
+    invalidate();
+  };
 
-  return (
-    <primitive object={scene} scale={4} />
-  )
-}
+  return <primitive object={scene} scale={4} />;
+};
 
-export default FlightCase
+export default FlightCase;
diff --git a/src/components/AstroPiModel/FlightCase.test.js b/src/components/AstroPiModel/FlightCase.test.js
index a7f87d15b..b0fbe1ef6 100644
--- a/src/components/AstroPiModel/FlightCase.test.js
+++ b/src/components/AstroPiModel/FlightCase.test.js
@@ -1,10 +1,8 @@
 import React from "react";
-import ReactThreeTestRenderer from '@react-three/test-renderer';
+import ReactThreeTestRenderer from "@react-three/test-renderer";
 
 import FlightCase from "./FlightCase";
 
 test("3D model loads and renders", async () => {
-  await ReactThreeTestRenderer.create(<FlightCase/>)
-})
-
-
+  await ReactThreeTestRenderer.create(<FlightCase />);
+});
diff --git a/src/components/AstroPiModel/Lighting.js b/src/components/AstroPiModel/Lighting.js
index d67f72909..5876b5a3d 100644
--- a/src/components/AstroPiModel/Lighting.js
+++ b/src/components/AstroPiModel/Lighting.js
@@ -1,19 +1,44 @@
-import React from 'react';
+import React from "react";
 
 const Lighting = () => {
-
-  return(
-    <>     
+  return (
+    <>
       <ambientLight intensity={0.25} />
-      <pointLight intensity={0.35} angle={28} penumbra={2} position={[0.418, 16.199, 0.300]} castShadow />
-      <pointLight position={[-16.116, 14.37, 8.208]} intensity={0.5} castShadow/>
-      <pointLight position={[-16.109, 18.021, -8.207]} intensity={0.5} castShadow/>
-      <pointLight position={[14.904, 12.198, -1.832]} intensity={0.17} castShadow/>
-      <pointLight position={[- 0.462, 8.89, 14.520]} intensity={0.43} castShadow/>
-      <pointLight position={[3.235, 11.486, - 12.541]} intensity={0.2} castShadow/>
-      <pointLight position={[0.0, -20.0, 0.0]} intensity={0.5} castShadow/>
+      <pointLight
+        intensity={0.35}
+        angle={28}
+        penumbra={2}
+        position={[0.418, 16.199, 0.3]}
+        castShadow
+      />
+      <pointLight
+        position={[-16.116, 14.37, 8.208]}
+        intensity={0.5}
+        castShadow
+      />
+      <pointLight
+        position={[-16.109, 18.021, -8.207]}
+        intensity={0.5}
+        castShadow
+      />
+      <pointLight
+        position={[14.904, 12.198, -1.832]}
+        intensity={0.17}
+        castShadow
+      />
+      <pointLight
+        position={[-0.462, 8.89, 14.52]}
+        intensity={0.43}
+        castShadow
+      />
+      <pointLight
+        position={[3.235, 11.486, -12.541]}
+        intensity={0.2}
+        castShadow
+      />
+      <pointLight position={[0.0, -20.0, 0.0]} intensity={0.5} castShadow />
     </>
-  )
-}
+  );
+};
 
-export default Lighting
+export default Lighting;
diff --git a/src/components/AstroPiModel/Lighting.test.js b/src/components/AstroPiModel/Lighting.test.js
index 375ee5589..5de81ab5b 100644
--- a/src/components/AstroPiModel/Lighting.test.js
+++ b/src/components/AstroPiModel/Lighting.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import ReactThreeTestRenderer from '@react-three/test-renderer';
+import ReactThreeTestRenderer from "@react-three/test-renderer";
 import Lighting from "./Lighting";
 
 test("Lighting component renders", async () => {
-  await ReactThreeTestRenderer.create(<Lighting/>)
-})
+  await ReactThreeTestRenderer.create(<Lighting />);
+});
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationPanel.js b/src/components/AstroPiModel/OrientationPanel/OrientationPanel.js
index 2114b9fda..43bf4da74 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationPanel.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationPanel.js
@@ -1,27 +1,35 @@
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import '../AstroPiModel.scss';
-import OrientationReading from './OrientationReading';
-import OrientationResetButton from './OrientationResetButton';
+import React from "react";
+import { useTranslation } from "react-i18next";
+import "../AstroPiModel.scss";
+import OrientationReading from "./OrientationReading";
+import OrientationResetButton from "./OrientationResetButton";
 
 const OrientationPanel = (props) => {
-
-  const { t } = useTranslation()
-  const {orientation, resetOrientation} = props
+  const { t } = useTranslation();
+  const { orientation, resetOrientation } = props;
 
   return (
     <div className="sense-hat-model-orientation">
       <div className="sense-hat-model-orientation__spacing"></div>
       <div className="sense-hat-model-orientation__values">
-        <OrientationReading name={t('output.senseHat.model.roll')} value={orientation[0]} />
-        <OrientationReading name={t('output.senseHat.model.pitch')} value={orientation[1]} />
-        <OrientationReading name={t('output.senseHat.model.yaw')} value={orientation[2]} />
+        <OrientationReading
+          name={t("output.senseHat.model.roll")}
+          value={orientation[0]}
+        />
+        <OrientationReading
+          name={t("output.senseHat.model.pitch")}
+          value={orientation[1]}
+        />
+        <OrientationReading
+          name={t("output.senseHat.model.yaw")}
+          value={orientation[2]}
+        />
       </div>
       <div className="sense-hat-model-orientation__reset-btn">
-        <OrientationResetButton resetOrientation={resetOrientation}/>
+        <OrientationResetButton resetOrientation={resetOrientation} />
       </div>
     </div>
-  )
+  );
 };
 
-export default OrientationPanel
+export default OrientationPanel;
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationPanel.test.js b/src/components/AstroPiModel/OrientationPanel/OrientationPanel.test.js
index 0492762f1..04f5e5d24 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationPanel.test.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationPanel.test.js
@@ -1,16 +1,21 @@
 import React from "react";
-import { render } from "@testing-library/react"
+import { render } from "@testing-library/react";
 import OrientationPanel from "./OrientationPanel";
 
 let panel;
-const resetFunction = jest.fn()
+const resetFunction = jest.fn();
 
 beforeAll(() => {
-  panel = render(<OrientationPanel orientation={[278, 84, 327]} resetOrientation={resetFunction}/>)
-})
+  panel = render(
+    <OrientationPanel
+      orientation={[278, 84, 327]}
+      resetOrientation={resetFunction}
+    />,
+  );
+});
 
 test("Renders roll, pitch and yaw values", () => {
-  expect(panel.queryByText("output.senseHat.model.roll: 278")).not.toBeNull()
-  expect(panel.queryByText("output.senseHat.model.pitch: 84")).not.toBeNull()
-  expect(panel.queryByText("output.senseHat.model.yaw: 327")).not.toBeNull()
-})
+  expect(panel.queryByText("output.senseHat.model.roll: 278")).not.toBeNull();
+  expect(panel.queryByText("output.senseHat.model.pitch: 84")).not.toBeNull();
+  expect(panel.queryByText("output.senseHat.model.yaw: 327")).not.toBeNull();
+});
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationReading.js b/src/components/AstroPiModel/OrientationPanel/OrientationReading.js
index 8a70116a6..939402b0d 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationReading.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationReading.js
@@ -1,14 +1,14 @@
-import React from 'react';
-import '../AstroPiModel.scss';
+import React from "react";
+import "../AstroPiModel.scss";
 
 const OrientationReading = (props) => {
-  const {name, value} = props
+  const { name, value } = props;
 
   return (
-      <span className="sense-hat-model-orientation__reading">
-        {name}: {Math.round(value)}
-      </span>
-  )
-}
+    <span className="sense-hat-model-orientation__reading">
+      {name}: {Math.round(value)}
+    </span>
+  );
+};
 
-export default OrientationReading
+export default OrientationReading;
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationReading.test.js b/src/components/AstroPiModel/OrientationPanel/OrientationReading.test.js
index 0e4d0ecd1..36acd69ae 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationReading.test.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationReading.test.js
@@ -1,17 +1,17 @@
 import React from "react";
-import { render } from "@testing-library/react"
+import { render } from "@testing-library/react";
 import OrientationReading from "./OrientationReading";
 
 let reading;
 
 beforeEach(() => {
-  reading = render(<OrientationReading name={"foo"} value={123.8}/>)
-})
+  reading = render(<OrientationReading name={"foo"} value={123.8} />);
+});
 
 test("Renders name", () => {
-  expect(reading.queryByText(/foo/)).not.toBeNull()
-})
+  expect(reading.queryByText(/foo/)).not.toBeNull();
+});
 
 test("Renders rounded value", () => {
-  expect(reading.queryByText(/124/)).not.toBeNull()
-})
+  expect(reading.queryByText(/124/)).not.toBeNull();
+});
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.js b/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.js
index 0da038da0..889eaf6fb 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.js
@@ -1,16 +1,15 @@
-import React from 'react';
-import '../AstroPiModel.scss';
-import { ResetIcon } from '../../../Icons';
+import React from "react";
+import "../AstroPiModel.scss";
+import { ResetIcon } from "../../../Icons";
 
 const OrientationResetButton = (props) => {
-
-  const {resetOrientation} = props;
+  const { resetOrientation } = props;
 
   return (
-    <button onClick={ e => resetOrientation(e)}>
-      <ResetIcon/>
+    <button onClick={(e) => resetOrientation(e)}>
+      <ResetIcon />
     </button>
-  )
-}
+  );
+};
 
-export default OrientationResetButton
+export default OrientationResetButton;
diff --git a/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.test.js b/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.test.js
index 260ae7562..0f9c37c86 100644
--- a/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.test.js
+++ b/src/components/AstroPiModel/OrientationPanel/OrientationResetButton.test.js
@@ -1,15 +1,17 @@
 import React from "react";
-import { render, fireEvent } from "@testing-library/react"
+import { render, fireEvent } from "@testing-library/react";
 import OrientationResetButton from "./OrientationResetButton";
 
 let resetButton;
-const resetFunction = jest.fn()
+const resetFunction = jest.fn();
 
 beforeEach(() => {
-  resetButton = render(<OrientationResetButton resetOrientation={resetFunction}/>)
-})
+  resetButton = render(
+    <OrientationResetButton resetOrientation={resetFunction} />,
+  );
+});
 
 test("Clicking button calls reset function", () => {
-  fireEvent.click(resetButton.getByRole("button"))
-  expect(resetFunction).toHaveBeenCalledTimes(1)
-})
+  fireEvent.click(resetButton.getByRole("button"));
+  expect(resetFunction).toHaveBeenCalledTimes(1);
+});
diff --git a/src/components/AstroPiModel/Simulator.js b/src/components/AstroPiModel/Simulator.js
index 7d008b6de..bd9d1d8fe 100644
--- a/src/components/AstroPiModel/Simulator.js
+++ b/src/components/AstroPiModel/Simulator.js
@@ -1,16 +1,16 @@
-import React from 'react';
-import * as THREE from 'three';
+import React from "react";
+import * as THREE from "three";
 import { ResizeObserver } from "@juggle/resize-observer";
 import { Canvas } from "@react-three/fiber";
 import { OrbitControls, PerspectiveCamera } from "@react-three/drei";
-import Lighting from './Lighting';
-import { Suspense } from 'react';
+import Lighting from "./Lighting";
+import { Suspense } from "react";
 
-import { extractRollPitchYaw } from '../../utils/Orientation';
-import FlightCase from './FlightCase'
-import './AstroPiModel.scss';
+import { extractRollPitchYaw } from "../../utils/Orientation";
+import FlightCase from "./FlightCase";
+import "./AstroPiModel.scss";
 
-var isDragging=false
+var isDragging = false;
 var targetRotationX = 0.5;
 var targetRotationY = 0.2;
 var mouseX = 0;
@@ -20,36 +20,39 @@ var mouseYOnMouseDown = 0;
 var windowHalfX = window.innerWidth / 2;
 var windowHalfY = window.innerHeight / 2;
 var slowingFactor = 0.25;
-const rotationScaleFactor = 0.00025
+const rotationScaleFactor = 0.00025;
 
 const Simulator = (props) => {
-  const {updateOrientation} = props
+  const { updateOrientation } = props;
 
   const handleDragStart = (e) => {
-    isDragging=true
+    isDragging = true;
     mouseXOnMouseDown = e.clientX - windowHalfX;
     mouseYOnMouseDown = e.clientY - windowHalfY;
-  }
+  };
   const handleDragStop = () => {
-    isDragging=false
-  }
+    isDragging = false;
+  };
 
   const dragModel = (e) => {
     mouseX = e.clientX - windowHalfX;
-    targetRotationX = ( mouseX - mouseXOnMouseDown ) * rotationScaleFactor;
+    targetRotationX = (mouseX - mouseXOnMouseDown) * rotationScaleFactor;
     mouseY = e.clientY - windowHalfY;
-    targetRotationY = ( mouseY - mouseYOnMouseDown ) * rotationScaleFactor;
-  
-    if(isDragging) {
-      window.mod.rotateOnWorldAxis(new THREE.Vector3(0, 0, -1), targetRotationX);
+    targetRotationY = (mouseY - mouseYOnMouseDown) * rotationScaleFactor;
+
+    if (isDragging) {
+      window.mod.rotateOnWorldAxis(
+        new THREE.Vector3(0, 0, -1),
+        targetRotationX,
+      );
       window.mod.rotateOnWorldAxis(new THREE.Vector3(1, 0, 0), targetRotationY);
       updateOrientation(
         extractRollPitchYaw(
-        window.mod.rotation.x,
-        window.mod.rotation.y,
-        window.mod.rotation.z
-        )
-      )
+          window.mod.rotation.x,
+          window.mod.rotation.y,
+          window.mod.rotation.z,
+        ),
+      );
       targetRotationY = targetRotationY * (1 - slowingFactor);
       targetRotationX = targetRotationX * (1 - slowingFactor);
     }
@@ -57,21 +60,32 @@ const Simulator = (props) => {
 
   return (
     <Canvas
-      frameloop='demand'
+      frameloop="demand"
       onPointerDown={handleDragStart}
       onPointerUp={handleDragStop}
       onPointerOut={handleDragStop}
       onPointerMove={dragModel}
-      resize={{polyfill: ResizeObserver}}
+      resize={{ polyfill: ResizeObserver }}
     >
       <Lighting />
       <Suspense fallback={null}>
-        <PerspectiveCamera makeDefault fov={25} near={1} far={20000} position={[0, 1.5, 0]} />
+        <PerspectiveCamera
+          makeDefault
+          fov={25}
+          near={1}
+          far={20000}
+          position={[0, 1.5, 0]}
+        />
         <FlightCase />
-        <OrbitControls enableRotate = {false} enablePan = {false} enableZoom = {false} enabled = {false} />
+        <OrbitControls
+          enableRotate={false}
+          enablePan={false}
+          enableZoom={false}
+          enabled={false}
+        />
       </Suspense>
     </Canvas>
-  )
+  );
 };
 
-export default Simulator
+export default Simulator;
diff --git a/src/components/AstroPiModel/Simulator.test.js b/src/components/AstroPiModel/Simulator.test.js
index 5480f4c12..d52708bd0 100644
--- a/src/components/AstroPiModel/Simulator.test.js
+++ b/src/components/AstroPiModel/Simulator.test.js
@@ -7,27 +7,27 @@ window.mod = {
   rotation: {
     x: 0,
     y: 0,
-    z: 0
-  }
-}
+    z: 0,
+  },
+};
 
 test("Three canvas renders", () => {
-  render(<Simulator/>)
-})
+  render(<Simulator />);
+});
 
 test("Moving pointer over model does not change orientation", () => {
-  const updateOrientation = jest.fn()
-  const simulator = render(<Simulator updateOrientation = {updateOrientation}/>)
-  const canvas = simulator.container.querySelector("canvas")
-  fireEvent.pointerMove(canvas)
-  expect(updateOrientation).not.toHaveBeenCalled()
-})
+  const updateOrientation = jest.fn();
+  const simulator = render(<Simulator updateOrientation={updateOrientation} />);
+  const canvas = simulator.container.querySelector("canvas");
+  fireEvent.pointerMove(canvas);
+  expect(updateOrientation).not.toHaveBeenCalled();
+});
 
 test("Dragging model changes orientation", async () => {
-  const updateOrientation = jest.fn()
-  const simulator = render(<Simulator updateOrientation = {updateOrientation}/>)
-  const canvas = simulator.container.querySelector("canvas")
-  fireEvent.pointerDown(canvas)
-  fireEvent.pointerMove(canvas)
-  expect(updateOrientation).toHaveBeenCalled()
-})
+  const updateOrientation = jest.fn();
+  const simulator = render(<Simulator updateOrientation={updateOrientation} />);
+  const canvas = simulator.container.querySelector("canvas");
+  fireEvent.pointerDown(canvas);
+  fireEvent.pointerMove(canvas);
+  expect(updateOrientation).toHaveBeenCalled();
+});
diff --git a/src/components/BetaBanner/BetaBanner.js b/src/components/BetaBanner/BetaBanner.js
index 28ca17500..c4383b29f 100644
--- a/src/components/BetaBanner/BetaBanner.js
+++ b/src/components/BetaBanner/BetaBanner.js
@@ -6,41 +6,56 @@ import { CloseIcon } from "../../Icons";
 import Button from "../Button/Button";
 import { showBetaModal } from "../Editor/EditorSlice";
 
-import './BetaBanner.scss'
+import "./BetaBanner.scss";
 
 const BetaBanner = () => {
-
-  const dispatch = useDispatch()
-  const { t } = useTranslation()
-  const [cookies, setCookie] = useCookies(['betaBannerDismissed'])
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
+  const [cookies, setCookie] = useCookies(["betaBannerDismissed"]);
 
   const closeBanner = () => {
-    setCookie('betaBannerDismissed', 'true', { path: '/' })
-  }
-  const showModal = () => { dispatch(showBetaModal()) }
-  const isShowing = !cookies.betaBannerDismissed
+    setCookie("betaBannerDismissed", "true", { path: "/" });
+  };
+  const showModal = () => {
+    dispatch(showBetaModal());
+  };
+  const isShowing = !cookies.betaBannerDismissed;
 
   const handleKeyDown = (e) => {
-    const enterKey = 13
-    const spaceKey = 32
+    const enterKey = 13;
+    const spaceKey = 32;
     if (e.keyCode === enterKey || e.keyCode === spaceKey) {
       e.preventDefault();
-      showModal()
+      showModal();
     }
-  }
+  };
 
-  return (
-    isShowing ? 
-      (<div className='editor-banner editor-banner--beta'>
-        <span className = 'editor-banner--beta__icon'>Beta</span>
-        <span className='editor-banner__message'>
-          {t('betaBanner.message')}
-          <span className='btn btn--tertiary editor-banner__link' onClick={showModal} tabIndex={0} role='button' onKeyDown={handleKeyDown}>{t('betaBanner.modalLink')}</span>
+  return isShowing ? (
+    <div className="editor-banner editor-banner--beta">
+      <span className="editor-banner--beta__icon">Beta</span>
+      <span className="editor-banner__message">
+        {t("betaBanner.message")}
+        <span
+          className="btn btn--tertiary editor-banner__link"
+          onClick={showModal}
+          tabIndex={0}
+          role="button"
+          onKeyDown={handleKeyDown}
+        >
+          {t("betaBanner.modalLink")}
         </span>
-        <Button className='btn--tertiary editor-banner__close-button' label={t('betaBanner.buttonLabel')} title={t('betaBanner.buttonLabel')} ButtonIcon={CloseIcon} onClickHandler={closeBanner} />
-      </div>)
-    : <></>
-  )
-}
+      </span>
+      <Button
+        className="btn--tertiary editor-banner__close-button"
+        label={t("betaBanner.buttonLabel")}
+        title={t("betaBanner.buttonLabel")}
+        ButtonIcon={CloseIcon}
+        onClickHandler={closeBanner}
+      />
+    </div>
+  ) : (
+    <></>
+  );
+};
 
-export default BetaBanner
+export default BetaBanner;
diff --git a/src/components/BetaBanner/BetaBanner.test.js b/src/components/BetaBanner/BetaBanner.test.js
index ee10b7482..d5508bab8 100644
--- a/src/components/BetaBanner/BetaBanner.test.js
+++ b/src/components/BetaBanner/BetaBanner.test.js
@@ -1,45 +1,44 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
-import { Cookies, CookiesProvider } from 'react-cookie';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
+import { Cookies, CookiesProvider } from "react-cookie";
 import BetaBanner from "./BetaBanner";
 
-let cookies
-let store
+let cookies;
+let store;
 
 beforeEach(() => {
   cookies = new Cookies();
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {}
-    store = mockStore(initialState);
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {};
+  store = mockStore(initialState);
   render(
     <CookiesProvider cookies={cookies}>
       <Provider store={store}>
         <BetaBanner />
       </Provider>
-    </CookiesProvider>
-  )
-})
+    </CookiesProvider>,
+  );
+});
 
-test('Banner shows', () => {
-  expect(screen.queryByText('betaBanner.message')).toBeInTheDocument()
-})
+test("Banner shows", () => {
+  expect(screen.queryByText("betaBanner.message")).toBeInTheDocument();
+});
 
-test('Clicking close button sets cookie', () => {
-  const closeButton = screen.getAllByRole('button').pop()
-  fireEvent.click(closeButton)
-  expect(cookies.cookies.betaBannerDismissed).toBe('true')
+test("Clicking close button sets cookie", () => {
+  const closeButton = screen.getAllByRole("button").pop();
+  fireEvent.click(closeButton);
+  expect(cookies.cookies.betaBannerDismissed).toBe("true");
+});
 
-})
-
-test('Clicking link dispatches modal action', () => {
-  const modalLink = screen.queryByText('betaBanner.modalLink')
-  fireEvent.click(modalLink)
-  expect(store.getActions()).toEqual([{type: 'editor/showBetaModal'}])
-})
+test("Clicking link dispatches modal action", () => {
+  const modalLink = screen.queryByText("betaBanner.modalLink");
+  fireEvent.click(modalLink);
+  expect(store.getActions()).toEqual([{ type: "editor/showBetaModal" }]);
+});
 
 afterEach(() => {
-  cookies.remove('betaBannerDismissed')
-})
+  cookies.remove("betaBannerDismissed");
+});
diff --git a/src/components/Callback.js b/src/components/Callback.js
index d50ab1f8d..590b72b08 100644
--- a/src/components/Callback.js
+++ b/src/components/Callback.js
@@ -1,30 +1,34 @@
 import React from "react";
 import { connect } from "react-redux";
 import { CallbackComponent } from "redux-oidc";
-import { useNavigate } from 'react-router-dom'
+import { useNavigate } from "react-router-dom";
 import userManager from "../utils/userManager";
 
 const Callback = () => {
-  let navigate = useNavigate()
+  let navigate = useNavigate();
 
-  const previousRoute = localStorage.getItem('location')
+  const previousRoute = localStorage.getItem("location");
 
   const onSuccess = () => {
-    localStorage.removeItem('location')
-    window.plausible('Login successful')
-    navigate(previousRoute)
-  }
+    localStorage.removeItem("location");
+    window.plausible("Login successful");
+    navigate(previousRoute);
+  };
 
   const onError = (error) => {
     navigate(previousRoute);
     console.error(error);
-  }
+  };
 
   return (
-    <CallbackComponent userManager={userManager} successCallback={onSuccess} errorCallback={(error) => onError(error)}>
+    <CallbackComponent
+      userManager={userManager}
+      successCallback={onSuccess}
+      errorCallback={(error) => onError(error)}
+    >
       <div>Redirecting...</div>
     </CallbackComponent>
   );
-}
+};
 
 export default connect()(Callback);
diff --git a/src/components/Editor/DraggableTabs/DraggableTab.js b/src/components/Editor/DraggableTabs/DraggableTab.js
index 785f2d1c9..4154400aa 100644
--- a/src/components/Editor/DraggableTabs/DraggableTab.js
+++ b/src/components/Editor/DraggableTabs/DraggableTab.js
@@ -4,41 +4,57 @@ import { useDispatch, useSelector } from "react-redux";
 import { Tab } from "react-tabs";
 import { setFocussedFileIndex } from "../EditorSlice";
 
-import './DraggableTabs.scss'
+import "./DraggableTabs.scss";
 
-const DraggableTab = ({children, panelIndex, fileIndex, ...otherProps}) => {
-  const openFiles = useSelector((state) => state.editor.openFiles)
-  const openFilesCount = openFiles[panelIndex].length
-  const dispatch = useDispatch()
+const DraggableTab = ({ children, panelIndex, fileIndex, ...otherProps }) => {
+  const openFiles = useSelector((state) => state.editor.openFiles);
+  const openFilesCount = openFiles[panelIndex].length;
+  const dispatch = useDispatch();
 
   const switchToFileTab = (panelIndex, fileIndex) => {
-    dispatch(setFocussedFileIndex({panelIndex, fileIndex}))
-  }
+    dispatch(setFocussedFileIndex({ panelIndex, fileIndex }));
+  };
 
   const onKeyPress = (e, panelIndex, fileIndex) => {
-    if (e.code === 'ArrowRight') {
-      switchToFileTab(panelIndex, (fileIndex + 1) % openFilesCount)
-    } else if (e.code === 'ArrowLeft') {
-      switchToFileTab(panelIndex, (fileIndex + openFilesCount - 1) % openFilesCount )
+    if (e.code === "ArrowRight") {
+      switchToFileTab(panelIndex, (fileIndex + 1) % openFilesCount);
+    } else if (e.code === "ArrowLeft") {
+      switchToFileTab(
+        panelIndex,
+        (fileIndex + openFilesCount - 1) % openFilesCount,
+      );
     }
-  }
-  
+  };
+
   return (
-    <Draggable  draggableId={`draggable${panelIndex}_${fileIndex}`} index={fileIndex}>
-      {({innerRef, draggableProps, dragHandleProps}) => (
-        <div className = 'draggable-tab' ref={innerRef} {...draggableProps} {...dragHandleProps} style={draggableProps.style}>
-          <Tab onClick = {(e) => {
-            e.stopPropagation()
-            switchToFileTab(panelIndex, fileIndex)
-          }} onKeyDown={e => onKeyPress(e, panelIndex, fileIndex)} {...otherProps} >
+    <Draggable
+      draggableId={`draggable${panelIndex}_${fileIndex}`}
+      index={fileIndex}
+    >
+      {({ innerRef, draggableProps, dragHandleProps }) => (
+        <div
+          className="draggable-tab"
+          ref={innerRef}
+          {...draggableProps}
+          {...dragHandleProps}
+          style={draggableProps.style}
+        >
+          <Tab
+            onClick={(e) => {
+              e.stopPropagation();
+              switchToFileTab(panelIndex, fileIndex);
+            }}
+            onKeyDown={(e) => onKeyPress(e, panelIndex, fileIndex)}
+            {...otherProps}
+          >
             {children}
           </Tab>
         </div>
       )}
     </Draggable>
-  )
+  );
 };
 
-DraggableTab.tabsRole = 'Tab'
+DraggableTab.tabsRole = "Tab";
 
-export default DraggableTab
+export default DraggableTab;
diff --git a/src/components/Editor/DraggableTabs/DraggableTab.test.js b/src/components/Editor/DraggableTabs/DraggableTab.test.js
index ee9237624..487a81de8 100644
--- a/src/components/Editor/DraggableTabs/DraggableTab.test.js
+++ b/src/components/Editor/DraggableTabs/DraggableTab.test.js
@@ -1,5 +1,5 @@
 import React from "react";
-import configureStore from 'redux-mock-store'
+import configureStore from "redux-mock-store";
 import { fireEvent, render, screen } from "@testing-library/react";
 import { Provider } from "react-redux";
 import DraggableTab from "./DraggableTab";
@@ -7,53 +7,69 @@ import DroppableTabList from "./DroppableTabList";
 import { DragDropContext } from "@hello-pangea/dnd";
 import { setFocussedFileIndex } from "../EditorSlice";
 
-describe('when tab is in focus', () => {
-  let store
+describe("when tab is in focus", () => {
+  let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              name: 'main',
-              extension: 'py',
-              content: 'print("hello")'
+              name: "main",
+              extension: "py",
+              content: 'print("hello")',
             },
             {
-              name: 'a',
-              extension: 'py',
-              content: '# Your code here'
-            }
-          ]
+              name: "a",
+              extension: "py",
+              content: "# Your code here",
+            },
+          ],
         },
-        openFiles: [['a.py', 'main.py', 'b.py']],
-        focussedFileIndices: [1]
+        openFiles: [["a.py", "main.py", "b.py"]],
+        focussedFileIndices: [1],
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><DragDropContext><DroppableTabList index={0}><DraggableTab panelIndex={0} fileIndex={1}>main.py</DraggableTab></DroppableTabList></DragDropContext></Provider>)
-  })
-  test('pressing right arrow key moves focus to right', () => {
-    const tab = screen.queryByText('main.py')
-    fireEvent.keyDown(tab, {code: 'ArrowRight'})
-    expect(store.getActions()).toEqual([setFocussedFileIndex({panelIndex: 0, fileIndex: 2})])
-  })
+    render(
+      <Provider store={store}>
+        <DragDropContext>
+          <DroppableTabList index={0}>
+            <DraggableTab panelIndex={0} fileIndex={1}>
+              main.py
+            </DraggableTab>
+          </DroppableTabList>
+        </DragDropContext>
+      </Provider>,
+    );
+  });
+  test("pressing right arrow key moves focus to right", () => {
+    const tab = screen.queryByText("main.py");
+    fireEvent.keyDown(tab, { code: "ArrowRight" });
+    expect(store.getActions()).toEqual([
+      setFocussedFileIndex({ panelIndex: 0, fileIndex: 2 }),
+    ]);
+  });
 
-  test('pressing left arrow key moves focus to left', () => {
-    const tab = screen.queryByText('main.py')
-    fireEvent.keyDown(tab, {code: 'ArrowLeft'})
-    expect(store.getActions()).toEqual([setFocussedFileIndex({panelIndex: 0, fileIndex: 0})])
-  })
+  test("pressing left arrow key moves focus to left", () => {
+    const tab = screen.queryByText("main.py");
+    fireEvent.keyDown(tab, { code: "ArrowLeft" });
+    expect(store.getActions()).toEqual([
+      setFocussedFileIndex({ panelIndex: 0, fileIndex: 0 }),
+    ]);
+  });
 
-  test('clicking tab switches focus to it', () => {
-    const tab = screen.queryByText('main.py')
-    fireEvent.click(tab)
-    expect(store.getActions()).toEqual([setFocussedFileIndex({panelIndex: 0, fileIndex: 1})])
-  })
-})
+  test("clicking tab switches focus to it", () => {
+    const tab = screen.queryByText("main.py");
+    fireEvent.click(tab);
+    expect(store.getActions()).toEqual([
+      setFocussedFileIndex({ panelIndex: 0, fileIndex: 1 }),
+    ]);
+  });
+});
diff --git a/src/components/Editor/DraggableTabs/DroppableTabList.js b/src/components/Editor/DraggableTabs/DroppableTabList.js
index 837bb59a2..0839e73f7 100644
--- a/src/components/Editor/DraggableTabs/DroppableTabList.js
+++ b/src/components/Editor/DraggableTabs/DroppableTabList.js
@@ -1,24 +1,28 @@
-import React from "react"
-import { Droppable } from "@hello-pangea/dnd"
-import { TabList } from "react-tabs"
+import React from "react";
+import { Droppable } from "@hello-pangea/dnd";
+import { TabList } from "react-tabs";
 
-import './DraggableTabs.scss'
+import "./DraggableTabs.scss";
 
-const DroppableTabList = ({children, index, ...otherProps}) => {
+const DroppableTabList = ({ children, index, ...otherProps }) => {
   return (
-    <TabList {...otherProps }>
-      <Droppable direction='horizontal' droppableId={index.toString()}>
-        {({innerRef, droppableProps, placeholder}) => (
-          <div className = 'droppable-tab-list' {...droppableProps} ref={innerRef}>
+    <TabList {...otherProps}>
+      <Droppable direction="horizontal" droppableId={index.toString()}>
+        {({ innerRef, droppableProps, placeholder }) => (
+          <div
+            className="droppable-tab-list"
+            {...droppableProps}
+            ref={innerRef}
+          >
             {children}
             {placeholder}
           </div>
         )}
       </Droppable>
     </TabList>
-  )
-}
+  );
+};
 
-DroppableTabList.tabsRole = 'TabList'
+DroppableTabList.tabsRole = "TabList";
 
-export default DroppableTabList
+export default DroppableTabList;
diff --git a/src/components/Editor/DraggableTabs/DroppableTabList.test.js b/src/components/Editor/DraggableTabs/DroppableTabList.test.js
index c0e3aa39f..9e5b3024b 100644
--- a/src/components/Editor/DraggableTabs/DroppableTabList.test.js
+++ b/src/components/Editor/DraggableTabs/DroppableTabList.test.js
@@ -4,9 +4,13 @@ import { render, screen } from "@testing-library/react";
 import { DragDropContext } from "@hello-pangea/dnd";
 
 beforeEach(() => {
-  render(<DragDropContext><DroppableTabList index={0}>hello</DroppableTabList></DragDropContext>)
-})
+  render(
+    <DragDropContext>
+      <DroppableTabList index={0}>hello</DroppableTabList>
+    </DragDropContext>,
+  );
+});
 
-test('Renders', () => {
-  expect(screen.queryByText('hello')).toBeInTheDocument()
-})
+test("Renders", () => {
+  expect(screen.queryByText("hello")).toBeInTheDocument();
+});
diff --git a/src/components/Editor/Editor.js b/src/components/Editor/Editor.js
index da0b1b731..ecaeea871 100644
--- a/src/components/Editor/Editor.js
+++ b/src/components/Editor/Editor.js
@@ -1,17 +1,17 @@
 // import './editor.css'
-import React, { useRef, useEffect } from 'react';
-import { useSelector, useDispatch } from 'react-redux'
-import { update } from './EditorSlice'
+import React, { useRef, useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { update } from "./EditorSlice";
 
-import { EditorState, basicSetup } from '@codemirror/basic-setup';
-import { EditorView, keymap } from '@codemirror/view';
-import { defaultKeymap } from '@codemirror/commands';
-import { python } from '@codemirror/lang-python';
+import { EditorState, basicSetup } from "@codemirror/basic-setup";
+import { EditorView, keymap } from "@codemirror/view";
+import { defaultKeymap } from "@codemirror/commands";
+import { python } from "@codemirror/lang-python";
 
 function Editor() {
   const editor = useRef();
-  const code = useSelector((state) => state.editor.code)
-  const dispatch = useDispatch()
+  const code = useSelector((state) => state.editor.code);
+  const dispatch = useDispatch();
 
   const onUpdate = EditorView.updateListener.of((v) => {
     dispatch(update(v.state.doc.toString()));
@@ -20,12 +20,7 @@ function Editor() {
   useEffect(() => {
     const startState = EditorState.create({
       doc: code,
-      extensions: [
-        basicSetup,
-        keymap.of(defaultKeymap),
-        python(),
-        onUpdate,
-      ],
+      extensions: [basicSetup, keymap.of(defaultKeymap), python(), onUpdate],
     });
 
     const view = new EditorView({ state: startState, parent: editor.current });
diff --git a/src/components/Editor/EditorInput/EditorInput.js b/src/components/Editor/EditorInput/EditorInput.js
index e80aea9da..6e5eb3d1e 100644
--- a/src/components/Editor/EditorInput/EditorInput.js
+++ b/src/components/Editor/EditorInput/EditorInput.js
@@ -1,81 +1,111 @@
-import React, { createRef, useEffect, useRef, useState } from 'react'
-import { DragDropContext } from '@hello-pangea/dnd'
-import { useDispatch, useSelector } from 'react-redux'
-import { TabPanel, Tabs } from 'react-tabs'
-import classNames from 'classnames';
+import React, { createRef, useEffect, useRef, useState } from "react";
+import { DragDropContext } from "@hello-pangea/dnd";
+import { useDispatch, useSelector } from "react-redux";
+import { TabPanel, Tabs } from "react-tabs";
+import classNames from "classnames";
 
-import { closeFile, setFocussedFileIndex, setOpenFiles } from '../EditorSlice'
-import Button from '../../Button/Button'
-import { CloseIcon } from '../../../Icons'
-import EditorPanel from '../EditorPanel/EditorPanel'
-import DraggableTab from '../DraggableTabs/DraggableTab'
-import DroppableTabList from '../DraggableTabs/DroppableTabList'
-import RunBar from '../../RunButton/RunBar'
+import { closeFile, setFocussedFileIndex, setOpenFiles } from "../EditorSlice";
+import Button from "../../Button/Button";
+import { CloseIcon } from "../../../Icons";
+import EditorPanel from "../EditorPanel/EditorPanel";
+import DraggableTab from "../DraggableTabs/DraggableTab";
+import DroppableTabList from "../DraggableTabs/DroppableTabList";
+import RunBar from "../../RunButton/RunBar";
 
-import './EditorInput.scss'
+import "./EditorInput.scss";
 
 const EditorInput = () => {
-  const project = useSelector((state) => state.editor.project)
-  const openFiles = useSelector((state) => state.editor.openFiles)
-  const focussedFileIndices = useSelector((state) => state.editor.focussedFileIndices)
-  const dispatch = useDispatch()
+  const project = useSelector((state) => state.editor.project);
+  const openFiles = useSelector((state) => state.editor.openFiles);
+  const focussedFileIndices = useSelector(
+    (state) => state.editor.focussedFileIndices,
+  );
+  const dispatch = useDispatch();
 
   const onDragStart = (input) => {
-    const { source } = input
-    dispatch(setFocussedFileIndex({panelIndex: parseInt(source.droppableId), fileIndex: source.index}))
-  }
+    const { source } = input;
+    dispatch(
+      setFocussedFileIndex({
+        panelIndex: parseInt(source.droppableId),
+        fileIndex: source.index,
+      }),
+    );
+  };
 
   const onDragEnd = (result) => {
-    const { source, destination } = result
-    if (!destination) return
+    const { source, destination } = result;
+    if (!destination) return;
 
-    let openFilesData = [...openFiles]
-    let oldPane = [...openFilesData[source.droppableId]]
-    const [removed] = oldPane.splice(source.index, 1)
-    openFilesData[source.droppableId] = [...oldPane]
+    let openFilesData = [...openFiles];
+    let oldPane = [...openFilesData[source.droppableId]];
+    const [removed] = oldPane.splice(source.index, 1);
+    openFilesData[source.droppableId] = [...oldPane];
 
-    let newPane = [...openFilesData[destination.droppableId]]
-    newPane.splice(destination.index, 0, removed)
-    openFilesData[destination.droppableId] = [...newPane]
-    dispatch(setOpenFiles(openFilesData))
-    dispatch(setFocussedFileIndex({panelIndex: parseInt(destination.droppableId), fileIndex: destination.index}))
+    let newPane = [...openFilesData[destination.droppableId]];
+    newPane.splice(destination.index, 0, removed);
+    openFilesData[destination.droppableId] = [...newPane];
+    dispatch(setOpenFiles(openFilesData));
+    dispatch(
+      setFocussedFileIndex({
+        panelIndex: parseInt(destination.droppableId),
+        fileIndex: destination.index,
+      }),
+    );
     if (destination.droppableId !== source.droppableId) {
-      dispatch(setFocussedFileIndex({panelIndex: parseInt(source.droppableId), fileIndex: Math.max(source.index - 1, 0)}))
+      dispatch(
+        setFocussedFileIndex({
+          panelIndex: parseInt(source.droppableId),
+          fileIndex: Math.max(source.index - 1, 0),
+        }),
+      );
     }
-  }
+  };
 
   const closeFileTab = (e, fileName) => {
-    e.stopPropagation()
-    dispatch(closeFile(fileName))
-  }
+    e.stopPropagation();
+    dispatch(closeFile(fileName));
+  };
 
-  const [numberOfComponents, setNumberOfComponents] = useState(project.components.length)
-  let tabRefs = useRef(project.components.map(createRef))
+  const [numberOfComponents, setNumberOfComponents] = useState(
+    project.components.length,
+  );
+  let tabRefs = useRef(project.components.map(createRef));
 
   useEffect(() => {
-    setNumberOfComponents(project.components.length)
-    Array(project.components.length).fill().forEach((_, i) => {
-      tabRefs.current[i] = tabRefs.current[i] || React.createRef();
-    })
-  }, [project])
+    setNumberOfComponents(project.components.length);
+    Array(project.components.length)
+      .fill()
+      .forEach((_, i) => {
+        tabRefs.current[i] = tabRefs.current[i] || React.createRef();
+      });
+  }, [project]);
 
   useEffect(() => {
     focussedFileIndices.forEach((index, i) => {
-      const fileName = openFiles[i][index]
-      const componentIndex = project.components.findIndex(file => `${file.name}.${file.extension}`=== fileName)
-      const fileRef = tabRefs.current[componentIndex]
+      const fileName = openFiles[i][index];
+      const componentIndex = project.components.findIndex(
+        (file) => `${file.name}.${file.extension}` === fileName,
+      );
+      const fileRef = tabRefs.current[componentIndex];
       if (fileRef && fileRef.current) {
-        fileRef.current.parentElement.scrollIntoView()
+        fileRef.current.parentElement.scrollIntoView();
       }
-    })
-  }, [focussedFileIndices, openFiles, numberOfComponents, project])
+    });
+  }, [focussedFileIndices, openFiles, numberOfComponents, project]);
 
   return (
-    <DragDropContext onDragStart={input => onDragStart(input)} onDragEnd={result => onDragEnd(result)}>
-      <div className = 'editor-input'>
+    <DragDropContext
+      onDragStart={(input) => onDragStart(input)}
+      onDragEnd={(result) => onDragEnd(result)}
+    >
+      <div className="editor-input">
         {openFiles.map((panel, panelIndex) => (
-          <Tabs key={panelIndex} selectedIndex={focussedFileIndices[panelIndex]} onSelect={() => {}}>
-            <div className='react-tabs__tab-container'>
+          <Tabs
+            key={panelIndex}
+            selectedIndex={focussedFileIndices[panelIndex]}
+            onSelect={() => {}}
+          >
+            <div className="react-tabs__tab-container">
               <DroppableTabList index={panelIndex}>
                 {panel.map((fileName, fileIndex) => (
                   <DraggableTab
@@ -84,17 +114,31 @@ const EditorInput = () => {
                     panelIndex={panelIndex}
                   >
                     <span
-                      className={classNames(
-                        'react-tabs__tab-inner',
-                        {'react-tabs__tab-inner--split': !["main.py", "index.html"].includes(fileName)}
-                      )}
-                      ref={tabRefs.current[project.components.findIndex(file => `${file.name}.${file.extension}`===fileName)]}
+                      className={classNames("react-tabs__tab-inner", {
+                        "react-tabs__tab-inner--split": ![
+                          "main.py",
+                          "index.html",
+                        ].includes(fileName),
+                      })}
+                      ref={
+                        tabRefs.current[
+                          project.components.findIndex(
+                            (file) =>
+                              `${file.name}.${file.extension}` === fileName,
+                          )
+                        ]
+                      }
                     >
                       {fileName}
-                      {!["main.py", "index.html"].includes(fileName) ?
-                        <Button className='btn--tertiary react-tabs__tab-inner-close-btn' label='close' onKeyDown={(e) => e.stopPropagation()} onClickHandler={(e) => closeFileTab(e, fileName)} ButtonIcon={() => <CloseIcon scaleFactor={0.85}/> }/>
-                      : null
-                      }
+                      {!["main.py", "index.html"].includes(fileName) ? (
+                        <Button
+                          className="btn--tertiary react-tabs__tab-inner-close-btn"
+                          label="close"
+                          onKeyDown={(e) => e.stopPropagation()}
+                          onClickHandler={(e) => closeFileTab(e, fileName)}
+                          ButtonIcon={() => <CloseIcon scaleFactor={0.85} />}
+                        />
+                      ) : null}
                     </span>
                   </DraggableTab>
                 ))}
@@ -102,7 +146,10 @@ const EditorInput = () => {
             </div>
             {panel.map((fileName, i) => (
               <TabPanel key={i}>
-                <EditorPanel fileName={fileName.split('.')[0]} extension={fileName.split('.').slice(1).join('.')} />
+                <EditorPanel
+                  fileName={fileName.split(".")[0]}
+                  extension={fileName.split(".").slice(1).join(".")}
+                />
               </TabPanel>
             ))}
             <RunBar />
@@ -110,6 +157,6 @@ const EditorInput = () => {
         ))}
       </div>
     </DragDropContext>
-  )
-}
-export default EditorInput
+  );
+};
+export default EditorInput;
diff --git a/src/components/Editor/EditorInput/EditorInput.test.js b/src/components/Editor/EditorInput/EditorInput.test.js
index 110881f35..0b7d82c38 100644
--- a/src/components/Editor/EditorInput/EditorInput.test.js
+++ b/src/components/Editor/EditorInput/EditorInput.test.js
@@ -1,82 +1,111 @@
-import React from "react"
-import configureStore from 'redux-mock-store'
-import EditorInput from "./EditorInput"
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from "react-redux"
-import { closeFile, setFocussedFileIndex, setOpenFiles } from "../EditorSlice"
+import React from "react";
+import configureStore from "redux-mock-store";
+import EditorInput from "./EditorInput";
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import { closeFile, setFocussedFileIndex, setOpenFiles } from "../EditorSlice";
 
-window.HTMLElement.prototype.scrollIntoView = jest.fn()
+window.HTMLElement.prototype.scrollIntoView = jest.fn();
 
-describe('Tab interactions', () => {
-  let store
+describe("Tab interactions", () => {
+  let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              name: 'main',
-              extension: 'py',
-              content: 'print("hello")'
+              name: "main",
+              extension: "py",
+              content: 'print("hello")',
             },
             {
-              name: 'a',
-              extension: 'py',
-              content: '# Your code here'
-            }
-          ]
+              name: "a",
+              extension: "py",
+              content: "# Your code here",
+            },
+          ],
         },
-        openFiles: [['main.py', 'a.py']],
-        focussedFileIndices: [1]
+        openFiles: [["main.py", "a.py"]],
+        focussedFileIndices: [1],
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id="app"><EditorInput/></div></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <EditorInput />
+        </div>
+      </Provider>,
+    );
+  });
 
   test("Renders content of focussed file", () => {
-    expect(screen.queryByText('# Your code here')).toBeInTheDocument()
-  })
+    expect(screen.queryByText("# Your code here")).toBeInTheDocument();
+  });
 
   test("Scrolls focussed file into view", () => {
-    expect(window.HTMLElement.prototype.scrollIntoView).toHaveBeenCalled()
-  })
+    expect(window.HTMLElement.prototype.scrollIntoView).toHaveBeenCalled();
+  });
 
-  test('Clicking the file close button dispatches close action', () => {
-    const closeButton = screen.queryAllByRole('button')[2]
-    fireEvent.click(closeButton)
-    expect(store.getActions()).toEqual([closeFile('a.py')])
-  })
+  test("Clicking the file close button dispatches close action", () => {
+    const closeButton = screen.queryAllByRole("button")[2];
+    fireEvent.click(closeButton);
+    expect(store.getActions()).toEqual([closeFile("a.py")]);
+  });
 
-  test('Focusses tab when dragged', async () => {
-    const tab = screen.queryByText('main.py').parentElement.parentElement
-    fireEvent.keyDown(tab, {key: ' ', keyCode: 32, code: 'Space'})
-    await waitFor(() => expect(store.getActions()).toEqual([setFocussedFileIndex({panelIndex: 0, fileIndex: 0})]))
-  })
+  test("Focusses tab when dragged", async () => {
+    const tab = screen.queryByText("main.py").parentElement.parentElement;
+    fireEvent.keyDown(tab, { key: " ", keyCode: 32, code: "Space" });
+    await waitFor(() =>
+      expect(store.getActions()).toEqual([
+        setFocussedFileIndex({ panelIndex: 0, fileIndex: 0 }),
+      ]),
+    );
+  });
 
-  test('moves tab correctly when dropped', async () => {
-    const tab = screen.queryByText('main.py').parentElement.parentElement
-    fireEvent.keyDown(tab, {key: ' ', keyCode: 32, code: 'Space'})
-    fireEvent.keyDown(tab, {key: 'ArrowRight', keyCode: 39, code: 'ArrowRight'})
-    fireEvent.keyDown(tab, {key: ' ', keyCode: 32, code: 'Space'})
+  test("moves tab correctly when dropped", async () => {
+    const tab = screen.queryByText("main.py").parentElement.parentElement;
+    fireEvent.keyDown(tab, { key: " ", keyCode: 32, code: "Space" });
+    fireEvent.keyDown(tab, {
+      key: "ArrowRight",
+      keyCode: 39,
+      code: "ArrowRight",
+    });
+    fireEvent.keyDown(tab, { key: " ", keyCode: 32, code: "Space" });
 
-    const moveTabAction = setOpenFiles([['a.py', 'main.py']])
-    await waitFor(() => expect(store.getActions()).toEqual(expect.arrayContaining([moveTabAction])))
-  })
+    const moveTabAction = setOpenFiles([["a.py", "main.py"]]);
+    await waitFor(() =>
+      expect(store.getActions()).toEqual(
+        expect.arrayContaining([moveTabAction]),
+      ),
+    );
+  });
 
-  test('focusses dropped tab', async () => {
-    const tab = screen.queryByText('main.py').parentElement.parentElement
-    fireEvent.keyDown(tab, {key: ' ', keyCode: 32, code: 'Space'})
-    fireEvent.keyDown(tab, {key: 'ArrowRight', keyCode: 39, code: 'ArrowRight'})
-    fireEvent.keyDown(tab, {key: ' ', keyCode: 32, code: 'Space'})
+  test("focusses dropped tab", async () => {
+    const tab = screen.queryByText("main.py").parentElement.parentElement;
+    fireEvent.keyDown(tab, { key: " ", keyCode: 32, code: "Space" });
+    fireEvent.keyDown(tab, {
+      key: "ArrowRight",
+      keyCode: 39,
+      code: "ArrowRight",
+    });
+    fireEvent.keyDown(tab, { key: " ", keyCode: 32, code: "Space" });
 
-    const switchFocusAction = setFocussedFileIndex({panelIndex: 0, fileIndex: 1})
-    await waitFor(() => expect(store.getActions()).toEqual(expect.arrayContaining([switchFocusAction])))
-  })
-})
+    const switchFocusAction = setFocussedFileIndex({
+      panelIndex: 0,
+      fileIndex: 1,
+    });
+    await waitFor(() =>
+      expect(store.getActions()).toEqual(
+        expect.arrayContaining([switchFocusAction]),
+      ),
+    );
+  });
+});
diff --git a/src/components/Editor/EditorPanel/EditorPanel.js b/src/components/Editor/EditorPanel/EditorPanel.js
index 0dadaa9c5..8f89e2e87 100644
--- a/src/components/Editor/EditorPanel/EditorPanel.js
+++ b/src/components/Editor/EditorPanel/EditorPanel.js
@@ -1,64 +1,74 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import './EditorPanel.scss'
-import React, { useRef, useEffect, useContext } from 'react';
-import { useSelector, useDispatch } from 'react-redux'
-import { updateProjectComponent } from '../EditorSlice'
-import { useCookies } from 'react-cookie';
+import "./EditorPanel.scss";
+import React, { useRef, useEffect, useContext } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { updateProjectComponent } from "../EditorSlice";
+import { useCookies } from "react-cookie";
 import { useTranslation } from "react-i18next";
-import { basicSetup } from 'codemirror'
-import { EditorView, keymap } from '@codemirror/view'
-import { EditorState } from '@codemirror/state'
-import { defaultKeymap, indentWithTab } from '@codemirror/commands'
-import { indentationMarkers } from '@replit/codemirror-indentation-markers'
-import { indentUnit } from '@codemirror/language';
+import { basicSetup } from "codemirror";
+import { EditorView, keymap } from "@codemirror/view";
+import { EditorState } from "@codemirror/state";
+import { defaultKeymap, indentWithTab } from "@codemirror/commands";
+import { indentationMarkers } from "@replit/codemirror-indentation-markers";
+import { indentUnit } from "@codemirror/language";
 
-import { html } from '@codemirror/lang-html'
-import { css } from '@codemirror/lang-css'
-import { python } from '@codemirror/lang-python'
+import { html } from "@codemirror/lang-html";
+import { css } from "@codemirror/lang-css";
+import { python } from "@codemirror/lang-python";
 
-import { editorLightTheme } from '../editorLightTheme'
-import { editorDarkTheme } from '../editorDarkTheme'
-import { SettingsContext } from '../../../settings';
+import { editorLightTheme } from "../editorLightTheme";
+import { editorDarkTheme } from "../editorDarkTheme";
+import { SettingsContext } from "../../../settings";
 
-const EditorPanel = ({
-  extension = 'html',
-  fileName = 'index'
-}) => {
+const EditorPanel = ({ extension = "html", fileName = "index" }) => {
   const editor = useRef();
   const project = useSelector((state) => state.editor.project);
-  const [cookies] = useCookies(['theme', 'fontSize'])
+  const [cookies] = useCookies(["theme", "fontSize"]);
   const dispatch = useDispatch();
   const { t } = useTranslation();
-  const settings = useContext(SettingsContext)
+  const settings = useContext(SettingsContext);
 
   const updateStoredProject = (content) => {
-    dispatch(updateProjectComponent({ extension: extension, name: fileName, code: content}));
-  }
+    dispatch(
+      updateProjectComponent({
+        extension: extension,
+        name: fileName,
+        code: content,
+      }),
+    );
+  };
 
-  const label = EditorView.contentAttributes.of({ 'aria-label': t('editorPanel.ariaLabel') });
+  const label = EditorView.contentAttributes.of({
+    "aria-label": t("editorPanel.ariaLabel"),
+  });
   const onUpdate = EditorView.updateListener.of((viewUpdate) => {
-    if(viewUpdate.docChanged) {
+    if (viewUpdate.docChanged) {
       updateStoredProject(viewUpdate.state.doc.toString());
     }
   });
 
   const getMode = () => {
     switch (extension) {
-      case 'html':
+      case "html":
         return html();
-      case 'css':
+      case "css":
         return css();
-      case 'py':
+      case "py":
         return python();
       default:
         return html();
     }
-  }
-  const isDarkMode = cookies.theme==="dark" || (!cookies.theme && window.matchMedia("(prefers-color-scheme:dark)").matches)
-  const editorTheme = isDarkMode ? editorDarkTheme : editorLightTheme
+  };
+  const isDarkMode =
+    cookies.theme === "dark" ||
+    (!cookies.theme &&
+      window.matchMedia("(prefers-color-scheme:dark)").matches);
+  const editorTheme = isDarkMode ? editorDarkTheme : editorLightTheme;
 
   useEffect(() => {
-    const code = project.components.find(item => item.extension === extension && item.name === fileName).content;
+    const code = project.components.find(
+      (item) => item.extension === extension && item.name === fileName,
+    ).content;
     const mode = getMode();
     const startState = EditorState.create({
       doc: code,
@@ -70,7 +80,7 @@ const EditorPanel = ({
         onUpdate,
         editorTheme,
         indentationMarkers(),
-        indentUnit.of('    '),
+        indentUnit.of("    "),
       ],
     });
 
@@ -81,12 +91,13 @@ const EditorPanel = ({
     });
 
     // 'aria-hidden' to fix keyboard access accessibility error
-    view.scrollDOM.setAttribute('aria-hidden', 'true')
+    view.scrollDOM.setAttribute("aria-hidden", "true");
 
     // Add alt text to hidden images to fix accessibility error
-    const hiddenImages = view.contentDOM.getElementsByClassName('cm-widgetBuffer');
+    const hiddenImages =
+      view.contentDOM.getElementsByClassName("cm-widgetBuffer");
     for (let img of hiddenImages) {
-      img.setAttribute('role', 'presentation')
+      img.setAttribute("role", "presentation");
     }
 
     return () => {
@@ -97,6 +108,6 @@ const EditorPanel = ({
   return (
     <div className={`editor editor--${settings.fontSize}`} ref={editor}></div>
   );
-}
+};
 
 export default EditorPanel;
diff --git a/src/components/Editor/EditorPanel/EditorPanel.test.js b/src/components/Editor/EditorPanel/EditorPanel.test.js
index cc879ba17..c18c5c953 100644
--- a/src/components/Editor/EditorPanel/EditorPanel.test.js
+++ b/src/components/Editor/EditorPanel/EditorPanel.test.js
@@ -1,45 +1,44 @@
-import configureStore from 'redux-mock-store'
-import { Provider } from "react-redux"
-import { SettingsContext } from "../../../settings"
-import { render } from '@testing-library/react'
-import { axe, toHaveNoViolations }from 'jest-axe'
-import EditorPanel from './EditorPanel'
+import configureStore from "redux-mock-store";
+import { Provider } from "react-redux";
+import { SettingsContext } from "../../../settings";
+import { render } from "@testing-library/react";
+import { axe, toHaveNoViolations } from "jest-axe";
+import EditorPanel from "./EditorPanel";
 
-expect.extend(toHaveNoViolations)
+expect.extend(toHaveNoViolations);
 
-describe('When font size is set', () => {
+describe("When font size is set", () => {
+  let editor;
 
-  let editor
-  
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
-          components: [
-            {name: 'main', extension: 'py', content: ''}
-          ]
-        }
-      }
-    }
+          components: [{ name: "main", extension: "py", content: "" }],
+        },
+      },
+    };
     const store = mockStore(initialState);
     const editorContainer = render(
       <Provider store={store}>
-        <SettingsContext.Provider value={{ theme: 'dark', fontSize: 'myFontSize' }}>
-          <EditorPanel fileName='main' extension='py'/>
+        <SettingsContext.Provider
+          value={{ theme: "dark", fontSize: "myFontSize" }}
+        >
+          <EditorPanel fileName="main" extension="py" />
         </SettingsContext.Provider>
-      </Provider>
-    )
-    editor = editorContainer.container.querySelector('.editor')
-  })
+      </Provider>,
+    );
+    editor = editorContainer.container.querySelector(".editor");
+  });
 
-  test('Font size class is set correctly', () => {
-    expect(editor).toHaveClass("editor--myFontSize")
-  })
+  test("Font size class is set correctly", () => {
+    expect(editor).toHaveClass("editor--myFontSize");
+  });
 
-  test('Editor panel has no AXE violations', async () => {
-    const axeResults = await axe(editor)
-    expect(axeResults).toHaveNoViolations()
-  })
-})
+  test("Editor panel has no AXE violations", async () => {
+    const axeResults = await axe(editor);
+    expect(axeResults).toHaveNoViolations();
+  });
+});
diff --git a/src/components/Editor/EditorSlice.js b/src/components/Editor/EditorSlice.js
index f6e19d4df..c9dbc4dac 100644
--- a/src/components/Editor/EditorSlice.js
+++ b/src/components/Editor/EditorSlice.js
@@ -13,7 +13,7 @@ export const syncProject = (actionName) =>
     `editor/${actionName}Project`,
     async (
       { project, identifier, locale, accessToken, autosave },
-      { rejectWithValue }
+      { rejectWithValue },
     ) => {
       let response;
       switch (actionName) {
@@ -52,7 +52,7 @@ export const syncProject = (actionName) =>
           return false;
         }
       },
-    }
+    },
   );
 
 export const loadProjectList = createAsyncThunk(
@@ -64,7 +64,7 @@ export const loadProjectList = createAsyncThunk(
       page,
       links: parseLinkHeader(response.headers.link),
     };
-  }
+  },
 );
 
 export const EditorSlice = createSlice({
@@ -110,32 +110,42 @@ export const EditorSlice = createSlice({
   },
   reducers: {
     closeFile: (state, action) => {
-      const panelIndex = state.openFiles.map((fileNames) => fileNames.includes(action.payload)).indexOf(true)
-      const closedFileIndex = state.openFiles[panelIndex].indexOf(action.payload)
-      state.openFiles[panelIndex] = state.openFiles[panelIndex].filter(fileName => fileName !== action.payload)
+      const panelIndex = state.openFiles
+        .map((fileNames) => fileNames.includes(action.payload))
+        .indexOf(true);
+      const closedFileIndex = state.openFiles[panelIndex].indexOf(
+        action.payload,
+      );
+      state.openFiles[panelIndex] = state.openFiles[panelIndex].filter(
+        (fileName) => fileName !== action.payload,
+      );
       if (
-        state.focussedFileIndices[panelIndex] >= state.openFiles[panelIndex].length ||
+        state.focussedFileIndices[panelIndex] >=
+          state.openFiles[panelIndex].length ||
         closedFileIndex < state.focussedFileIndices[panelIndex]
       ) {
-        state.focussedFileIndices[panelIndex]--
+        state.focussedFileIndices[panelIndex]--;
       }
     },
     openFile: (state, action) => {
-      const firstPanelIndex = 0
+      const firstPanelIndex = 0;
       if (!state.openFiles.flat().includes(action.payload)) {
-        state.openFiles[firstPanelIndex].push(action.payload)
+        state.openFiles[firstPanelIndex].push(action.payload);
       }
-      state.focussedFileIndices[firstPanelIndex] = state.openFiles[firstPanelIndex].indexOf(action.payload)
+      state.focussedFileIndices[firstPanelIndex] = state.openFiles[
+        firstPanelIndex
+      ].indexOf(action.payload);
     },
     setOpenFiles: (state, action) => {
-      state.openFiles = action.payload
+      state.openFiles = action.payload;
     },
     addFilePanel: (state) => {
-      state.openFiles.push([])
-      state.focussedFileIndices.push(0)
+      state.openFiles.push([]);
+      state.focussedFileIndices.push(0);
     },
     setFocussedFileIndex: (state, action) => {
-      state.focussedFileIndices[action.payload.panelIndex] = action.payload.fileIndex
+      state.focussedFileIndices[action.payload.panelIndex] =
+        action.payload.fileIndex;
     },
     updateImages: (state, action) => {
       if (!state.project.image_list) {
@@ -168,13 +178,13 @@ export const EditorSlice = createSlice({
       if (!state.project.image_list) {
         state.project.image_list = [];
       }
-      state.loading="success"
+      state.loading = "success";
       if (state.openFiles.flat().length === 0) {
-        const firstPanelIndex = 0
+        const firstPanelIndex = 0;
         if (state.project.project_type === "html") {
-          state.openFiles[firstPanelIndex].push("index.html")
+          state.openFiles[firstPanelIndex].push("index.html");
         } else {
-          state.openFiles[firstPanelIndex].push("main.py")
+          state.openFiles[firstPanelIndex].push("main.py");
         }
       }
       state.justLoaded = true;
@@ -217,9 +227,11 @@ export const EditorSlice = createSlice({
       state.project.components[key].name = name;
       state.project.components[key].extension = extension;
       if (state.openFiles.flat().includes(oldName)) {
-        const panelIndex = state.openFiles.map((fileNames) => fileNames.includes(oldName)).indexOf(true)
-        const fileIndex = state.openFiles[panelIndex].indexOf(oldName)
-        state.openFiles[panelIndex][fileIndex] = `${name}.${extension}`
+        const panelIndex = state.openFiles
+          .map((fileNames) => fileNames.includes(oldName))
+          .indexOf(true);
+        const fileIndex = state.openFiles[panelIndex].indexOf(oldName);
+        state.openFiles[panelIndex][fileIndex] = `${name}.${extension}`;
       }
       state.saving = "idle";
     },
@@ -352,7 +364,7 @@ export const EditorSlice = createSlice({
         state.saving = "idle";
         state.currentLoadingRequestId = undefined;
         if (state.openFiles.flat().length === 0) {
-          const firstPanelIndex = 0
+          const firstPanelIndex = 0;
           if (state.project.project_type === "html") {
             state.openFiles[firstPanelIndex].push("index.html");
           } else {
diff --git a/src/components/Editor/EditorSlice.test.js b/src/components/Editor/EditorSlice.test.js
index 4a7a6d040..a53c3b702 100644
--- a/src/components/Editor/EditorSlice.test.js
+++ b/src/components/Editor/EditorSlice.test.js
@@ -1,4 +1,10 @@
-import { createOrUpdateProject, createRemix, deleteProject, readProject, readProjectList } from '../../utils/apiCallHandler';
+import {
+  createOrUpdateProject,
+  createRemix,
+  deleteProject,
+  readProject,
+  readProjectList,
+} from "../../utils/apiCallHandler";
 
 import reducer, {
   syncProject,
@@ -12,585 +18,677 @@ import reducer, {
   loadProjectList,
 } from "./EditorSlice";
 
-jest.mock('../../utils/apiCallHandler')
+jest.mock("../../utils/apiCallHandler");
 
 test("Action stopCodeRun sets codeRunStopped to true", () => {
   const previousState = {
     codeRunTriggered: true,
-    codeRunStopped: false
+    codeRunStopped: false,
   };
   const expectedState = {
     codeRunTriggered: true,
-    codeRunStopped: true
-  }
-  expect(reducer(previousState, stopCodeRun())).toEqual(expectedState)
-})
+    codeRunStopped: true,
+  };
+  expect(reducer(previousState, stopCodeRun())).toEqual(expectedState);
+});
 
 test("Showing rename modal sets file state and showing status", () => {
   const previousState = {
     renameFileModalShowing: false,
     modals: {},
-  }
+  };
   const expectedState = {
     renameFileModalShowing: true,
     modals: {
       renameFile: {
-        name: 'main',
-        ext: '.py',
-        fileKey: 0
-      }
+        name: "main",
+        ext: ".py",
+        fileKey: 0,
+      },
     },
-  }
-  expect(reducer(previousState, showRenameFileModal({name: 'main', ext: '.py', fileKey: 0}))).toEqual(expectedState)
-})
+  };
+  expect(
+    reducer(
+      previousState,
+      showRenameFileModal({ name: "main", ext: ".py", fileKey: 0 }),
+    ),
+  ).toEqual(expectedState);
+});
 
 test("closing rename modal updates showing status", () => {
   const previousState = {
-    nameError: 'some error',
+    nameError: "some error",
     renameFileModalShowing: true,
     modals: {
       renameFile: {
-        name: 'main',
-        ext: '.py',
-        fileKey: 0
-      }
-    }
-  }
+        name: "main",
+        ext: ".py",
+        fileKey: 0,
+      },
+    },
+  };
   const expectedState = {
-    nameError: '',
+    nameError: "",
     renameFileModalShowing: false,
     modals: {
       renameFile: {
-        name: 'main',
-        ext: '.py',
-        fileKey: 0
-      }
-    }
-  }
-  expect(reducer(previousState, closeRenameFileModal())).toEqual(expectedState)
-})
-
-describe('When project has no identifier', () => {
-  const dispatch = jest.fn()
+        name: "main",
+        ext: ".py",
+        fileKey: 0,
+      },
+    },
+  };
+  expect(reducer(previousState, closeRenameFileModal())).toEqual(expectedState);
+});
+
+describe("When project has no identifier", () => {
+  const dispatch = jest.fn();
   const project = {
-    name: 'hello world',
-    project_type: 'python',
+    name: "hello world",
+    project_type: "python",
     components: [
       {
-        name: 'main',
-        extension: 'py',
-        content: '# hello'
-      }
-    ]
-  }
-  const access_token = 'myToken'
+        name: "main",
+        extension: "py",
+        content: "# hello",
+      },
+    ],
+  };
+  const access_token = "myToken";
 
   const initialState = {
     editor: {
       project: project,
-      saving: 'idle',
+      saving: "idle",
     },
     auth: {
-      isLoadingUser: false
-    }
-  }
+      isLoadingUser: false,
+    },
+  };
 
-  let saveThunk
-  let saveAction
+  let saveThunk;
+  let saveAction;
 
   beforeEach(() => {
-    Date.now = jest.fn(() => 1669808953)
-    saveThunk= syncProject('save')
-    saveAction = saveThunk({ project, accessToken: access_token, autosave: false })
-  })
-
-  test('Saving creates new project', async () => {
-    await saveAction(dispatch, () => initialState)
-    expect(createOrUpdateProject).toHaveBeenCalledWith(project, access_token)
-  })
-
-  test('Successfully creating project triggers fulfilled action', async () => {
-    createOrUpdateProject.mockImplementationOnce(() => Promise.resolve({ status: 200 }))
-    await saveAction(dispatch, () => initialState)
-    expect(dispatch.mock.calls[1][0].type).toBe('editor/saveProject/fulfilled')
-  })
-
-  test('The saveProject/fulfilled action sets saving to success and loaded to idle', async () => {
-    const returnedProject = {...project, identifier: 'auto-generated-identifier'} 
+    Date.now = jest.fn(() => 1669808953);
+    saveThunk = syncProject("save");
+    saveAction = saveThunk({
+      project,
+      accessToken: access_token,
+      autosave: false,
+    });
+  });
+
+  test("Saving creates new project", async () => {
+    await saveAction(dispatch, () => initialState);
+    expect(createOrUpdateProject).toHaveBeenCalledWith(project, access_token);
+  });
+
+  test("Successfully creating project triggers fulfilled action", async () => {
+    createOrUpdateProject.mockImplementationOnce(() =>
+      Promise.resolve({ status: 200 }),
+    );
+    await saveAction(dispatch, () => initialState);
+    expect(dispatch.mock.calls[1][0].type).toBe("editor/saveProject/fulfilled");
+  });
+
+  test("The saveProject/fulfilled action sets saving to success and loaded to idle", async () => {
+    const returnedProject = {
+      ...project,
+      identifier: "auto-generated-identifier",
+    };
     const expectedState = {
       project: returnedProject,
-      saving: 'success',
+      saving: "success",
       lastSavedTime: 1669808953,
-      loading: 'idle'
-    }
+      loading: "idle",
+    };
 
-    expect(reducer(initialState.editor, saveThunk.fulfilled({ project: returnedProject }))).toEqual(expectedState)
-  })
+    expect(
+      reducer(
+        initialState.editor,
+        saveThunk.fulfilled({ project: returnedProject }),
+      ),
+    ).toEqual(expectedState);
+  });
 
   // TODO: Autosave state testing
+});
 
-})
-
-describe('When project has an identifier', () => {
-  const dispatch = jest.fn()
+describe("When project has an identifier", () => {
+  const dispatch = jest.fn();
   const project = {
-    name: 'hello world',
-    project_type: 'python',
-    identifier: 'my-project-identifier',
+    name: "hello world",
+    project_type: "python",
+    identifier: "my-project-identifier",
     components: [
       {
-        name: 'main',
-        extension: 'py',
-        content: '# hello'
-      }
+        name: "main",
+        extension: "py",
+        content: "# hello",
+      },
     ],
-    image_list: []
-  }
-  const access_token = 'myToken'
+    image_list: [],
+  };
+  const access_token = "myToken";
   const initialState = {
     editor: {
       project: project,
-      saving: 'idle'
+      saving: "idle",
     },
     auth: {
-      isLoadingUser: false
-    }
-  }
+      isLoadingUser: false,
+    },
+  };
 
-  let saveThunk
-  let saveAction
+  let saveThunk;
+  let saveAction;
 
-  let remixThunk
-  let remixAction
+  let remixThunk;
+  let remixAction;
 
   beforeEach(() => {
-    saveThunk= syncProject('save')
-    saveAction = saveThunk({ project, accessToken: access_token, autosave: false })
-    remixThunk = syncProject('remix')
-    remixAction = remixThunk({ project, accessToken: access_token })
-  })
-
-  test('Saving updates existing project', async () => {
-    await saveAction(dispatch, () => initialState)
-    expect(createOrUpdateProject).toHaveBeenCalledWith(project, access_token)
-  })
-
-  test('Successfully updating project triggers fulfilled action', async () => {
-    createOrUpdateProject.mockImplementationOnce(() => Promise.resolve({ status: 200 }))
-    await saveAction(dispatch, () => initialState)
-    expect(dispatch.mock.calls[1][0].type).toBe('editor/saveProject/fulfilled')
-  })
-
-  test('The saveProject/fulfilled action sets saving to success', async () => {
+    saveThunk = syncProject("save");
+    saveAction = saveThunk({
+      project,
+      accessToken: access_token,
+      autosave: false,
+    });
+    remixThunk = syncProject("remix");
+    remixAction = remixThunk({ project, accessToken: access_token });
+  });
+
+  test("Saving updates existing project", async () => {
+    await saveAction(dispatch, () => initialState);
+    expect(createOrUpdateProject).toHaveBeenCalledWith(project, access_token);
+  });
+
+  test("Successfully updating project triggers fulfilled action", async () => {
+    createOrUpdateProject.mockImplementationOnce(() =>
+      Promise.resolve({ status: 200 }),
+    );
+    await saveAction(dispatch, () => initialState);
+    expect(dispatch.mock.calls[1][0].type).toBe("editor/saveProject/fulfilled");
+  });
+
+  test("The saveProject/fulfilled action sets saving to success", async () => {
     const expectedState = {
       project: project,
-      saving: 'success'
-    }
-
-    expect(reducer(initialState.editor, saveThunk.fulfilled({ project }))).toEqual(expectedState)
-  })
-
-  test('Remixing triggers createRemix API call', async () => {
-    await remixAction(dispatch, () => initialState)
-    expect(createRemix).toHaveBeenCalledWith(project, access_token)
-  })
-
-  test('Successfully remixing project triggers fulfilled action', async () => {
-    createRemix.mockImplementationOnce(() => Promise.resolve({ status: 200 }))
-    await remixAction(dispatch, () => initialState)
-    expect(dispatch.mock.calls[1][0].type).toBe('editor/remixProject/fulfilled')
-  })
-
-  test('The remixProject/fulfilled action sets saving, loading and lastSaveAutosave', async () => {
+      saving: "success",
+    };
+
+    expect(
+      reducer(initialState.editor, saveThunk.fulfilled({ project })),
+    ).toEqual(expectedState);
+  });
+
+  test("Remixing triggers createRemix API call", async () => {
+    await remixAction(dispatch, () => initialState);
+    expect(createRemix).toHaveBeenCalledWith(project, access_token);
+  });
+
+  test("Successfully remixing project triggers fulfilled action", async () => {
+    createRemix.mockImplementationOnce(() => Promise.resolve({ status: 200 }));
+    await remixAction(dispatch, () => initialState);
+    expect(dispatch.mock.calls[1][0].type).toBe(
+      "editor/remixProject/fulfilled",
+    );
+  });
+
+  test("The remixProject/fulfilled action sets saving, loading and lastSaveAutosave", async () => {
     const expectedState = {
       project: project,
-      saving: 'success',
-      loading: 'idle',
-      lastSaveAutosave: false
-    }
-
-    expect(reducer(initialState.editor, remixThunk.fulfilled({ project }))).toEqual(expectedState)
-  })
-})
-
-describe('When renaming a project from the rename project modal', () => {
-  let project = { name: 'hello world' }
-  const access_token = 'myToken'
+      saving: "success",
+      loading: "idle",
+      lastSaveAutosave: false,
+    };
+
+    expect(
+      reducer(initialState.editor, remixThunk.fulfilled({ project })),
+    ).toEqual(expectedState);
+  });
+});
+
+describe("When renaming a project from the rename project modal", () => {
+  let project = { name: "hello world" };
+  const access_token = "myToken";
   const initialState = {
     editor: {
       project: {},
-      modals: {renameProject: project},
+      modals: { renameProject: project },
       renameProjectModalShowing: true,
-      projectListLoaded: 'success'
+      projectListLoaded: "success",
     },
-    auth: {user: {access_token}}
-  }
+    auth: { user: { access_token } },
+  };
 
-  let saveThunk
+  let saveThunk;
 
   beforeEach(() => {
-    saveThunk= syncProject('save')
-  })
+    saveThunk = syncProject("save");
+  });
 
-  test('The saveProject/fulfilled action closes rename project modal and reloads projects list', () => {
+  test("The saveProject/fulfilled action closes rename project modal and reloads projects list", () => {
     const expectedState = {
       project: {},
-      saving: 'success',
+      saving: "success",
       modals: { renameProject: null },
       renameProjectModalShowing: false,
-      projectListLoaded: 'idle'
-    }
-    expect(reducer(initialState.editor, saveThunk.fulfilled({ project }))).toEqual(expectedState)
-  })
-})
-
-describe('When deleting a project', () => {
-  const dispatch = jest.fn()
-  let project = { identifier: 'my-amazing-project', name: 'hello world' }
-  const access_token = 'myToken'
+      projectListLoaded: "idle",
+    };
+    expect(
+      reducer(initialState.editor, saveThunk.fulfilled({ project })),
+    ).toEqual(expectedState);
+  });
+});
+
+describe("When deleting a project", () => {
+  const dispatch = jest.fn();
+  let project = { identifier: "my-amazing-project", name: "hello world" };
+  const access_token = "myToken";
   const initialState = {
     editor: {
       project: {},
-      modals: {deleteProject: project},
+      modals: { deleteProject: project },
       deleteProjectModalShowing: true,
-      projectListLoaded: 'success'
+      projectListLoaded: "success",
     },
-    auth: {user: {access_token}}
-  }
+    auth: { user: { access_token } },
+  };
 
-  let deleteThunk
-  let deleteAction
+  let deleteThunk;
+  let deleteAction;
 
   beforeEach(() => {
-    deleteThunk = syncProject('delete')
-    deleteAction = deleteThunk({ identifier: project.identifier, accessToken: access_token })
-  })
-
-  test('Deleting a project triggers deleteProject API call', async () => {
-    await deleteAction(dispatch, () => initialState)
-    expect(deleteProject).toHaveBeenCalledWith(project.identifier, access_token)
-  })
-
-  test('Successfully deleting project triggers fulfilled action', async () => {
-    deleteProject.mockImplementationOnce(() => Promise.resolve({ status: 200 }))
-    await deleteAction(dispatch, () => initialState)
-    expect(dispatch.mock.calls[1][0].type).toBe('editor/deleteProject/fulfilled')
-  })
-
-  test('The deleteProject/fulfilled action closes delete project modal and reloads projects list', () => {
+    deleteThunk = syncProject("delete");
+    deleteAction = deleteThunk({
+      identifier: project.identifier,
+      accessToken: access_token,
+    });
+  });
+
+  test("Deleting a project triggers deleteProject API call", async () => {
+    await deleteAction(dispatch, () => initialState);
+    expect(deleteProject).toHaveBeenCalledWith(
+      project.identifier,
+      access_token,
+    );
+  });
+
+  test("Successfully deleting project triggers fulfilled action", async () => {
+    deleteProject.mockImplementationOnce(() =>
+      Promise.resolve({ status: 200 }),
+    );
+    await deleteAction(dispatch, () => initialState);
+    expect(dispatch.mock.calls[1][0].type).toBe(
+      "editor/deleteProject/fulfilled",
+    );
+  });
+
+  test("The deleteProject/fulfilled action closes delete project modal and reloads projects list", () => {
     const expectedState = {
       project: {},
       modals: { deleteProject: null },
       deleteProjectModalShowing: false,
-      projectListLoaded: 'idle'
-    }
-    expect(reducer(initialState.editor, deleteThunk.fulfilled({}))).toEqual(expectedState)
-  })
-})
-
-const requestingAProject = function(project, projectFile) {
-  const dispatch = jest.fn()
+      projectListLoaded: "idle",
+    };
+    expect(reducer(initialState.editor, deleteThunk.fulfilled({}))).toEqual(
+      expectedState,
+    );
+  });
+});
+
+const requestingAProject = function (project, projectFile) {
+  const dispatch = jest.fn();
   const initialState = {
     editor: {
       project: {},
-      loading: 'idle'
+      loading: "idle",
     },
     auth: {
-      isLoadingUser: false
-    }
-  }
+      isLoadingUser: false,
+    },
+  };
 
-  let loadThunk
-  let loadAction
+  let loadThunk;
+  let loadAction;
 
-  let loadFulfilledAction
-  let loadRejectedAction
+  let loadFulfilledAction;
+  let loadRejectedAction;
 
   beforeEach(() => {
-    loadThunk = syncProject('load')
-    loadAction = loadThunk({ identifier: 'my-project-identifier', locale: 'ja-JP', accessToken: 'my_token' })
-
-    loadFulfilledAction = loadThunk.fulfilled({ project })
-    loadFulfilledAction.meta.requestId='my_request_id'
-    loadRejectedAction = loadThunk.rejected()
-    loadRejectedAction.meta.requestId='my_request_id'
-  })
-
-  test('Reads project from database', async () => {
-    await loadAction(dispatch, () => initialState)
-    expect(readProject).toHaveBeenCalledWith('my-project-identifier', 'ja-JP', 'my_token')
-  })
-
-  test('If loading status pending, loading success updates status', () => {
+    loadThunk = syncProject("load");
+    loadAction = loadThunk({
+      identifier: "my-project-identifier",
+      locale: "ja-JP",
+      accessToken: "my_token",
+    });
+
+    loadFulfilledAction = loadThunk.fulfilled({ project });
+    loadFulfilledAction.meta.requestId = "my_request_id";
+    loadRejectedAction = loadThunk.rejected();
+    loadRejectedAction.meta.requestId = "my_request_id";
+  });
+
+  test("Reads project from database", async () => {
+    await loadAction(dispatch, () => initialState);
+    expect(readProject).toHaveBeenCalledWith(
+      "my-project-identifier",
+      "ja-JP",
+      "my_token",
+    );
+  });
+
+  test("If loading status pending, loading success updates status", () => {
     const initialState = {
       openFiles: [[]],
-      loading: 'pending',
-      currentLoadingRequestId: 'my_request_id'
-    }
+      loading: "pending",
+      currentLoadingRequestId: "my_request_id",
+    };
     const expectedState = {
       openFiles: [[projectFile]],
-      loading: 'success',
+      loading: "success",
       justLoaded: true,
-      saving: 'idle',
+      saving: "idle",
       project: project,
       currentLoadingRequestId: undefined,
-    }
-    expect(reducer(initialState, loadFulfilledAction)).toEqual(expectedState)
-  })
+    };
+    expect(reducer(initialState, loadFulfilledAction)).toEqual(expectedState);
+  });
 
-  test('If not latest request, loading success does not update status', () => {
+  test("If not latest request, loading success does not update status", () => {
     const initialState = {
-      loading: 'pending',
-      currentLoadingRequestId: 'another_request_id'
-    }
-    expect(reducer(initialState, loadFulfilledAction)).toEqual(initialState)
-  })
+      loading: "pending",
+      currentLoadingRequestId: "another_request_id",
+    };
+    expect(reducer(initialState, loadFulfilledAction)).toEqual(initialState);
+  });
 
-  test('If already rejected, loading success does not update status', () => {
+  test("If already rejected, loading success does not update status", () => {
     const initialState = {
-      loading: 'failed'
-    }
-    expect(reducer(initialState, syncProject('load').fulfilled())).toEqual(initialState)
-  })
-
-  test('If loading status pending, loading failure updates status', () => {
+      loading: "failed",
+    };
+    expect(reducer(initialState, syncProject("load").fulfilled())).toEqual(
+      initialState,
+    );
+  });
+
+  test("If loading status pending, loading failure updates status", () => {
     const initialState = {
-      loading: 'pending',
-      currentLoadingRequestId: 'my_request_id'
-    }
+      loading: "pending",
+      currentLoadingRequestId: "my_request_id",
+    };
     const expectedState = {
-      loading: 'failed',
-      saving: 'idle',
-      currentLoadingRequestId: undefined
-    }
-    expect(reducer(initialState, loadRejectedAction)).toEqual(expectedState)
-  })
-
-  test('If not latest request, loading failure does not update status', () => {
+      loading: "failed",
+      saving: "idle",
+      currentLoadingRequestId: undefined,
+    };
+    expect(reducer(initialState, loadRejectedAction)).toEqual(expectedState);
+  });
+
+  test("If not latest request, loading failure does not update status", () => {
     const initialState = {
-      loading: 'pending',
-      currentLoadingRequestId: 'another_request_id'
-    }
-    expect(reducer(initialState, loadRejectedAction)).toEqual(initialState)
-  })
+      loading: "pending",
+      currentLoadingRequestId: "another_request_id",
+    };
+    expect(reducer(initialState, loadRejectedAction)).toEqual(initialState);
+  });
 
-  test('If already fulfilled, loading rejection does not update status', () => {
+  test("If already fulfilled, loading rejection does not update status", () => {
     const initialState = {
-      loading: 'success'
-    }
-    expect(reducer(initialState, loadThunk.rejected())).toEqual(initialState)
-  })
-}
+      loading: "success",
+    };
+    expect(reducer(initialState, loadThunk.rejected())).toEqual(initialState);
+  });
+};
 
-describe('When requesting a python project', () => {
+describe("When requesting a python project", () => {
   const project = {
-    name: 'hello world',
-    project_type: 'python',
-    identifier: 'my-project-identifier',
+    name: "hello world",
+    project_type: "python",
+    identifier: "my-project-identifier",
     components: [
       {
-        name: 'main',
-        extension: 'py',
-        content: '# hello'
-      }
+        name: "main",
+        extension: "py",
+        content: "# hello",
+      },
     ],
-    image_list: []
-  }
-  requestingAProject(project, 'main.py')
-})
+    image_list: [],
+  };
+  requestingAProject(project, "main.py");
+});
 
-describe('When requesting a HTML project', () => {
+describe("When requesting a HTML project", () => {
   const project = {
-    name: 'hello html world',
-    project_type: 'html',
-    identifier: 'my-project-identifier',
+    name: "hello html world",
+    project_type: "html",
+    identifier: "my-project-identifier",
     components: [
       {
-        name: 'index',
-        extension: 'html',
-        content: '# hello world'
-      }
+        name: "index",
+        extension: "html",
+        content: "# hello world",
+      },
     ],
-    image_list: []
-  }
-  requestingAProject(project, 'index.html')
-})
-
-describe('When requesting project list', () => {
-  const dispatch = jest.fn()
-  const projects = [
-    { name: 'project1' },
-    { name: 'project2' }
-  ]
+    image_list: [],
+  };
+  requestingAProject(project, "index.html");
+});
+
+describe("When requesting project list", () => {
+  const dispatch = jest.fn();
+  const projects = [{ name: "project1" }, { name: "project2" }];
   const initialState = {
     projectList: [],
-    projectListLoaded: 'pending',
-    projectIndexCurrentPage: 4
-  }
-  let loadProjectListThunk
+    projectListLoaded: "pending",
+    projectIndexCurrentPage: 4,
+  };
+  let loadProjectListThunk;
 
   beforeEach(() => {
-    loadProjectListThunk = loadProjectList({page: 12, accessToken: 'access_token'})
-  })
-
-  test('Loading project list triggers loadProjectList API call', async () => {
-    await loadProjectListThunk(dispatch, () => initialState)
-    expect(readProjectList).toHaveBeenCalledWith(12, 'access_token')
-  })
-
-  test('Successfully loading project list triggers fulfilled action', async () => {
-    readProjectList.mockImplementationOnce(() => Promise.resolve({ status: 200, headers: {}}))
-    await loadProjectListThunk(dispatch, () => initialState)
-    expect(dispatch.mock.calls[1][0].type).toBe('editor/loadProjectList/fulfilled')
-  })
-
-  test('The loadProjectList/fulfilled action with projects returned sets the projectList and total pages', () => {
+    loadProjectListThunk = loadProjectList({
+      page: 12,
+      accessToken: "access_token",
+    });
+  });
+
+  test("Loading project list triggers loadProjectList API call", async () => {
+    await loadProjectListThunk(dispatch, () => initialState);
+    expect(readProjectList).toHaveBeenCalledWith(12, "access_token");
+  });
+
+  test("Successfully loading project list triggers fulfilled action", async () => {
+    readProjectList.mockImplementationOnce(() =>
+      Promise.resolve({ status: 200, headers: {} }),
+    );
+    await loadProjectListThunk(dispatch, () => initialState);
+    expect(dispatch.mock.calls[1][0].type).toBe(
+      "editor/loadProjectList/fulfilled",
+    );
+  });
+
+  test("The loadProjectList/fulfilled action with projects returned sets the projectList and total pages", () => {
     const expectedState = {
       projectList: projects,
-      projectListLoaded: 'success',
+      projectListLoaded: "success",
       projectIndexCurrentPage: 4,
-      projectIndexTotalPages: 12
-    }
-    expect(reducer(initialState, loadProjectList.fulfilled({projects, page: 4, links: {last: {page: 12}}}))).toEqual(expectedState)
-  })
-
-  test('The loadProjectList/fulfilled action with no projects loads previous page', () => {
+      projectIndexTotalPages: 12,
+    };
+    expect(
+      reducer(
+        initialState,
+        loadProjectList.fulfilled({
+          projects,
+          page: 4,
+          links: { last: { page: 12 } },
+        }),
+      ),
+    ).toEqual(expectedState);
+  });
+
+  test("The loadProjectList/fulfilled action with no projects loads previous page", () => {
     const expectedState = {
       projectList: [],
-      projectListLoaded: 'idle',
-      projectIndexCurrentPage: 3
-    }
-    expect(reducer(initialState, loadProjectList.fulfilled({projects: [], page: 4}))).toEqual(expectedState)
-  })
-
-  test('The loadProjectList/fulfilled action with no projects on page 1 sets loading to success', () => {
+      projectListLoaded: "idle",
+      projectIndexCurrentPage: 3,
+    };
+    expect(
+      reducer(
+        initialState,
+        loadProjectList.fulfilled({ projects: [], page: 4 }),
+      ),
+    ).toEqual(expectedState);
+  });
+
+  test("The loadProjectList/fulfilled action with no projects on page 1 sets loading to success", () => {
     const expectedState = {
       projectList: [],
-      projectListLoaded: 'success',
+      projectListLoaded: "success",
       projectIndexCurrentPage: 1,
-      projectIndexTotalPages: 1
-    }
-    expect(reducer({...initialState, projectIndexCurrentPage: 1}, loadProjectList.fulfilled({projects: [], page: 1}))).toEqual(expectedState)
-  })
-})
-
-describe('Opening files', () => {
+      projectIndexTotalPages: 1,
+    };
+    expect(
+      reducer(
+        { ...initialState, projectIndexCurrentPage: 1 },
+        loadProjectList.fulfilled({ projects: [], page: 1 }),
+      ),
+    ).toEqual(expectedState);
+  });
+});
+
+describe("Opening files", () => {
   const initialState = {
-    openFiles: [['main.py', 'file1.py']],
-    focussedFileIndices: [0]
-  }
+    openFiles: [["main.py", "file1.py"]],
+    focussedFileIndices: [0],
+  };
 
-  test('Opening unopened file adds it to openFiles and focusses that file', () => {
+  test("Opening unopened file adds it to openFiles and focusses that file", () => {
     const expectedState = {
-      openFiles: [['main.py', 'file1.py', 'file2.py']],
-      focussedFileIndices: [2]
-    }
-    expect(reducer(initialState, openFile('file2.py'))).toEqual(expectedState)
-  })
+      openFiles: [["main.py", "file1.py", "file2.py"]],
+      focussedFileIndices: [2],
+    };
+    expect(reducer(initialState, openFile("file2.py"))).toEqual(expectedState);
+  });
 
-  test('Opening already open file focusses that file', () => {
+  test("Opening already open file focusses that file", () => {
     const expectedState = {
-      openFiles: [['main.py', 'file1.py']],
-      focussedFileIndices: [1]
-    }
-    expect(reducer(initialState, openFile('file1.py'))).toEqual(expectedState)
-  })
+      openFiles: [["main.py", "file1.py"]],
+      focussedFileIndices: [1],
+    };
+    expect(reducer(initialState, openFile("file1.py"))).toEqual(expectedState);
+  });
 
-  test('Switching file focus', () => {
+  test("Switching file focus", () => {
     const expectedState = {
-      openFiles: [['main.py', 'file1.py']],
-      focussedFileIndices: [1]
-    }
-    expect(reducer(initialState, setFocussedFileIndex({panelIndex: 0, fileIndex: 1}))).toEqual(expectedState)
-  })
-})
-
-describe('Closing files', () => {
-  test('Closing the last file when focussed transfers focus to the left', () => {
+      openFiles: [["main.py", "file1.py"]],
+      focussedFileIndices: [1],
+    };
+    expect(
+      reducer(
+        initialState,
+        setFocussedFileIndex({ panelIndex: 0, fileIndex: 1 }),
+      ),
+    ).toEqual(expectedState);
+  });
+});
+
+describe("Closing files", () => {
+  test("Closing the last file when focussed transfers focus to the left", () => {
     const initialState = {
-      openFiles: [['main.py', 'file1.py']],
-      focussedFileIndices: [1]
-    }
+      openFiles: [["main.py", "file1.py"]],
+      focussedFileIndices: [1],
+    };
     const expectedState = {
-      openFiles: [['main.py']],
-      focussedFileIndices: [0]
-    }
-    expect(reducer(initialState, closeFile('file1.py'))).toEqual(expectedState)
-  })
+      openFiles: [["main.py"]],
+      focussedFileIndices: [0],
+    };
+    expect(reducer(initialState, closeFile("file1.py"))).toEqual(expectedState);
+  });
 
-  test('Closing not the last file when focussed does not change focus', () => {
+  test("Closing not the last file when focussed does not change focus", () => {
     const initialState = {
-      openFiles: [['main.py', 'file1.py', 'file2.py']],
-      focussedFileIndices: [1]
-    }
+      openFiles: [["main.py", "file1.py", "file2.py"]],
+      focussedFileIndices: [1],
+    };
     const expectedState = {
-      openFiles: [['main.py', 'file2.py']],
-      focussedFileIndices: [1]
-    }
-    expect(reducer(initialState, closeFile('file1.py'))).toEqual(expectedState)
-  })
+      openFiles: [["main.py", "file2.py"]],
+      focussedFileIndices: [1],
+    };
+    expect(reducer(initialState, closeFile("file1.py"))).toEqual(expectedState);
+  });
 
-  test('Closing unfocussed file before file that is in focus keeps same file in focus', () => {
+  test("Closing unfocussed file before file that is in focus keeps same file in focus", () => {
     const initialState = {
-      openFiles: [['main.py', 'file1.py', 'file2.py', 'file3.py']],
-      focussedFileIndices: [2]
-    }
+      openFiles: [["main.py", "file1.py", "file2.py", "file3.py"]],
+      focussedFileIndices: [2],
+    };
     const expectedState = {
-      openFiles: [['main.py', 'file2.py', 'file3.py']],
-      focussedFileIndices: [1]
-    }
-    expect(reducer(initialState, closeFile('file1.py'))).toEqual(expectedState)
-  })
+      openFiles: [["main.py", "file2.py", "file3.py"]],
+      focussedFileIndices: [1],
+    };
+    expect(reducer(initialState, closeFile("file1.py"))).toEqual(expectedState);
+  });
 
-  test('Closing unfocussed file after file that is in focus keeps same file in focus', () => {
+  test("Closing unfocussed file after file that is in focus keeps same file in focus", () => {
     const initialState = {
-      openFiles: [['main.py', 'file1.py', 'file2.py', 'file3.py']],
-      focussedFileIndices: [1]
-    }
+      openFiles: [["main.py", "file1.py", "file2.py", "file3.py"]],
+      focussedFileIndices: [1],
+    };
     const expectedState = {
-      openFiles: [['main.py', 'file1.py', 'file3.py']],
-      focussedFileIndices: [1]
-    }
-    expect(reducer(initialState, closeFile('file2.py'))).toEqual(expectedState)
-  })
-})
-
-describe('Updating file name', () => {
+      openFiles: [["main.py", "file1.py", "file3.py"]],
+      focussedFileIndices: [1],
+    };
+    expect(reducer(initialState, closeFile("file2.py"))).toEqual(expectedState);
+  });
+});
+
+describe("Updating file name", () => {
   const initialState = {
     project: {
       components: [
-        {name: 'file', extension: 'py' },
-        {name: 'another_file', extension: 'py'}
-      ]
+        { name: "file", extension: "py" },
+        { name: "another_file", extension: "py" },
+      ],
     },
-    openFiles: [['file.py']]
-  }
+    openFiles: [["file.py"]],
+  };
 
-  test('If file is open updates name in project and openFiles and saves', () => {
+  test("If file is open updates name in project and openFiles and saves", () => {
     const expectedState = {
       project: {
         components: [
-          {name: 'my_file', extension: 'py' },
-          {name: 'another_file', extension: 'py'}
-        ]
+          { name: "my_file", extension: "py" },
+          { name: "another_file", extension: "py" },
+        ],
       },
-      openFiles: [['my_file.py']],
+      openFiles: [["my_file.py"]],
       saving: "idle",
-    }
-    expect(reducer(initialState, updateComponentName({key: 0, name: 'my_file', extension: 'py'}))).toEqual(expectedState)
-  })
-
-  test('If file is closed updates name in project and saves', () => {
+    };
+    expect(
+      reducer(
+        initialState,
+        updateComponentName({ key: 0, name: "my_file", extension: "py" }),
+      ),
+    ).toEqual(expectedState);
+  });
+
+  test("If file is closed updates name in project and saves", () => {
     const expectedState = {
       project: {
         components: [
-          {name: 'file', extension: 'py' },
-          {name: 'my_file', extension: 'py'}
-        ]
+          { name: "file", extension: "py" },
+          { name: "my_file", extension: "py" },
+        ],
       },
-      openFiles: [['file.py']],
+      openFiles: [["file.py"]],
       saving: "idle",
-    }
-    expect(reducer(initialState, updateComponentName({key: 1, name: 'my_file', extension: 'py'}))).toEqual(expectedState)
-  })
-})
+    };
+    expect(
+      reducer(
+        initialState,
+        updateComponentName({ key: 1, name: "my_file", extension: "py" }),
+      ),
+    ).toEqual(expectedState);
+  });
+});
diff --git a/src/components/Editor/ErrorMessage/ErrorMessage.js b/src/components/Editor/ErrorMessage/ErrorMessage.js
index f2efa986b..ee2d151c9 100644
--- a/src/components/Editor/ErrorMessage/ErrorMessage.js
+++ b/src/components/Editor/ErrorMessage/ErrorMessage.js
@@ -1,15 +1,15 @@
-import React, { useContext } from 'react'
-import './ErrorMessage.scss'
-import { useSelector } from 'react-redux'
-import { SettingsContext } from '../../../settings';
+import React, { useContext } from "react";
+import "./ErrorMessage.scss";
+import { useSelector } from "react-redux";
+import { SettingsContext } from "../../../settings";
 
 const ErrorMessage = () => {
   const error = useSelector((state) => state.editor.error);
-  const settings = useContext(SettingsContext)
+  const settings = useContext(SettingsContext);
 
   return error ? (
     <div className={`error-message error-message--${settings.fontSize}`}>
-      <p className='error-message__content'>{ error }</p>
+      <p className="error-message__content">{error}</p>
     </div>
   ) : null;
 };
diff --git a/src/components/Editor/ErrorMessage/ErrorMessage.test.js b/src/components/Editor/ErrorMessage/ErrorMessage.test.js
index c9444f7b7..e45d7ba60 100644
--- a/src/components/Editor/ErrorMessage/ErrorMessage.test.js
+++ b/src/components/Editor/ErrorMessage/ErrorMessage.test.js
@@ -1,35 +1,36 @@
-import configureStore from 'redux-mock-store'
-import { Provider } from "react-redux"
-import { SettingsContext } from "../../../settings"
-import ErrorMessage from "./ErrorMessage"
-import { render, screen } from '@testing-library/react'
+import configureStore from "redux-mock-store";
+import { Provider } from "react-redux";
+import { SettingsContext } from "../../../settings";
+import ErrorMessage from "./ErrorMessage";
+import { render, screen } from "@testing-library/react";
 
-describe('When error is set', () => {
-  
+describe("When error is set", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
-        error: 'Oops'
-      }
-    }
+        error: "Oops",
+      },
+    };
     const store = mockStore(initialState);
     render(
       <Provider store={store}>
-        <SettingsContext.Provider value={{ theme: 'dark', fontSize: 'myFontSize' }}>
+        <SettingsContext.Provider
+          value={{ theme: "dark", fontSize: "myFontSize" }}
+        >
           <ErrorMessage />
         </SettingsContext.Provider>
-      </Provider>
-    )
-  })
+      </Provider>,
+    );
+  });
 
-  test('Error message displays', () => {
-    expect(screen.queryByText('Oops')).toBeInTheDocument()
-  })
+  test("Error message displays", () => {
+    expect(screen.queryByText("Oops")).toBeInTheDocument();
+  });
 
-  test('Font size class is set correctly', () => {
-    const errorMessage = screen.queryByText('Oops').parentElement
-    expect(errorMessage).toHaveClass("error-message--myFontSize")
-  })
-})
+  test("Font size class is set correctly", () => {
+    const errorMessage = screen.queryByText("Oops").parentElement;
+    expect(errorMessage).toHaveClass("error-message--myFontSize");
+  });
+});
diff --git a/src/components/Editor/ErrorMessage/NameErrorMessage.js b/src/components/Editor/ErrorMessage/NameErrorMessage.js
index e8de91a99..78663e0f1 100644
--- a/src/components/Editor/ErrorMessage/NameErrorMessage.js
+++ b/src/components/Editor/ErrorMessage/NameErrorMessage.js
@@ -1,12 +1,12 @@
-import './ErrorMessage.scss'
-import { useSelector } from 'react-redux'
+import "./ErrorMessage.scss";
+import { useSelector } from "react-redux";
 
 const NameErrorMessage = () => {
   const error = useSelector((state) => state.editor.nameError);
 
   return error ? (
-    <div className='error-message'>
-      <p className='error-message__content'>{ error }</p>
+    <div className="error-message">
+      <p className="error-message__content">{error}</p>
     </div>
   ) : null;
 };
diff --git a/src/components/Editor/FontSizeSelector/FontSizeSelector.js b/src/components/Editor/FontSizeSelector/FontSizeSelector.js
index d7858df12..af2e63632 100644
--- a/src/components/Editor/FontSizeSelector/FontSizeSelector.js
+++ b/src/components/Editor/FontSizeSelector/FontSizeSelector.js
@@ -2,46 +2,67 @@ import React from "react";
 import { useCookies } from "react-cookie";
 import { useTranslation } from "react-i18next";
 import { FontIcon } from "../../../Icons";
-import './FontSizeSelector.scss'
+import "./FontSizeSelector.scss";
 
-const COOKIE_PATHS = ['/', '/projects', '/python']
+const COOKIE_PATHS = ["/", "/projects", "/python"];
 
 const FontSizeSelector = () => {
-  const [ cookies , setCookie, removeCookie] = useCookies(['fontSize'])
-  const fontSize = cookies.fontSize || "small"
-  const { t } = useTranslation()
+  const [cookies, setCookie, removeCookie] = useCookies(["fontSize"]);
+  const fontSize = cookies.fontSize || "small";
+  const { t } = useTranslation();
 
   const setFontSize = (fontSize) => {
     if (cookies.fontSize) {
       COOKIE_PATHS.forEach((path) => {
-        removeCookie('fontSize', {path})
-      })
+        removeCookie("fontSize", { path });
+      });
     }
-    setCookie('fontSize', fontSize, { path: '/' })
-  }
+    setCookie("fontSize", fontSize, { path: "/" });
+  };
 
   return (
-    <div className='font-size-selector'>
-      <div className='font-btn font-btn--small' onClick={() => setFontSize('small')}>
-        <button className={`font-btn__icon font-btn__icon--small ${fontSize==='small' ? 'font-btn__icon--active' : ''}`}>
-          <FontIcon size={15}/>
+    <div className="font-size-selector">
+      <div
+        className="font-btn font-btn--small"
+        onClick={() => setFontSize("small")}
+      >
+        <button
+          className={`font-btn__icon font-btn__icon--small ${
+            fontSize === "small" ? "font-btn__icon--active" : ""
+          }`}
+        >
+          <FontIcon size={15} />
         </button>
-        <p>{t('header.settingsMenu.textSizeOptions.small')}</p>
+        <p>{t("header.settingsMenu.textSizeOptions.small")}</p>
       </div>
-      <div className='font-btn font-btn--medium' onClick={() => setFontSize('medium')}>
-        <button className={`font-btn__icon font-btn__icon--medium ${fontSize==='medium' ? 'font-btn__icon--active' : ''}`}>
-          <FontIcon size={23}/>
+      <div
+        className="font-btn font-btn--medium"
+        onClick={() => setFontSize("medium")}
+      >
+        <button
+          className={`font-btn__icon font-btn__icon--medium ${
+            fontSize === "medium" ? "font-btn__icon--active" : ""
+          }`}
+        >
+          <FontIcon size={23} />
         </button>
-        <p>{t('header.settingsMenu.textSizeOptions.medium')}</p>
+        <p>{t("header.settingsMenu.textSizeOptions.medium")}</p>
       </div>
-      <div className='font-btn font-btn--large' onClick={() => setFontSize('large')}>
-        <button className={`font-btn__icon font-btn__icon--large ${fontSize==='large' ? 'font-btn__icon--active' : ''}`}>
-          <FontIcon size={36}/>
+      <div
+        className="font-btn font-btn--large"
+        onClick={() => setFontSize("large")}
+      >
+        <button
+          className={`font-btn__icon font-btn__icon--large ${
+            fontSize === "large" ? "font-btn__icon--active" : ""
+          }`}
+        >
+          <FontIcon size={36} />
         </button>
-        <p>{t('header.settingsMenu.textSizeOptions.large')}</p>
+        <p>{t("header.settingsMenu.textSizeOptions.large")}</p>
       </div>
     </div>
-  )
-}
+  );
+};
 
-export default FontSizeSelector
+export default FontSizeSelector;
diff --git a/src/components/Editor/FontSizeSelector/FontSizeSelector.test.js b/src/components/Editor/FontSizeSelector/FontSizeSelector.test.js
index e7472ac1e..fc1db32c1 100644
--- a/src/components/Editor/FontSizeSelector/FontSizeSelector.test.js
+++ b/src/components/Editor/FontSizeSelector/FontSizeSelector.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { render, fireEvent } from "@testing-library/react"
+import { render, fireEvent } from "@testing-library/react";
 import FontSizeSelector from "./FontSizeSelector";
-import { Cookies, CookiesProvider } from 'react-cookie';
+import { Cookies, CookiesProvider } from "react-cookie";
 
 describe("When font size cookie unset", () => {
   let cookies;
@@ -12,33 +12,39 @@ describe("When font size cookie unset", () => {
     fontSelector = render(
       <CookiesProvider cookies={cookies}>
         <FontSizeSelector />
-      </CookiesProvider>
-    )
-  })
+      </CookiesProvider>,
+    );
+  });
 
-  test('Cookie remains unset after render', () => {
-    expect(cookies.cookies.fontSize).toBeUndefined()
-  })
+  test("Cookie remains unset after render", () => {
+    expect(cookies.cookies.fontSize).toBeUndefined();
+  });
 
-  test('Sets cookie to large when first button clicked', async () => {
-    const largeButton = fontSelector.getByText('header.settingsMenu.textSizeOptions.large').parentElement
-    fireEvent.click(largeButton)
-    expect(cookies.cookies.fontSize).toBe("large")
-  })
+  test("Sets cookie to large when first button clicked", async () => {
+    const largeButton = fontSelector.getByText(
+      "header.settingsMenu.textSizeOptions.large",
+    ).parentElement;
+    fireEvent.click(largeButton);
+    expect(cookies.cookies.fontSize).toBe("large");
+  });
 
-  test('Sets cookie to medium when second button clicked', async () => {
-    const mediumButton = fontSelector.getByText('header.settingsMenu.textSizeOptions.medium').parentElement
-    fireEvent.click(mediumButton)
-    expect(cookies.cookies.fontSize).toBe("medium")
-  })
+  test("Sets cookie to medium when second button clicked", async () => {
+    const mediumButton = fontSelector.getByText(
+      "header.settingsMenu.textSizeOptions.medium",
+    ).parentElement;
+    fireEvent.click(mediumButton);
+    expect(cookies.cookies.fontSize).toBe("medium");
+  });
 
-  test('Sets cookie to small when third button clicked', async () => {
-    const smallButton = fontSelector.getByText('header.settingsMenu.textSizeOptions.small').parentElement
-    fireEvent.click(smallButton)
-    expect(cookies.cookies.fontSize).toBe("small")
-  })
+  test("Sets cookie to small when third button clicked", async () => {
+    const smallButton = fontSelector.getByText(
+      "header.settingsMenu.textSizeOptions.small",
+    ).parentElement;
+    fireEvent.click(smallButton);
+    expect(cookies.cookies.fontSize).toBe("small");
+  });
 
   afterEach(() => {
-    cookies.remove("theme")
-  })
-})
+    cookies.remove("theme");
+  });
+});
diff --git a/src/components/Editor/Hooks/useEmbeddedMode.js b/src/components/Editor/Hooks/useEmbeddedMode.js
index 3bdbf4809..e3432577b 100644
--- a/src/components/Editor/Hooks/useEmbeddedMode.js
+++ b/src/components/Editor/Hooks/useEmbeddedMode.js
@@ -1,7 +1,7 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import { useEffect } from 'react';
-import { useDispatch } from 'react-redux'
-import { setEmbedded } from '../EditorSlice'
+import { useEffect } from "react";
+import { useDispatch } from "react-redux";
+import { setEmbedded } from "../EditorSlice";
 
 export const useEmbeddedMode = (embed = false) => {
   const dispatch = useDispatch();
diff --git a/src/components/Editor/Hooks/useProject.js b/src/components/Editor/Hooks/useProject.js
index 6ac28205f..602d054cc 100644
--- a/src/components/Editor/Hooks/useProject.js
+++ b/src/components/Editor/Hooks/useProject.js
@@ -9,7 +9,7 @@ export const useProject = (projectIdentifier = null, accessToken = null) => {
   const getCachedProject = (id) =>
     JSON.parse(localStorage.getItem(id || "project"));
   const [cachedProject, setCachedProject] = useState(
-    getCachedProject(projectIdentifier)
+    getCachedProject(projectIdentifier),
   );
   const { i18n } = useTranslation();
   const dispatch = useDispatch();
@@ -40,7 +40,7 @@ export const useProject = (projectIdentifier = null, accessToken = null) => {
           identifier: projectIdentifier,
           locale: i18n.language,
           accessToken,
-        })
+        }),
       );
       return;
     }
diff --git a/src/components/Editor/Hooks/useProject.test.js b/src/components/Editor/Hooks/useProject.test.js
index 55ca440a8..d369457e1 100644
--- a/src/components/Editor/Hooks/useProject.test.js
+++ b/src/components/Editor/Hooks/useProject.test.js
@@ -55,7 +55,7 @@ test("If cached project does not match identifer does not use cached project", a
   localStorage.setItem("project", JSON.stringify(cachedProject));
   renderHook(() => useProject("my-favourite-project"));
   await waitFor(() =>
-    expect(setProject).not.toHaveBeenCalledWith(cachedProject)
+    expect(setProject).not.toHaveBeenCalledWith(cachedProject),
   );
 });
 
@@ -68,7 +68,7 @@ test("If cached project does not match identifier loads correct uncached project
       identifier: project1.identifier,
       locale: "ja-JP",
       accessToken,
-    })
+    }),
   );
 });
 
@@ -80,7 +80,7 @@ test("If no cached project loads uncached project", async () => {
       identifier: "hello-world-project",
       locale: "ja-JP",
       accessToken,
-    })
+    }),
   );
 });
 
diff --git a/src/components/Editor/Hooks/useRequiresUser.js b/src/components/Editor/Hooks/useRequiresUser.js
index ca7f99e97..088f7a672 100644
--- a/src/components/Editor/Hooks/useRequiresUser.js
+++ b/src/components/Editor/Hooks/useRequiresUser.js
@@ -1,18 +1,17 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import { useEffect } from 'react';
-import { useNavigate } from 'react-router-dom'
+import { useEffect } from "react";
+import { useNavigate } from "react-router-dom";
 
 export const useRequiresUser = (isLoading, user) => {
-  const navigate = useNavigate()
+  const navigate = useNavigate();
 
   useEffect(() => {
-    if(isLoading) {
+    if (isLoading) {
       return;
     }
 
-    if(!isLoading && !user) {
-      navigate('/')
+    if (!isLoading && !user) {
+      navigate("/");
     }
   }, [isLoading, user]);
 };
-
diff --git a/src/components/Editor/ImageUploadButton/ImageUploadButton.js b/src/components/Editor/ImageUploadButton/ImageUploadButton.js
index ea5384d34..f3b69479f 100644
--- a/src/components/Editor/ImageUploadButton/ImageUploadButton.js
+++ b/src/components/Editor/ImageUploadButton/ImageUploadButton.js
@@ -1,139 +1,161 @@
-import './ImageUploadButton.css';
+import "./ImageUploadButton.css";
 
-import { useCallback, useState } from 'react'
-import { useDispatch, useSelector } from 'react-redux';
-import Dropzone from 'react-dropzone';
-import Modal from 'react-modal';
+import { useCallback, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Dropzone from "react-dropzone";
+import Modal from "react-modal";
 
-import { updateImages, setNameError } from '../EditorSlice';
-import Button from '../../Button/Button'
-import NameErrorMessage from '../ErrorMessage/NameErrorMessage';
-import store from '../../../app/store';
-import { uploadImages } from '../../../utils/apiCallHandler';
+import { updateImages, setNameError } from "../EditorSlice";
+import Button from "../../Button/Button";
+import NameErrorMessage from "../ErrorMessage/NameErrorMessage";
+import store from "../../../app/store";
+import { uploadImages } from "../../../utils/apiCallHandler";
 
 const allowedExtensions = {
-  "python": [
-    "jpg",
-    "jpeg",
-    "png",
-    "gif"
-  ]
-}
+  python: ["jpg", "jpeg", "png", "gif"],
+};
 
 const allowedExtensionsString = (projectType) => {
   const extensionsList = allowedExtensions[projectType];
   if (extensionsList.length === 1) {
-    return `'.${extensionsList[0]}'`
+    return `'.${extensionsList[0]}'`;
   } else {
-    return `'.` + extensionsList.slice(0, -1).join(`', '.`) + `' or '.` + extensionsList[extensionsList.length - 1] + `'`;
+    return (
+      `'.` +
+      extensionsList.slice(0, -1).join(`', '.`) +
+      `' or '.` +
+      extensionsList[extensionsList.length - 1] +
+      `'`
+    );
   }
-}
+};
 
 const ImageUploadButton = () => {
   const [modalIsOpen, setIsOpen] = useState(false);
   const [files, setFiles] = useState([]);
   const dispatch = useDispatch();
   const projectType = useSelector((state) => state.editor.project.project_type);
-  const projectIdentifier = useSelector((state) => state.editor.project.identifier);
+  const projectIdentifier = useSelector(
+    (state) => state.editor.project.identifier,
+  );
   const projectImages = useSelector((state) => state.editor.project.image_list);
-  const imageNames = projectImages.map(image => `${image.filename}`);
+  const imageNames = projectImages.map((image) => `${image.filename}`);
   const user = useSelector((state) => state.auth.user);
 
   const closeModal = () => {
-    setFiles([])
+    setFiles([]);
     setIsOpen(false);
-  }
+  };
   const showModal = () => {
     dispatch(setNameError(""));
-    setIsOpen(true)
+    setIsOpen(true);
   };
   const saveImages = async () => {
     files.every((file) => {
-      const fileName = file.name
-      const extension = fileName.split('.').slice(1).join('.').toLowerCase();
-      if (imageNames.includes(fileName) || files.filter(file => file.name === fileName).length > 1) {
+      const fileName = file.name;
+      const extension = fileName.split(".").slice(1).join(".").toLowerCase();
+      if (
+        imageNames.includes(fileName) ||
+        files.filter((file) => file.name === fileName).length > 1
+      ) {
         dispatch(setNameError("Image names must be unique."));
-        return false
-      }
-      else if (isValidFileName(fileName, files)) {
-        return true
+        return false;
+      } else if (isValidFileName(fileName, files)) {
+        return true;
       } else if (!allowedExtensions[projectType].includes(extension)) {
-        dispatch(setNameError(`Image names must end in ${allowedExtensionsString(projectType)}.`));
-        return false
+        dispatch(
+          setNameError(
+            `Image names must end in ${allowedExtensionsString(projectType)}.`,
+          ),
+        );
+        return false;
       } else {
         dispatch(setNameError("Error"));
-        return false
+        return false;
       }
-    })
-    if (store.getState().editor.nameError === '') {
-      const response = await uploadImages(projectIdentifier, user.access_token, files)
-      dispatch(updateImages(response.data.image_list))
-      closeModal()
+    });
+    if (store.getState().editor.nameError === "") {
+      const response = await uploadImages(
+        projectIdentifier,
+        user.access_token,
+        files,
+      );
+      dispatch(updateImages(response.data.image_list));
+      closeModal();
     }
-  }
+  };
 
   const isValidFileName = (fileName, files) => {
-    const extension = fileName.split('.').slice(1).join('.').toLowerCase()
-    if (allowedExtensions[projectType].includes(extension) && !imageNames.includes(fileName) && files.filter(file => file.name === fileName).length === 1) {
+    const extension = fileName.split(".").slice(1).join(".").toLowerCase();
+    if (
+      allowedExtensions[projectType].includes(extension) &&
+      !imageNames.includes(fileName) &&
+      files.filter((file) => file.name === fileName).length === 1
+    ) {
       return true;
     } else {
       return false;
     }
-  }
+  };
 
   const customStyles = {
     content: {
-      top: '50%',
-      left: '50%',
-      right: 'auto',
-      bottom: 'auto',
-      marginRight: '-50%',
-      transform: 'translate(-50%, -50%)',
+      top: "50%",
+      left: "50%",
+      right: "auto",
+      bottom: "auto",
+      marginRight: "-50%",
+      transform: "translate(-50%, -50%)",
     },
     overlay: {
-      zIndex: 1000
-    }
+      zIndex: 1000,
+    },
   };
 
   return (
     <>
-      <Button buttonText='Upload Image' onClickHandler={showModal} className="proj-image-upload-button" />
+      <Button
+        buttonText="Upload Image"
+        onClickHandler={showModal}
+        className="proj-image-upload-button"
+      />
 
       <Modal
         isOpen={modalIsOpen}
         onRequestClose={closeModal}
         style={customStyles}
         contentLabel="Upload Image"
-        appElement={document.getElementById('root') || undefined}
+        appElement={document.getElementById("root") || undefined}
       >
         <h2>Upload an image</h2>
 
         <NameErrorMessage />
         <Dropzone
-          onDrop={
-            useCallback(acceptedFiles => {
-              setFiles(prev => [...prev, ...acceptedFiles]);
-            }, [])
-          }>
+          onDrop={useCallback((acceptedFiles) => {
+            setFiles((prev) => [...prev, ...acceptedFiles]);
+          }, [])}
+        >
           {({ getRootProps, getInputProps }) => (
             <section>
-              <div {...getRootProps()} className='dropzone-area'>
+              <div {...getRootProps()} className="dropzone-area">
                 <input {...getInputProps()} />
-                <p className='dropzone-info'>Drag and drop images here, or click to select images from file</p>
-                {files.map((file, i) =>
-                  <p key={i}>{file.name}</p>)}
+                <p className="dropzone-info">
+                  Drag and drop images here, or click to select images from file
+                </p>
+                {files.map((file, i) => (
+                  <p key={i}>{file.name}</p>
+                ))}
               </div>
             </section>
           )}
         </Dropzone>
-        <div className='modal-footer'>
-          <Button buttonText='Cancel' onClickHandler={closeModal} />
-          <Button buttonText='Save' onClickHandler={saveImages} />
+        <div className="modal-footer">
+          <Button buttonText="Cancel" onClickHandler={closeModal} />
+          <Button buttonText="Save" onClickHandler={saveImages} />
         </div>
-
       </Modal>
     </>
   );
-}
+};
 
 export default ImageUploadButton;
diff --git a/src/components/Editor/ImageUploadButton/ImageUploadButton.test.js b/src/components/Editor/ImageUploadButton/ImageUploadButton.test.js
index b121206b8..df575e530 100644
--- a/src/components/Editor/ImageUploadButton/ImageUploadButton.test.js
+++ b/src/components/Editor/ImageUploadButton/ImageUploadButton.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { fireEvent, render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import ImageUploadButton from "./ImageUploadButton";
 
@@ -11,47 +11,53 @@ describe("When user logged in and owns project", () => {
   let queryByText;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
               name: "main",
-              extension: "py"
-            }
+              extension: "py",
+            },
           ],
           image_list: [],
           project_type: "python",
-          user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
+          user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
         },
         nameError: "",
       },
       auth: {
         user: {
           profile: {
-            user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-          }
-        }
-      }
-    }
+            user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+          },
+        },
+      },
+    };
     store = mockStore(initialState);
-    ({ queryByText } = render(<Provider store={store}><div id='root'><ImageUploadButton /></div></Provider>))
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <div id="root">
+          <ImageUploadButton />
+        </div>
+      </Provider>,
+    ));
     button = queryByText(/Upload Image/);
-  })
+  });
 
   test("Modal opens when Image Upload button clicked", () => {
-    fireEvent.click(button)
-    const dropzone = queryByText(/Drag and drop/)
-    expect(dropzone).not.toBeNull()
-  })
+    fireEvent.click(button);
+    const dropzone = queryByText(/Drag and drop/);
+    expect(dropzone).not.toBeNull();
+  });
 
   test("Modal closes when cancel button clicked", () => {
-    fireEvent.click(button)
-    const cancelButton = queryByText(/Cancel/)
-    fireEvent.click(cancelButton)
-    const dropzone = queryByText(/Drag and drop/)
-    expect(dropzone).toBeNull()
-  })
-})
+    fireEvent.click(button);
+    const cancelButton = queryByText(/Cancel/);
+    fireEvent.click(cancelButton);
+    const dropzone = queryByText(/Drag and drop/);
+    expect(dropzone).toBeNull();
+  });
+});
diff --git a/src/components/Editor/NewComponentButton/NewComponentButton.js b/src/components/Editor/NewComponentButton/NewComponentButton.js
index 84c6de76f..c9e440fed 100644
--- a/src/components/Editor/NewComponentButton/NewComponentButton.js
+++ b/src/components/Editor/NewComponentButton/NewComponentButton.js
@@ -1,30 +1,30 @@
-import './NewComponentButton.scss';
+import "./NewComponentButton.scss";
 
-import {React} from 'react'
-import { useDispatch } from 'react-redux';
+import { React } from "react";
+import { useDispatch } from "react-redux";
 
-import { showNewFileModal } from '../EditorSlice';
-import Button from '../../Button/Button'
-import { PlusIcon } from '../../../Icons';
-import { useTranslation } from 'react-i18next';
+import { showNewFileModal } from "../EditorSlice";
+import Button from "../../Button/Button";
+import { PlusIcon } from "../../../Icons";
+import { useTranslation } from "react-i18next";
 
 const NewComponentButton = () => {
-    const { t } = useTranslation()
-    const dispatch = useDispatch();
+  const { t } = useTranslation();
+  const dispatch = useDispatch();
 
-    const openNewFileModal = () => {
-      dispatch(showNewFileModal())
-    }
+  const openNewFileModal = () => {
+    dispatch(showNewFileModal());
+  };
 
-    return (
-        <Button
-          buttonText={t('filePane.newFileButton')}
-          ButtonIcon={PlusIcon}
-          buttonOuter
-          onClickHandler={openNewFileModal}
-          className="btn--primary btn--small proj-new-component-button"
-        />
-    );
-  }
+  return (
+    <Button
+      buttonText={t("filePane.newFileButton")}
+      ButtonIcon={PlusIcon}
+      buttonOuter
+      onClickHandler={openNewFileModal}
+      className="btn--primary btn--small proj-new-component-button"
+    />
+  );
+};
 
 export default NewComponentButton;
diff --git a/src/components/Editor/NewComponentButton/NewComponentButton.test.js b/src/components/Editor/NewComponentButton/NewComponentButton.test.js
index 6c5f11691..7ba970ed4 100644
--- a/src/components/Editor/NewComponentButton/NewComponentButton.test.js
+++ b/src/components/Editor/NewComponentButton/NewComponentButton.test.js
@@ -1,43 +1,47 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import NewComponentButton from "./NewComponentButton";
-import { showNewFileModal } from "../EditorSlice"
+import { showNewFileModal } from "../EditorSlice";
 
 describe("Testing the new file modal", () => {
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
               name: "main",
-              extension: "py"
-            }
+              extension: "py",
+            },
           ],
-          project_type: "python"
+          project_type: "python",
         },
         nameError: "",
-      }
-    }
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><NewComponentButton /></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <NewComponentButton />
+      </Provider>,
+    );
+  });
 
-  test('Button renders', () => {
-    expect(screen.queryByText('filePane.newFileButton')).toBeInTheDocument()
-  })
+  test("Button renders", () => {
+    expect(screen.queryByText("filePane.newFileButton")).toBeInTheDocument();
+  });
 
-  test('Clicking button opens new file modal', () => {
-    const button = screen.queryByText('filePane.newFileButton')
-    fireEvent.click(button)
-    const expectedActions = [showNewFileModal()]
-    expect(store.getActions()).toEqual(expectedActions)
-  })
-})
+  test("Clicking button opens new file modal", () => {
+    const button = screen.queryByText("filePane.newFileButton");
+    fireEvent.click(button);
+    const expectedActions = [showNewFileModal()];
+    expect(store.getActions()).toEqual(expectedActions);
+  });
+});
diff --git a/src/components/Editor/NewInputPanelButton/NewInputPanelButton.js b/src/components/Editor/NewInputPanelButton/NewInputPanelButton.js
index ffd73b731..3b9b828c1 100644
--- a/src/components/Editor/NewInputPanelButton/NewInputPanelButton.js
+++ b/src/components/Editor/NewInputPanelButton/NewInputPanelButton.js
@@ -4,14 +4,18 @@ import { useDispatch } from "react-redux";
 import { addFilePanel } from "../EditorSlice";
 
 const NewInputPanelButton = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
 
   const openNewPanel = () => {
-    dispatch(addFilePanel())
-  }
+    dispatch(addFilePanel());
+  };
   return (
-    <Button className={'btn--primary'} buttonText='Add another panel' onClickHandler={openNewPanel} />
-  )
-}
+    <Button
+      className={"btn--primary"}
+      buttonText="Add another panel"
+      onClickHandler={openNewPanel}
+    />
+  );
+};
 
-export default NewInputPanelButton
+export default NewInputPanelButton;
diff --git a/src/components/Editor/Output/Output.js b/src/components/Editor/Output/Output.js
index eb7fc830e..3df4eeeb2 100644
--- a/src/components/Editor/Output/Output.js
+++ b/src/components/Editor/Output/Output.js
@@ -6,18 +6,16 @@ import RunBar from "../../RunButton/RunBar";
 
 const Output = () => {
   const project = useSelector((state) => state.editor.project);
-  const isEmbedded = useSelector((state) => state.editor.isEmbedded)
+  const isEmbedded = useSelector((state) => state.editor.isEmbedded);
   return (
     <>
       <ExternalFiles />
-      <div className='proj-runner-container'>
+      <div className="proj-runner-container">
         <RunnerFactory projectType={project.project_type} />
-        {
-          isEmbedded ? <RunBar /> : null
-        }
+        {isEmbedded ? <RunBar /> : null}
       </div>
     </>
-  )
-}
+  );
+};
 
-export default Output
+export default Output;
diff --git a/src/components/Editor/Output/Output.test.js b/src/components/Editor/Output/Output.test.js
index f2555aa34..952923c04 100644
--- a/src/components/Editor/Output/Output.test.js
+++ b/src/components/Editor/Output/Output.test.js
@@ -1,21 +1,25 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import Output from "./Output";
 
 test("Component renders", () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {
-          components: []
-        }
-      }
-    }
-    const store = mockStore(initialState);
-  const {container} = render(<Provider store={store}><Output/></Provider>)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {
+        components: [],
+      },
+    },
+  };
+  const store = mockStore(initialState);
+  const { container } = render(
+    <Provider store={store}>
+      <Output />
+    </Provider>,
+  );
   expect(container.lastChild).toHaveClass("proj-runner-container");
-})
+});
diff --git a/src/components/Editor/Project/Project.js b/src/components/Editor/Project/Project.js
index 09161239d..7751cdffb 100644
--- a/src/components/Editor/Project/Project.js
+++ b/src/components/Editor/Project/Project.js
@@ -1,129 +1,172 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import React, { useEffect, useState, useMemo } from 'react';
-import { useDispatch, useSelector} from 'react-redux'
-import 'react-tabs/style/react-tabs.css'
-import 'react-toastify/dist/ReactToastify.css'
-import { useContainerQuery } from 'react-container-query';
-import classnames from 'classnames';
+import React, { useEffect, useState, useMemo } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import "react-tabs/style/react-tabs.css";
+import "react-toastify/dist/ReactToastify.css";
+import { useContainerQuery } from "react-container-query";
+import classnames from "classnames";
 
-import './Project.scss';
-import Output from '../Output/Output'
-import RenameFile from '../../Modals/RenameFile'
-import { expireJustLoaded, setHasShownSavePrompt, setFocussedFileIndex, syncProject, openFile } from '../EditorSlice';
-import { isOwner } from '../../../utils/projectHelpers'
-import NotFoundModal from '../../Modals/NotFoundModal';
-import AccessDeniedNoAuthModal from '../../Modals/AccessDeniedNoAuthModal';
-import AccessDeniedWithAuthModal from '../../Modals/AccessDeniedWithAuthModal';
-import { showLoginPrompt, showSavedMessage, showSavePrompt } from '../../../utils/Notifications';
-import SideMenu from '../../Menus/SideMenu/SideMenu';
-import EditorInput from '../EditorInput/EditorInput';
-import NewFileModal from '../../Modals/NewFileModal';
-import ResizableWithHandle from '../../../utils/ResizableWithHandle';
-import { projContainer } from '../../../utils/containerQueries';
+import "./Project.scss";
+import Output from "../Output/Output";
+import RenameFile from "../../Modals/RenameFile";
+import {
+  expireJustLoaded,
+  setHasShownSavePrompt,
+  setFocussedFileIndex,
+  syncProject,
+  openFile,
+} from "../EditorSlice";
+import { isOwner } from "../../../utils/projectHelpers";
+import NotFoundModal from "../../Modals/NotFoundModal";
+import AccessDeniedNoAuthModal from "../../Modals/AccessDeniedNoAuthModal";
+import AccessDeniedWithAuthModal from "../../Modals/AccessDeniedWithAuthModal";
+import {
+  showLoginPrompt,
+  showSavedMessage,
+  showSavePrompt,
+} from "../../../utils/Notifications";
+import SideMenu from "../../Menus/SideMenu/SideMenu";
+import EditorInput from "../EditorInput/EditorInput";
+import NewFileModal from "../../Modals/NewFileModal";
+import ResizableWithHandle from "../../../utils/ResizableWithHandle";
+import { projContainer } from "../../../utils/containerQueries";
 
 const Project = (props) => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { forWebComponent } = props;
-  const user = useSelector((state) => state.auth.user)
-  const project = useSelector((state) => state.editor.project)
-  const modals = useSelector((state) => state.editor.modals)
-  const newFileModalShowing = useSelector((state) => state.editor.newFileModalShowing)
-  const renameFileModalShowing = useSelector((state) => state.editor.renameFileModalShowing)
-  const notFoundModalShowing = useSelector((state) => state.editor.notFoundModalShowing)
-  const accessDeniedNoAuthModalShowing = useSelector((state) => state.editor.accessDeniedNoAuthModalShowing)
-  const accessDeniedWithAuthModalShowing = useSelector((state) => state.editor.accessDeniedWithAuthModalShowing)
-  const justLoaded = useSelector((state) => state.editor.justLoaded)
-  const hasShownSavePrompt = useSelector((state) => state.editor.hasShownSavePrompt)
-  const openFiles = useSelector((state) => state.editor.openFiles)
-  const saving = useSelector((state) => state.editor.saving)
-  const autosave = useSelector((state) => state.editor.lastSaveAutosave)
+  const user = useSelector((state) => state.auth.user);
+  const project = useSelector((state) => state.editor.project);
+  const modals = useSelector((state) => state.editor.modals);
+  const newFileModalShowing = useSelector(
+    (state) => state.editor.newFileModalShowing,
+  );
+  const renameFileModalShowing = useSelector(
+    (state) => state.editor.renameFileModalShowing,
+  );
+  const notFoundModalShowing = useSelector(
+    (state) => state.editor.notFoundModalShowing,
+  );
+  const accessDeniedNoAuthModalShowing = useSelector(
+    (state) => state.editor.accessDeniedNoAuthModalShowing,
+  );
+  const accessDeniedWithAuthModalShowing = useSelector(
+    (state) => state.editor.accessDeniedWithAuthModalShowing,
+  );
+  const justLoaded = useSelector((state) => state.editor.justLoaded);
+  const hasShownSavePrompt = useSelector(
+    (state) => state.editor.hasShownSavePrompt,
+  );
+  const openFiles = useSelector((state) => state.editor.openFiles);
+  const saving = useSelector((state) => state.editor.saving);
+  const autosave = useSelector((state) => state.editor.lastSaveAutosave);
 
   useEffect(() => {
-    if (saving === 'success' && autosave === false) {
-      showSavedMessage()
+    if (saving === "success" && autosave === false) {
+      showSavedMessage();
     }
-  }, [saving, autosave])
+  }, [saving, autosave]);
 
   const switchToFileTab = (panelIndex, fileIndex) => {
-    dispatch(setFocussedFileIndex({panelIndex, fileIndex}))
-  }
+    dispatch(setFocussedFileIndex({ panelIndex, fileIndex }));
+  };
 
   const openFileTab = (fileName) => {
     if (openFiles.flat().includes(fileName)) {
-      const panelIndex = openFiles.map((fileNames) => (
-        fileNames.includes(fileName)
-      )).indexOf(true)
-      const fileIndex = openFiles[panelIndex].indexOf(fileName)
-      switchToFileTab(panelIndex, fileIndex)
+      const panelIndex = openFiles
+        .map((fileNames) => fileNames.includes(fileName))
+        .indexOf(true);
+      const fileIndex = openFiles[panelIndex].indexOf(fileName);
+      switchToFileTab(panelIndex, fileIndex);
     } else {
-      dispatch(openFile(fileName))
-      switchToFileTab(0, openFiles[0].length)
+      dispatch(openFile(fileName));
+      switchToFileTab(0, openFiles[0].length);
     }
-  }
+  };
 
   useEffect(() => {
     if (forWebComponent) {
-      return
+      return;
     }
-    if (user && localStorage.getItem('awaitingSave')) {
+    if (user && localStorage.getItem("awaitingSave")) {
       if (isOwner(user, project)) {
-        dispatch(syncProject('save')({project, accessToken: user.access_token, autosave: false}))
+        dispatch(
+          syncProject("save")({
+            project,
+            accessToken: user.access_token,
+            autosave: false,
+          }),
+        );
       } else if (user && project.identifier) {
-        dispatch(syncProject('remix')({project, accessToken: user.access_token}))
+        dispatch(
+          syncProject("remix")({ project, accessToken: user.access_token }),
+        );
       }
-      localStorage.removeItem('awaitingSave')
-      return
+      localStorage.removeItem("awaitingSave");
+      return;
     }
     let debouncer = setTimeout(() => {
       if (isOwner(user, project) && project.identifier) {
         if (justLoaded) {
-          dispatch(expireJustLoaded())
+          dispatch(expireJustLoaded());
         }
-        dispatch(syncProject('save')({ project, accessToken: user.access_token, autosave: true }));
-      }
-      else {
+        dispatch(
+          syncProject("save")({
+            project,
+            accessToken: user.access_token,
+            autosave: true,
+          }),
+        );
+      } else {
         if (justLoaded) {
-          dispatch(expireJustLoaded())
+          dispatch(expireJustLoaded());
         } else {
-          localStorage.setItem(project.identifier || 'project', JSON.stringify(project))
+          localStorage.setItem(
+            project.identifier || "project",
+            JSON.stringify(project),
+          );
           if (!hasShownSavePrompt) {
-            user ? showSavePrompt() : showLoginPrompt()
-            dispatch(setHasShownSavePrompt())
+            user ? showSavePrompt() : showLoginPrompt();
+            dispatch(setHasShownSavePrompt());
           }
         }
       }
     }, 2000);
 
-    return () => clearTimeout(debouncer)
-  }, [dispatch, forWebComponent, project, user])
+    return () => clearTimeout(debouncer);
+  }, [dispatch, forWebComponent, project, user]);
 
   const [params, containerRef] = useContainerQuery(projContainer);
-  const [defaultWidth, setDefaultWidth] = useState('auto');
-  const [defaultHeight, setDefaultHeight] = useState('auto');
-  const [maxWidth, setMaxWidth] = useState('100%');
-  const [handleDirection, setHandleDirection] = useState('right');
+  const [defaultWidth, setDefaultWidth] = useState("auto");
+  const [defaultHeight, setDefaultHeight] = useState("auto");
+  const [maxWidth, setMaxWidth] = useState("100%");
+  const [handleDirection, setHandleDirection] = useState("right");
 
   useMemo(() => {
-    const isDesktop = params['width-larger-than-880'];
+    const isDesktop = params["width-larger-than-880"];
 
-    setDefaultWidth(isDesktop ? '50%' : '100%');
-    setDefaultHeight(isDesktop ? '100%' : '50%');
-    setMaxWidth(isDesktop ? '75%' : '100%');
-    setHandleDirection(isDesktop ? 'right' : 'bottom');
+    setDefaultWidth(isDesktop ? "50%" : "100%");
+    setDefaultHeight(isDesktop ? "100%" : "50%");
+    setMaxWidth(isDesktop ? "75%" : "100%");
+    setHandleDirection(isDesktop ? "right" : "bottom");
   }, [params]);
 
   return (
-    <div className='proj'>
-      <div ref={containerRef} className={classnames('proj-container', {'proj-container--wc': forWebComponent})}>
-        {!forWebComponent ? <SideMenu openFileTab={openFileTab}/> : null}
-        <div className='proj-editor-wrapper'>
+    <div className="proj">
+      <div
+        ref={containerRef}
+        className={classnames("proj-container", {
+          "proj-container--wc": forWebComponent,
+        })}
+      >
+        {!forWebComponent ? <SideMenu openFileTab={openFileTab} /> : null}
+        <div className="proj-editor-wrapper">
           <ResizableWithHandle
-            data-testid='proj-editor-container'
-            className='proj-editor-container'
+            data-testid="proj-editor-container"
+            className="proj-editor-container"
             defaultWidth={defaultWidth}
             defaultHeight={defaultHeight}
             handleDirection={handleDirection}
-            minWidth='25%'
+            minWidth="25%"
             maxWidth={maxWidth}
           >
             <EditorInput />
@@ -131,13 +174,13 @@ const Project = (props) => {
           <Output />
         </div>
       </div>
-      {(newFileModalShowing) ? <NewFileModal /> : null}
-      {(renameFileModalShowing && modals.renameFile) ? <RenameFile /> : null}
-      {(notFoundModalShowing) ? <NotFoundModal /> : null}
-      {(accessDeniedNoAuthModalShowing) ? <AccessDeniedNoAuthModal /> : null}
-      {(accessDeniedWithAuthModalShowing) ? <AccessDeniedWithAuthModal /> : null}
+      {newFileModalShowing ? <NewFileModal /> : null}
+      {renameFileModalShowing && modals.renameFile ? <RenameFile /> : null}
+      {notFoundModalShowing ? <NotFoundModal /> : null}
+      {accessDeniedNoAuthModalShowing ? <AccessDeniedNoAuthModal /> : null}
+      {accessDeniedWithAuthModalShowing ? <AccessDeniedWithAuthModal /> : null}
     </div>
-  )
+  );
 };
 
 export default Project;
diff --git a/src/components/Editor/Project/Project.test.js b/src/components/Editor/Project/Project.test.js
index b3d8d63d2..eb5def959 100644
--- a/src/components/Editor/Project/Project.test.js
+++ b/src/components/Editor/Project/Project.test.js
@@ -1,452 +1,605 @@
 import React from "react";
-import { render, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import Project from "./Project";
-import { expireJustLoaded, setHasShownSavePrompt, syncProject } from "../EditorSlice";
-import { showLoginPrompt, showSavedMessage, showSavePrompt } from "../../../utils/Notifications";
-
-window.HTMLElement.prototype.scrollIntoView = jest.fn()
-
-jest.mock('axios');
-
-jest.mock('react-router-dom', () => ({
-  ...jest.requireActual('react-router-dom'),
-  useNavigate: () => jest.fn()
+import {
+  expireJustLoaded,
+  setHasShownSavePrompt,
+  syncProject,
+} from "../EditorSlice";
+import {
+  showLoginPrompt,
+  showSavedMessage,
+  showSavePrompt,
+} from "../../../utils/Notifications";
+
+window.HTMLElement.prototype.scrollIntoView = jest.fn();
+
+jest.mock("axios");
+
+jest.mock("react-router-dom", () => ({
+  ...jest.requireActual("react-router-dom"),
+  useNavigate: () => jest.fn(),
 }));
 
-jest.mock('../EditorSlice', () => ({
-  ...jest.requireActual('../EditorSlice'),
-  syncProject: jest.fn((_) => jest.fn())
-}))
+jest.mock("../EditorSlice", () => ({
+  ...jest.requireActual("../EditorSlice"),
+  syncProject: jest.fn((_) => jest.fn()),
+}));
 
-jest.mock('../../../utils/Notifications')
+jest.mock("../../../utils/Notifications");
 
-jest.useFakeTimers()
+jest.useFakeTimers();
 
 const user1 = {
-  access_token: 'myAccessToken',
+  access_token: "myAccessToken",
   profile: {
-    user: 'b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf'
-  }
-}
+    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+  },
+};
 
 const user2 = {
-  access_token: 'myAccessToken',
+  access_token: "myAccessToken",
   profile: {
-    user: 'cd8a5b3d-f7bb-425e-908f-1386decd6bb1'
-  }
-}
+    user: "cd8a5b3d-f7bb-425e-908f-1386decd6bb1",
+  },
+};
 
 const project = {
-  name: 'hello world',
-    project_type: 'python',
-    identifier: 'hello-world-project',
-    components: [
-      {
-        name: 'main',
-        extension: 'py',
-        content: '# hello'
-      }
-    ],
-    user_id: user1.profile.user
-}
+  name: "hello world",
+  project_type: "python",
+  identifier: "hello-world-project",
+  components: [
+    {
+      name: "main",
+      extension: "py",
+      content: "# hello",
+    },
+  ],
+  user_id: user1.profile.user,
+};
 
 test("Renders with file menu if not for web component", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
-        components: []
+        components: [],
       },
       openFiles: [[]],
-      focussedFileIndices: [0]
+      focussedFileIndices: [0],
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  const {queryByText} = render(<Provider store={store}><div id="app"><Project/></div></Provider>)
-  expect(queryByText('filePane.files')).not.toBeNull()
-})
+  const { queryByText } = render(
+    <Provider store={store}>
+      <div id="app">
+        <Project />
+      </div>
+    </Provider>,
+  );
+  expect(queryByText("filePane.files")).not.toBeNull();
+});
 
 test("Renders without file menu if for web component", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
-        components: []
+        components: [],
       },
       openFiles: [[]],
-      focussedFileIndices: [0]
+      focussedFileIndices: [0],
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  const {queryByText} = render(<Provider store={store}><Project forWebComponent={true}/></Provider>)
-  expect(queryByText('filePane.files')).toBeNull()
-})
-
-describe('When not logged in and just loaded', () => {
-  let mockedStore
+  const { queryByText } = render(
+    <Provider store={store}>
+      <Project forWebComponent={true} />
+    </Provider>,
+  );
+  expect(queryByText("filePane.files")).toBeNull();
+});
+
+describe("When not logged in and just loaded", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        loading: 'success',
+        loading: "success",
         justLoaded: true,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
-      auth: {}
-    }
+      auth: {},
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Expires justLoaded', async () => {
-    await waitFor(() => expect(mockedStore.getActions()).toEqual([expireJustLoaded()]), {timeout: 2100})
-  })
-})
-
-describe('When not logged in and not just loaded', () => {
-  let mockedStore
+    localStorage.clear();
+  });
+
+  test("Expires justLoaded", async () => {
+    await waitFor(
+      () => expect(mockedStore.getActions()).toEqual([expireJustLoaded()]),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When not logged in and not just loaded", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        loading: 'success',
+        loading: "success",
         justLoaded: false,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
-      auth: {}
-    }
+      auth: {},
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
+    localStorage.clear();
+  });
 
-  test('Login prompt shown', async () => {
-    await waitFor(() => expect(showLoginPrompt).toHaveBeenCalled(), {timeout: 2100})
-  })
-
-  test('Dispatches save prompt shown action', async () => {
-    await waitFor(() => expect(mockedStore.getActions()).toEqual([setHasShownSavePrompt()]), {timeout: 2100})
-  })
-
-  test('Project saved in localStorage', async () => {
-    await waitFor(() => expect(localStorage.getItem('hello-world-project')).toEqual(JSON.stringify(project)), {timeout: 2100})
-  })
-})
-
-describe('When not logged in and has been prompted to login to save', () => {
-  let mockedStore
+  test("Login prompt shown", async () => {
+    await waitFor(() => expect(showLoginPrompt).toHaveBeenCalled(), {
+      timeout: 2100,
+    });
+  });
+
+  test("Dispatches save prompt shown action", async () => {
+    await waitFor(
+      () => expect(mockedStore.getActions()).toEqual([setHasShownSavePrompt()]),
+      { timeout: 2100 },
+    );
+  });
+
+  test("Project saved in localStorage", async () => {
+    await waitFor(
+      () =>
+        expect(localStorage.getItem("hello-world-project")).toEqual(
+          JSON.stringify(project),
+        ),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When not logged in and has been prompted to login to save", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        loading: 'success',
+        loading: "success",
         justLoaded: false,
         hasShownSavePrompt: true,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
-      auth: {}
-    }
+      auth: {},
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Login prompt shown', async () => {
-    jest.runAllTimers()
-    await waitFor(() => expect(showLoginPrompt).not.toHaveBeenCalled(), {timeout: 2100})
-  })
+    localStorage.clear();
+  });
 
-  test('Project saved in localStorage', async () => {
-    await waitFor(() => expect(localStorage.getItem('hello-world-project')).toEqual(JSON.stringify(project)), {timeout: 2100})
-  })
-})
-
-describe('When logged in and user does not own project and just loaded', () => {
-  let mockedStore
+  test("Login prompt shown", async () => {
+    jest.runAllTimers();
+    await waitFor(() => expect(showLoginPrompt).not.toHaveBeenCalled(), {
+      timeout: 2100,
+    });
+  });
+
+  test("Project saved in localStorage", async () => {
+    await waitFor(
+      () =>
+        expect(localStorage.getItem("hello-world-project")).toEqual(
+          JSON.stringify(project),
+        ),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When logged in and user does not own project and just loaded", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project,
-        loading: 'success',
+        loading: "success",
         justLoaded: true,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user2
-      }
-    }
+        user: user2,
+      },
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Expires justLoaded', async () => {
-    await waitFor(() => expect(mockedStore.getActions()).toEqual([expireJustLoaded()]), {timeout: 2100})
-  })
-})
-
-describe('When logged in and user does not own project and not just loaded', () => {
-  let mockedStore
+    localStorage.clear();
+  });
+
+  test("Expires justLoaded", async () => {
+    await waitFor(
+      () => expect(mockedStore.getActions()).toEqual([expireJustLoaded()]),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When logged in and user does not own project and not just loaded", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project,
-        loading: 'success',
+        loading: "success",
         justLoaded: false,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user2
-      }
-    }
+        user: user2,
+      },
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Save prompt shown', async () => {
-    await waitFor(() => expect(showSavePrompt).toHaveBeenCalled(), {timeout: 2100})
-  })
-
-  test('Dispatches save prompt shown action', async () => {
-    await waitFor(() => expect(mockedStore.getActions()).toEqual([setHasShownSavePrompt()]), {timeout: 2100})
-  })
-
-  test('Project saved in localStorage', async () => {
-    await waitFor(() => expect(localStorage.getItem('hello-world-project')).toEqual(JSON.stringify(project)), {timeout: 2100})
-  })
-})
+    localStorage.clear();
+  });
 
-describe('When logged in and user does not own project and prompted to save', () => {
-  let mockedStore
+  test("Save prompt shown", async () => {
+    await waitFor(() => expect(showSavePrompt).toHaveBeenCalled(), {
+      timeout: 2100,
+    });
+  });
+
+  test("Dispatches save prompt shown action", async () => {
+    await waitFor(
+      () => expect(mockedStore.getActions()).toEqual([setHasShownSavePrompt()]),
+      { timeout: 2100 },
+    );
+  });
+
+  test("Project saved in localStorage", async () => {
+    await waitFor(
+      () =>
+        expect(localStorage.getItem("hello-world-project")).toEqual(
+          JSON.stringify(project),
+        ),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When logged in and user does not own project and prompted to save", () => {
+  let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project,
-        loading: 'success',
+        loading: "success",
         justLoaded: false,
         hasShownSavePrompt: true,
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user2
-      }
-    }
+        user: user2,
+      },
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
+    localStorage.clear();
+  });
 
-  test('Save prompt not shown again', async () => {
-    jest.runAllTimers()
-    await waitFor(() => expect(showSavePrompt).not.toHaveBeenCalled(), {timeout: 2100})
-  })
-
-  test('Project saved in localStorage', async () => {
-    await waitFor(() => expect(localStorage.getItem('hello-world-project')).toEqual(JSON.stringify(project)), {timeout: 2100})
-  })
-})
-
-describe('When logged in and user does not own project and awaiting save', () => {
-  let mockedStore
-  let remixProject
-  let remixAction
+  test("Save prompt not shown again", async () => {
+    jest.runAllTimers();
+    await waitFor(() => expect(showSavePrompt).not.toHaveBeenCalled(), {
+      timeout: 2100,
+    });
+  });
+
+  test("Project saved in localStorage", async () => {
+    await waitFor(
+      () =>
+        expect(localStorage.getItem("hello-world-project")).toEqual(
+          JSON.stringify(project),
+        ),
+      { timeout: 2100 },
+    );
+  });
+});
+
+describe("When logged in and user does not own project and awaiting save", () => {
+  let mockedStore;
+  let remixProject;
+  let remixAction;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project,
-        loading: 'success',
+        loading: "success",
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user2
-      }
-    }
+        user: user2,
+      },
+    };
     mockedStore = mockStore(initialState);
-    localStorage.setItem('awaitingSave', 'true')
-    remixAction = {type: 'REMIX_PROJECT' }
-    remixProject = jest.fn(() => remixAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (remixProject)))
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    localStorage.setItem("awaitingSave", "true");
+    remixAction = { type: "REMIX_PROJECT" };
+    remixProject = jest.fn(() => remixAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => remixProject));
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Project remixed and saved to database', async () => {
-    await waitFor(() => expect(remixProject).toHaveBeenCalledWith({project, accessToken: user2.access_token}), {timeout: 2100})
-    expect(mockedStore.getActions()[0]).toEqual(remixAction)
-  })
-})
-
-describe('When logged in and project has no identifier and awaiting save', () => {
-  let mockedStore
-  let saveProject
-  let saveAction
+    localStorage.clear();
+  });
+
+  test("Project remixed and saved to database", async () => {
+    await waitFor(
+      () =>
+        expect(remixProject).toHaveBeenCalledWith({
+          project,
+          accessToken: user2.access_token,
+        }),
+      { timeout: 2100 },
+    );
+    expect(mockedStore.getActions()[0]).toEqual(remixAction);
+  });
+});
+
+describe("When logged in and project has no identifier and awaiting save", () => {
+  let mockedStore;
+  let saveProject;
+  let saveAction;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
-        project: {...project, identifier: null},
-        loading: 'success',
+        project: { ...project, identifier: null },
+        loading: "success",
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user2
-      }
-    }
+        user: user2,
+      },
+    };
     mockedStore = mockStore(initialState);
-    localStorage.setItem('awaitingSave', 'true')
-    saveAction = {type: 'SAVE_PROJECT' }
-    saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
+    localStorage.setItem("awaitingSave", "true");
+    saveAction = { type: "SAVE_PROJECT" };
+    saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
 
   afterEach(() => {
-    localStorage.clear()
-  })
-
-  test('Project saved to database', async () => {
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({project: {...project, identifier: null}, accessToken: user2.access_token, autosave: false}), {timeout: 2100})
-    expect(mockedStore.getActions()[0]).toEqual(saveAction)
-  })
-})
-
-describe('When logged in and user owns project', () => {
-
+    localStorage.clear();
+  });
+
+  test("Project saved to database", async () => {
+    await waitFor(
+      () =>
+        expect(saveProject).toHaveBeenCalledWith({
+          project: { ...project, identifier: null },
+          accessToken: user2.access_token,
+          autosave: false,
+        }),
+      { timeout: 2100 },
+    );
+    expect(mockedStore.getActions()[0]).toEqual(saveAction);
+  });
+});
+
+describe("When logged in and user owns project", () => {
   let mockedStore;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project,
-        loading: 'success',
+        loading: "success",
         openFiles: [[]],
-        focussedFileIndices: [0]
+        focussedFileIndices: [0],
       },
       auth: {
-        user: user1
-      }
-    }
+        user: user1,
+      },
+    };
     mockedStore = mockStore(initialState);
-    render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  })
-
-  test('Project autosaved to database', async () => {
-    const saveAction = {type: 'SAVE_PROJECT' }
-    const saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({project, accessToken: user1.access_token, autosave: true}), {timeout: 2100})
-    expect(mockedStore.getActions()[0]).toEqual(saveAction)
-  })
-})
-
-test('Successful manual save prompts project saved message', async () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+    render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+  });
+
+  test("Project autosaved to database", async () => {
+    const saveAction = { type: "SAVE_PROJECT" };
+    const saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    await waitFor(
+      () =>
+        expect(saveProject).toHaveBeenCalledWith({
+          project,
+          accessToken: user1.access_token,
+          autosave: true,
+        }),
+      { timeout: 2100 },
+    );
+    expect(mockedStore.getActions()[0]).toEqual(saveAction);
+  });
+});
+
+test("Successful manual save prompts project saved message", async () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
-        components: []
+        components: [],
       },
       openFiles: [[]],
       focussedFileIndices: [0],
-      saving: 'success',
-      lastSaveAutosave: false
+      saving: "success",
+      lastSaveAutosave: false,
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const mockedStore = mockStore(initialState);
-  render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-  await waitFor(() => expect(showSavedMessage).toHaveBeenCalled())
-})
+  render(
+    <Provider store={mockedStore}>
+      <div id="app">
+        <Project />
+      </div>
+    </Provider>,
+  );
+  await waitFor(() => expect(showSavedMessage).toHaveBeenCalled());
+});
 
 // TODO: Write test for successful autosave not prompting the project saved message as per the above
 
-describe('When not logged in and falling on default container width', () => {
+describe("When not logged in and falling on default container width", () => {
   test("Shows bottom drag bar with expected params", () => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        openFiles: [['main.py']],
-        focussedFileIndices: [0]
+        openFiles: [["main.py"]],
+        focussedFileIndices: [0],
       },
-      auth: {}
-    }
+      auth: {},
+    };
     const mockedStore = mockStore(initialState);
-    const { getByTestId } = render(<Provider store={mockedStore}><div id="app"><Project/></div></Provider>);
-
-    const container = getByTestId('proj-editor-container');
+    const { getByTestId } = render(
+      <Provider store={mockedStore}>
+        <div id="app">
+          <Project />
+        </div>
+      </Provider>,
+    );
+
+    const container = getByTestId("proj-editor-container");
     expect(container).toHaveStyle({
-      'min-width': '25%',
-      'max-width': '100%',
-      'width': '100%',
-      'height': '50%',
+      "min-width": "25%",
+      "max-width": "100%",
+      width: "100%",
+      height: "50%",
     });
 
-    expect(container.getElementsByClassName('resizable-with-handle__handle--bottom').length).toBe(1);
-  })
-})
+    expect(
+      container.getElementsByClassName("resizable-with-handle__handle--bottom")
+        .length,
+    ).toBe(1);
+  });
+});
diff --git a/src/components/Editor/ProjectComponentLoader/ProjectComponentLoader.test.js b/src/components/Editor/ProjectComponentLoader/ProjectComponentLoader.test.js
index 1f2b9dd2a..4e6fef29b 100644
--- a/src/components/Editor/ProjectComponentLoader/ProjectComponentLoader.test.js
+++ b/src/components/Editor/ProjectComponentLoader/ProjectComponentLoader.test.js
@@ -1,60 +1,73 @@
 import React from "react";
-import { render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import ProjectComponentLoader from "./ProjectComponentLoader";
 import { setProject } from "../EditorSlice";
 import { defaultPythonProject } from "../../../utils/defaultProjects";
 
-jest.mock('react-router-dom', () => ({
-    ...jest.requireActual('react-router-dom'),
-    useNavigate: () => jest.fn()
+jest.mock("react-router-dom", () => ({
+  ...jest.requireActual("react-router-dom"),
+  useNavigate: () => jest.fn(),
 }));
 
 test("Renders loading message if loading is pending", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
-      loading: 'pending'
+      loading: "pending",
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><ProjectComponentLoader match={{params: {}}}/></Provider>)
-  expect(screen.queryByText('project.loading')).toBeInTheDocument()
-})
+  render(
+    <Provider store={store}>
+      <ProjectComponentLoader match={{ params: {} }} />
+    </Provider>,
+  );
+  expect(screen.queryByText("project.loading")).toBeInTheDocument();
+});
 
 test("Loads default project if loading fails", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
-      loading: 'failed'
+      loading: "failed",
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><ProjectComponentLoader match={{params: {}}}/></Provider>)
-  const expectedActions = [setProject(defaultPythonProject)]
-  expect(store.getActions()).toEqual(expectedActions)
-})
+  render(
+    <Provider store={store}>
+      <ProjectComponentLoader match={{ params: {} }} />
+    </Provider>,
+  );
+  const expectedActions = [setProject(defaultPythonProject)];
+  expect(store.getActions()).toEqual(expectedActions);
+});
 
 test("Does not render loading message if loading is success", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
-        components: []
+        components: [],
       },
       openFiles: [[]],
       focussedFileIndices: [0],
-      loading: 'success'
+      loading: "success",
     },
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><div id='app'></div><ProjectComponentLoader match={{params: {}}}/></Provider>)
-  expect(screen.queryByText('project.loading')).not.toBeInTheDocument()
-})
+  render(
+    <Provider store={store}>
+      <div id="app"></div>
+      <ProjectComponentLoader match={{ params: {} }} />
+    </Provider>,
+  );
+  expect(screen.queryByText("project.loading")).not.toBeInTheDocument();
+});
diff --git a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.js b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.js
index 4eba59b5d..b980e90a5 100644
--- a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.js
+++ b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.js
@@ -16,11 +16,11 @@ function HtmlRunner() {
   const projectCode = useSelector((state) => state.editor.project.components);
   const projectImages = useSelector((state) => state.editor.project.image_list);
   const codeRunTriggered = useSelector(
-    (state) => state.editor.codeRunTriggered
+    (state) => state.editor.codeRunTriggered,
   );
   const firstPanelIndex = 0;
   const focussedFileIndex = useSelector(
-    (state) => state.editor.focussedFileIndices
+    (state) => state.editor.focussedFileIndices,
   )[firstPanelIndex];
   const openFiles = useSelector((state) => state.editor.openFiles)[
     firstPanelIndex
@@ -38,7 +38,7 @@ function HtmlRunner() {
 
   const focussedComponent = (fileName = "index.html") =>
     projectCode.filter(
-      (component) => `${component.name}.${component.extension}` === fileName
+      (component) => `${component.name}.${component.extension}` === fileName,
     )[0];
 
   const previewable = (file) => file.endsWith(".html");
@@ -46,7 +46,7 @@ function HtmlRunner() {
   const [previewFile, setPreviewFile] = useState(
     previewable(openFiles[focussedFileIndex])
       ? openFiles[focussedFileIndex]
-      : "index.html"
+      : "index.html",
   );
 
   const showModal = () => {
@@ -66,7 +66,7 @@ function HtmlRunner() {
       projectImages.forEach((image) => {
         updatedProjectFile.content = updatedProjectFile.content.replace(
           image.filename,
-          image.url
+          image.url,
         );
       });
     }
@@ -131,7 +131,7 @@ function HtmlRunner() {
     // replace href's with blob urls
     hrefNodes.forEach((hrefNode) => {
       const projectFile = projectCode.filter(
-        (file) => `${file.name}.${file.extension}` === hrefNode.attrs.href
+        (file) => `${file.name}.${file.extension}` === hrefNode.attrs.href,
       );
       // remove target blanks
       if (hrefNode.attrs?.target === "_blank") {
@@ -144,7 +144,7 @@ function HtmlRunner() {
         if (parentTag(hrefNode, "head")) {
           const projectFileBlob = getBlobURL(
             cssProjectImgs(projectFile[0]).content,
-            `text/${projectFile[0].extension}`
+            `text/${projectFile[0].extension}`,
           );
           hrefNode.setAttribute("href", projectFileBlob);
         } else {
@@ -170,11 +170,11 @@ function HtmlRunner() {
     const srcNodes = indexPage.querySelectorAll("[src]");
     srcNodes.forEach((srcNode) => {
       const projectImage = projectImages.filter(
-        (component) => component.filename === srcNode.attrs.src
+        (component) => component.filename === srcNode.attrs.src,
       );
       srcNode.setAttribute(
         "src",
-        !!projectImage.length ? projectImage[0].url : ""
+        !!projectImage.length ? projectImage[0].url : "",
       );
     });
 
diff --git a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js
index a513730dc..2dbc72a4e 100644
--- a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js
+++ b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js
@@ -46,7 +46,7 @@ describe("When page first loaded", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -75,7 +75,7 @@ describe("When focussed on another HTML file", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -112,7 +112,7 @@ describe("When page first loaded in embedded viewer", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -122,7 +122,7 @@ describe("When page first loaded in embedded viewer", () => {
 
   test("Dispatches action to trigger code run", () => {
     expect(store.getActions()).toEqual(
-      expect.arrayContaining([triggerCodeRun()])
+      expect.arrayContaining([triggerCodeRun()]),
     );
   });
 });
@@ -151,7 +151,7 @@ describe("When run run triggered", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -163,7 +163,7 @@ describe("When run run triggered", () => {
 
   test("Dispatches action to end code run", () => {
     expect(store.getActions()).toEqual(
-      expect.arrayContaining([codeRunHandled()])
+      expect.arrayContaining([codeRunHandled()]),
     );
   });
 });
@@ -201,7 +201,7 @@ describe("When an external link is rendered", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -246,7 +246,7 @@ describe("When a new tab link is rendered", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
@@ -281,7 +281,7 @@ describe("When an allowed link is rendered", () => {
         <div id="app">
           <HtmlRunner />
         </div>
-      </Provider>
+      </Provider>,
     );
   });
 
diff --git a/src/components/Editor/Runners/PythonRunner/OutputViewToggle.js b/src/components/Editor/Runners/PythonRunner/OutputViewToggle.js
index 7a79b20ee..6b466fbc7 100644
--- a/src/components/Editor/Runners/PythonRunner/OutputViewToggle.js
+++ b/src/components/Editor/Runners/PythonRunner/OutputViewToggle.js
@@ -5,44 +5,54 @@ import Button from "../../../Button/Button";
 import { setIsSplitView } from "../../EditorSlice";
 import { useTranslation } from "react-i18next";
 
-import './OutputViewToggle.scss';
+import "./OutputViewToggle.scss";
 
 const OutputViewToggle = () => {
-
-  const isSplitView = useSelector((state) => state.editor.isSplitView)
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered)
-  const drawTriggered = useSelector((state) => state.editor.drawTriggered)
-  const dispatch = useDispatch()
-  const { t } = useTranslation()
+  const isSplitView = useSelector((state) => state.editor.isSplitView);
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
+  const drawTriggered = useSelector((state) => state.editor.drawTriggered);
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
 
   const switchToTabbedView = () => {
-    dispatch(setIsSplitView(false))
-  }
+    dispatch(setIsSplitView(false));
+  };
 
   const switchToSplitView = () => {
-    dispatch(setIsSplitView(true))
-  }
+    dispatch(setIsSplitView(true));
+  };
 
   return (
-    <div className = {`output-view-toggle`} disabled = {codeRunTriggered || drawTriggered}>
-      <Button className = {`btn--small output-view-toggle__button output-view-toggle__button--tabbed${isSplitView ? "" : " output-view-toggle__button--active"}` }
+    <div
+      className={`output-view-toggle`}
+      disabled={codeRunTriggered || drawTriggered}
+    >
+      <Button
+        className={`btn--small output-view-toggle__button output-view-toggle__button--tabbed${
+          isSplitView ? "" : " output-view-toggle__button--active"
+        }`}
         buttonOuter
-        disabled = {codeRunTriggered || drawTriggered}
-        label={t('outputViewToggle.buttonTabLabel')}
-        title={t('outputViewToggle.buttonTabTitle')}
+        disabled={codeRunTriggered || drawTriggered}
+        label={t("outputViewToggle.buttonTabLabel")}
+        title={t("outputViewToggle.buttonTabTitle")}
         ButtonIcon={TabbedViewIcon}
         onClickHandler={switchToTabbedView}
       />
-      <Button className = {`btn--small output-view-toggle__button output-view-toggle__button--split${isSplitView ? " output-view-toggle__button--active" : ""}` }
+      <Button
+        className={`btn--small output-view-toggle__button output-view-toggle__button--split${
+          isSplitView ? " output-view-toggle__button--active" : ""
+        }`}
         buttonOuter
-        disabled = {codeRunTriggered || drawTriggered}
-        label={t('outputViewToggle.buttonSplitLabel')}
-        title={t('outputViewToggle.buttonSplitTitle')}
+        disabled={codeRunTriggered || drawTriggered}
+        label={t("outputViewToggle.buttonSplitLabel")}
+        title={t("outputViewToggle.buttonSplitTitle")}
         ButtonIcon={SplitViewIcon}
         onClickHandler={switchToSplitView}
       />
     </div>
-  )
-}
+  );
+};
 
-export default OutputViewToggle
+export default OutputViewToggle;
diff --git a/src/components/Editor/Runners/PythonRunner/OutputViewToggle.test.js b/src/components/Editor/Runners/PythonRunner/OutputViewToggle.test.js
index 176e0f189..94c90811b 100644
--- a/src/components/Editor/Runners/PythonRunner/OutputViewToggle.test.js
+++ b/src/components/Editor/Runners/PythonRunner/OutputViewToggle.test.js
@@ -1,151 +1,203 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import OutputViewToggle from "./OutputViewToggle";
 import { setIsSplitView } from "../../EditorSlice";
 
-describe('When in tabbed view', () => {
+describe("When in tabbed view", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         isSplitView: false,
-      }
-    }
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-  })
-
-  test('Tabbed view button is active', () => {
-    expect(screen.getAllByRole('button')[0]).toHaveClass('output-view-toggle__button--tabbed output-view-toggle__button--active')
-  })
-
-  test('Split view button is not active', () => {
-    expect(screen.getAllByRole('button')[1]).toHaveClass('output-view-toggle__button--split')
-    expect(screen.getAllByRole('button')[1]).not.toHaveClass('output-view-toggle__button--active')
-  })
-})
-
-describe('When in split view', () => {
+    render(
+      <Provider store={store}>
+        <OutputViewToggle />
+      </Provider>,
+    );
+  });
+
+  test("Tabbed view button is active", () => {
+    expect(screen.getAllByRole("button")[0]).toHaveClass(
+      "output-view-toggle__button--tabbed output-view-toggle__button--active",
+    );
+  });
+
+  test("Split view button is not active", () => {
+    expect(screen.getAllByRole("button")[1]).toHaveClass(
+      "output-view-toggle__button--split",
+    );
+    expect(screen.getAllByRole("button")[1]).not.toHaveClass(
+      "output-view-toggle__button--active",
+    );
+  });
+});
+
+describe("When in split view", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         isSplitView: true,
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-  })
-
-  test('Split view button is active', () => {
-    expect(screen.getAllByRole('button')[1]).toHaveClass('output-view-toggle__button--split output-view-toggle__button--active')
-  })
-
-  test('Tabbed view button is not active', () => {
-    expect(screen.getAllByRole('button')[0]).toHaveClass('output-view-toggle__button--tabbed')
-    expect(screen.getAllByRole('button')[0]).not.toHaveClass('output-view-toggle__button--active')
-  })
-})
-
-test('Clicking tabbed view icon switches to tabbed view', () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {}
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-    fireEvent.click(screen.getAllByRole('button')[0])
-    const expectedActions = [setIsSplitView(false)]
-    expect(store.getActions()).toEqual(expectedActions);
-})
-
-test('Clicking split view icon switches to tabbed view', () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {}
-    }
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-    fireEvent.click(screen.getAllByRole('button')[1])
-    const expectedActions = [setIsSplitView(true)]
-    expect(store.getActions()).toEqual(expectedActions);
-})
-
-describe('When in a code run is triggered', () => {
+    render(
+      <Provider store={store}>
+        <OutputViewToggle />
+      </Provider>,
+    );
+  });
+
+  test("Split view button is active", () => {
+    expect(screen.getAllByRole("button")[1]).toHaveClass(
+      "output-view-toggle__button--split output-view-toggle__button--active",
+    );
+  });
+
+  test("Tabbed view button is not active", () => {
+    expect(screen.getAllByRole("button")[0]).toHaveClass(
+      "output-view-toggle__button--tabbed",
+    );
+    expect(screen.getAllByRole("button")[0]).not.toHaveClass(
+      "output-view-toggle__button--active",
+    );
+  });
+});
+
+test("Clicking tabbed view icon switches to tabbed view", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {},
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <OutputViewToggle />
+    </Provider>,
+  );
+  fireEvent.click(screen.getAllByRole("button")[0]);
+  const expectedActions = [setIsSplitView(false)];
+  expect(store.getActions()).toEqual(expectedActions);
+});
+
+test("Clicking split view icon switches to tabbed view", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {},
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <OutputViewToggle />
+    </Provider>,
+  );
+  fireEvent.click(screen.getAllByRole("button")[1]);
+  const expectedActions = [setIsSplitView(true)];
+  expect(store.getActions()).toEqual(expectedActions);
+});
+
+describe("When in a code run is triggered", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         codeRunTriggered: true,
-      }
-    }
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-  })
-
-  test('Tabbed view button is disabled', () => {
-    expect(screen.getAllByRole('button')[0]).toHaveClass('output-view-toggle__button--tabbed')
-    expect(screen.getAllByRole('button')[0]).toBeDisabled()
-  })
-
-  test('Split view button is disabled', () => {
-    expect(screen.getAllByRole('button')[1]).toHaveClass('output-view-toggle__button--split')
-    expect(screen.getAllByRole('button')[1]).toBeDisabled()
-  })
-})
-
-describe('When in a draw run is triggered', () => {
+    render(
+      <Provider store={store}>
+        <OutputViewToggle />
+      </Provider>,
+    );
+  });
+
+  test("Tabbed view button is disabled", () => {
+    expect(screen.getAllByRole("button")[0]).toHaveClass(
+      "output-view-toggle__button--tabbed",
+    );
+    expect(screen.getAllByRole("button")[0]).toBeDisabled();
+  });
+
+  test("Split view button is disabled", () => {
+    expect(screen.getAllByRole("button")[1]).toHaveClass(
+      "output-view-toggle__button--split",
+    );
+    expect(screen.getAllByRole("button")[1]).toBeDisabled();
+  });
+});
+
+describe("When in a draw run is triggered", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         drawTriggered: true,
-      }
-    }
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-  })
-
-  test('Tabbed view button is disabled', () => {
-    expect(screen.getAllByRole('button')[0]).toHaveClass('output-view-toggle__button--tabbed')
-    expect(screen.getAllByRole('button')[0]).toBeDisabled()
-  })
-
-  test('Split view button is disabled', () => {
-    expect(screen.getAllByRole('button')[1]).toHaveClass('output-view-toggle__button--split')
-    expect(screen.getAllByRole('button')[1]).toBeDisabled()
-  })
-})
-
-describe('When in neither a code run nor a draw run is triggered', () => {
+    render(
+      <Provider store={store}>
+        <OutputViewToggle />
+      </Provider>,
+    );
+  });
+
+  test("Tabbed view button is disabled", () => {
+    expect(screen.getAllByRole("button")[0]).toHaveClass(
+      "output-view-toggle__button--tabbed",
+    );
+    expect(screen.getAllByRole("button")[0]).toBeDisabled();
+  });
+
+  test("Split view button is disabled", () => {
+    expect(screen.getAllByRole("button")[1]).toHaveClass(
+      "output-view-toggle__button--split",
+    );
+    expect(screen.getAllByRole("button")[1]).toBeDisabled();
+  });
+});
+
+describe("When in neither a code run nor a draw run is triggered", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
-        codeRunTriggered:false,
+        codeRunTriggered: false,
         drawTriggered: false,
-      }
-    }
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><OutputViewToggle /></Provider>);
-  })
-
-  test('Tabbed view button is enabled', () => {
-    expect(screen.getAllByRole('button')[0]).toHaveClass('output-view-toggle__button--tabbed')
-    expect(screen.getAllByRole('button')[0]).not.toBeDisabled()
-  })
-
-  test('Split view button is enabled', () => {
-    expect(screen.getAllByRole('button')[1]).toHaveClass('output-view-toggle__button--split')
-    expect(screen.getAllByRole('button')[1]).not.toBeDisabled()
-  })
-})
+    render(
+      <Provider store={store}>
+        <OutputViewToggle />
+      </Provider>,
+    );
+  });
+
+  test("Tabbed view button is enabled", () => {
+    expect(screen.getAllByRole("button")[0]).toHaveClass(
+      "output-view-toggle__button--tabbed",
+    );
+    expect(screen.getAllByRole("button")[0]).not.toBeDisabled();
+  });
+
+  test("Split view button is enabled", () => {
+    expect(screen.getAllByRole("button")[1]).toHaveClass(
+      "output-view-toggle__button--split",
+    );
+    expect(screen.getAllByRole("button")[1]).not.toBeDisabled();
+  });
+});
diff --git a/src/components/Editor/Runners/PythonRunner/PythonRunner.js b/src/components/Editor/Runners/PythonRunner/PythonRunner.js
index 500d46631..4e965fdb8 100644
--- a/src/components/Editor/Runners/PythonRunner/PythonRunner.js
+++ b/src/components/Editor/Runners/PythonRunner/PythonRunner.js
@@ -1,74 +1,84 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import './PythonRunner.scss';
-import React, { useContext, useEffect, useRef, useState } from 'react';
+import "./PythonRunner.scss";
+import React, { useContext, useEffect, useRef, useState } from "react";
 import * as Sentry from "@sentry/browser";
-import { useSelector, useDispatch } from 'react-redux'
-import { useTranslation } from 'react-i18next';
-import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
-import Sk from "skulpt"
-import { setError, codeRunHandled, stopDraw, setSenseHatEnabled, triggerDraw } from '../../EditorSlice'
-import ErrorMessage from '../../ErrorMessage/ErrorMessage'
-
-import store from '../../../../app/store'
-import VisualOutputPane from './VisualOutputPane';
-import OutputViewToggle from './OutputViewToggle';
-import { SettingsContext } from '../../../../settings';
+import { useSelector, useDispatch } from "react-redux";
+import { useTranslation } from "react-i18next";
+import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
+import Sk from "skulpt";
+import {
+  setError,
+  codeRunHandled,
+  stopDraw,
+  setSenseHatEnabled,
+  triggerDraw,
+} from "../../EditorSlice";
+import ErrorMessage from "../../ErrorMessage/ErrorMessage";
+
+import store from "../../../../app/store";
+import VisualOutputPane from "./VisualOutputPane";
+import OutputViewToggle from "./OutputViewToggle";
+import { SettingsContext } from "../../../../settings";
 
 const externalLibraries = {
   "./pygal/__init__.js": {
     path: `${process.env.PUBLIC_URL}/shims/pygal/pygal.js`,
     dependencies: [
-      'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/highcharts.js',
-      'https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/js/highcharts-more.js'
+      "https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/highcharts.js",
+      "https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.2/js/highcharts-more.js",
     ],
   },
   "./py5/__init__.js": {
     path: `${process.env.PUBLIC_URL}/shims/processing/py5/py5-shim.js`,
-    dependencies: [
-      'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js'
-    ]
+    dependencies: ["https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"],
   },
   "./py5_imported/__init__.js": {
     path: `${process.env.PUBLIC_URL}/shims/processing/py5_imported_mode/py5_imported.js`,
   },
   "./py5_imported_mode.py": {
-    path: `${process.env.PUBLIC_URL}/shims/processing/py5_imported_mode/py5_imported_mode.py`
+    path: `${process.env.PUBLIC_URL}/shims/processing/py5_imported_mode/py5_imported_mode.py`,
   },
   "./p5/__init__.js": {
     path: `${process.env.PUBLIC_URL}/shims/processing/p5/p5-shim.js`,
-    dependencies: [
-      'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js'
-    ]
+    dependencies: ["https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"],
   },
   "./_internal_sense_hat/__init__.js": {
-    path: `${process.env.PUBLIC_URL}/shims/sense_hat/_internal_sense_hat.js`
+    path: `${process.env.PUBLIC_URL}/shims/sense_hat/_internal_sense_hat.js`,
   },
   "./sense_hat.py": {
-    path: `${process.env.PUBLIC_URL}/shims/sense_hat/sense_hat_blob.py`
-  }
+    path: `${process.env.PUBLIC_URL}/shims/sense_hat/sense_hat_blob.py`,
+  },
 };
 
 const PythonRunner = () => {
   const projectCode = useSelector((state) => state.editor.project.components);
   const isSplitView = useSelector((state) => state.editor.isSplitView);
   const isEmbedded = useSelector((state) => state.editor.isEmbedded);
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered);
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
   const codeRunStopped = useSelector((state) => state.editor.codeRunStopped);
   const drawTriggered = useSelector((state) => state.editor.drawTriggered);
-  const senseHatAlwaysEnabled = useSelector((state) => state.editor.senseHatAlwaysEnabled);
+  const senseHatAlwaysEnabled = useSelector(
+    (state) => state.editor.senseHatAlwaysEnabled,
+  );
   const output = useRef();
   const dispatch = useDispatch();
-  const { t } = useTranslation()
-  const settings = useContext(SettingsContext)
+  const { t } = useTranslation();
+  const settings = useContext(SettingsContext);
 
-  const queryParams = new URLSearchParams(window.location.search)
-  const [hasVisualOutput, setHasVisualOutput] = useState(queryParams.get('show_visual_tab') === 'true' || senseHatAlwaysEnabled)
+  const queryParams = new URLSearchParams(window.location.search);
+  const [hasVisualOutput, setHasVisualOutput] = useState(
+    queryParams.get("show_visual_tab") === "true" || senseHatAlwaysEnabled,
+  );
 
   const getInput = () => {
-    const pageInput = document.getElementById("input")
-    const webComponentInput = document.querySelector('editor-wc') ? document.querySelector('editor-wc').shadowRoot.getElementById("input") : null;
-    return pageInput || webComponentInput
-  }
+    const pageInput = document.getElementById("input");
+    const webComponentInput = document.querySelector("editor-wc")
+      ? document.querySelector("editor-wc").shadowRoot.getElementById("input")
+      : null;
+    return pageInput || webComponentInput;
+  };
 
   useEffect(() => {
     if (codeRunTriggered) {
@@ -78,63 +88,62 @@ const PythonRunner = () => {
 
   useEffect(() => {
     if (codeRunStopped && getInput()) {
-      const input = getInput()
-      input.removeAttribute("id")
-      input.removeAttribute("contentEditable")
-      dispatch(setError(t('output.errors.interrupted')));
-      dispatch(codeRunHandled())
+      const input = getInput();
+      input.removeAttribute("id");
+      input.removeAttribute("contentEditable");
+      dispatch(setError(t("output.errors.interrupted")));
+      dispatch(codeRunHandled());
     }
   }, [codeRunStopped]);
 
   useEffect(() => {
     if (!codeRunTriggered && !drawTriggered) {
       if (getInput()) {
-        const input = getInput()
-        input.removeAttribute("id")
-        input.removeAttribute("contentEditable")
+        const input = getInput();
+        input.removeAttribute("id");
+        input.removeAttribute("contentEditable");
       }
     }
-  },
-  [drawTriggered, codeRunTriggered]
-  )
+  }, [drawTriggered, codeRunTriggered]);
 
-  const visualLibraries =[
+  const visualLibraries = [
     "./pygal/__init__.js",
     "./py5/__init__.js",
     "./py5_imported/__init__.js",
     "./p5/__init__.js",
     "./_internal_sense_hat/__init__.js",
-    "src/builtin/turtle/__init__.js"
-  ]
+    "src/builtin/turtle/__init__.js",
+  ];
 
   const outf = (text) => {
     if (text !== "") {
       const node = output.current;
-      const div = document.createElement("span")
-      div.classList.add('pythonrunner-console-output-line')
+      const div = document.createElement("span");
+      div.classList.add("pythonrunner-console-output-line");
       div.innerHTML = new Option(text).innerHTML;
       node.appendChild(div);
       node.scrollTop = node.scrollHeight;
     }
-  }
+  };
 
   const builtinRead = (x) => {
-
-    if (x==="./_internal_sense_hat/__init__.js") {
-      dispatch(setSenseHatEnabled(true))
+    if (x === "./_internal_sense_hat/__init__.js") {
+      dispatch(setSenseHatEnabled(true));
     }
 
-    if(x === "./p5/__init__.js" || x === "./py5/__init__.js") {
-      dispatch(triggerDraw())
+    if (x === "./p5/__init__.js" || x === "./py5/__init__.js") {
+      dispatch(triggerDraw());
     }
-    
+
     // TODO: Handle pre-importing py5_imported when refactored py5 shim imported
 
     if (visualLibraries.includes(x)) {
-      setHasVisualOutput(true)
+      setHasVisualOutput(true);
     }
 
-    let localProjectFiles = projectCode.filter((component) => component.name !== 'main').map((component) => `./${component.name}.py`);
+    let localProjectFiles = projectCode
+      .filter((component) => component.name !== "main")
+      .map((component) => `./${component.name}.py`);
 
     if (localProjectFiles.includes(x)) {
       let filename = x.slice(2, -3);
@@ -144,57 +153,78 @@ const PythonRunner = () => {
       }
     }
 
-    if (Sk.builtinFiles !== undefined && Sk.builtinFiles["files"][x] !== undefined) {
+    if (
+      Sk.builtinFiles !== undefined &&
+      Sk.builtinFiles["files"][x] !== undefined
+    ) {
       return Sk.builtinFiles["files"][x];
     }
 
     if (externalLibraries[x]) {
       var externalLibraryInfo = externalLibraries[x];
 
-      return externalLibraries[x].code || Sk.misceval.promiseToSuspension(
-        fetch(externalLibraryInfo.path).then((response) => response.text()).then((code) => {
-          if (!code) {
-            throw new Sk.builtin.ImportError("Failed to load remote module");
-          }
-          externalLibraries[x].code = code
-          var promise;
-
-          function mapUrlToPromise(path) {
-            // If the script is already in the DOM don't add it again.
-            const existingScriptElement = document.querySelector(`script[src="${path}"]`)
-            if(!existingScriptElement) {
-              return new Promise(function (resolve, _reject) {
-                let scriptElement = document.createElement("script");
-                scriptElement.type = "text/javascript";
-                scriptElement.src = path;
-                scriptElement.async = true
-                scriptElement.onload = function () {
-                  resolve(true);
+      return (
+        externalLibraries[x].code ||
+        Sk.misceval.promiseToSuspension(
+          fetch(externalLibraryInfo.path)
+            .then((response) => response.text())
+            .then((code) => {
+              if (!code) {
+                throw new Sk.builtin.ImportError(
+                  "Failed to load remote module",
+                );
+              }
+              externalLibraries[x].code = code;
+              var promise;
+
+              function mapUrlToPromise(path) {
+                // If the script is already in the DOM don't add it again.
+                const existingScriptElement = document.querySelector(
+                  `script[src="${path}"]`,
+                );
+                if (!existingScriptElement) {
+                  return new Promise(function (resolve, _reject) {
+                    let scriptElement = document.createElement("script");
+                    scriptElement.type = "text/javascript";
+                    scriptElement.src = path;
+                    scriptElement.async = true;
+                    scriptElement.onload = function () {
+                      resolve(true);
+                    };
+
+                    document.body.appendChild(scriptElement);
+                  });
                 }
-
-                document.body.appendChild(scriptElement);
-              });
-            }
-          }
-          if (externalLibraryInfo.loadDepsSynchronously) {
-            promise = (externalLibraryInfo.dependencies || []).reduce((p, url) => {
-              return p.then(() => mapUrlToPromise(url));
-            }, Promise.resolve()); // initial
-          } else {
-            promise = Promise.all((externalLibraryInfo.dependencies || []).map(mapUrlToPromise));
-          }
-
-          return promise.then(function () {
-            return code;
-          }).catch(function () {
-            throw new Sk.builtin.ImportError("Failed to load dependencies required");
-          });
-        })
+              }
+              if (externalLibraryInfo.loadDepsSynchronously) {
+                promise = (externalLibraryInfo.dependencies || []).reduce(
+                  (p, url) => {
+                    return p.then(() => mapUrlToPromise(url));
+                  },
+                  Promise.resolve(),
+                ); // initial
+              } else {
+                promise = Promise.all(
+                  (externalLibraryInfo.dependencies || []).map(mapUrlToPromise),
+                );
+              }
+
+              return promise
+                .then(function () {
+                  return code;
+                })
+                .catch(function () {
+                  throw new Sk.builtin.ImportError(
+                    "Failed to load dependencies required",
+                  );
+                });
+            }),
+        )
       );
     }
 
     throw new Error("File not found: '" + x + "'");
-  }
+  };
 
   const inputSpan = () => {
     const span = document.createElement("span");
@@ -202,76 +232,81 @@ const PythonRunner = () => {
     span.setAttribute("spellCheck", "false");
     span.setAttribute("class", "pythonrunner-input");
     span.setAttribute("contentEditable", "true");
-    return span
-  }
+    return span;
+  };
 
   const inf = function () {
     if (Sk.sense_hat) {
-      Sk.sense_hat.mz_criteria.noInputEvents = false
+      Sk.sense_hat.mz_criteria.noInputEvents = false;
     }
     const outputPane = output.current;
     outputPane.appendChild(inputSpan());
 
-    const input = getInput()
+    const input = getInput();
     input.focus();
 
     return new Promise(function (resolve, reject) {
       input.addEventListener("keydown", function removeInput(e) {
         if (e.key === "Enter") {
-          input.removeEventListener(e.type, removeInput)
+          input.removeEventListener(e.type, removeInput);
           // resolve the promise with the value of the input field
           const answer = input.innerText;
           input.removeAttribute("id");
           input.removeAttribute("contentEditable");
-          input.innerText=answer+'\n';
+          input.innerText = answer + "\n";
 
           document.addEventListener("keyup", function storeInput(e) {
             if (e.key === "Enter") {
               document.removeEventListener(e.type, storeInput);
               resolve(answer);
             }
-          })
+          });
         }
-      })
-    })
-  }
+      });
+    });
+  };
 
   const handleError = (err) => {
-    let errorMessage
-    if (err.message === t('output.errors.interrupted')) {
-      errorMessage = err.message
+    let errorMessage;
+    if (err.message === t("output.errors.interrupted")) {
+      errorMessage = err.message;
     } else {
-      const errorDetails = (err.tp$str && err.tp$str().v).replace(/\[(.*?)\]/, "").replace(/\.$/, '')
-      const errorType = err.tp$name || err.constructor.name
-      const lineNumber = err.traceback[0].lineno
-      const fileName = err.traceback[0].filename.replace(/^\.\//, '')
-
-      Sentry.captureMessage(`${errorType}: ${errorDetails}`)
+      const errorDetails = (err.tp$str && err.tp$str().v)
+        .replace(/\[(.*?)\]/, "")
+        .replace(/\.$/, "");
+      const errorType = err.tp$name || err.constructor.name;
+      const lineNumber = err.traceback[0].lineno;
+      const fileName = err.traceback[0].filename.replace(/^\.\//, "");
+
+      Sentry.captureMessage(`${errorType}: ${errorDetails}`);
       errorMessage = `${errorType}: ${errorDetails} on line ${lineNumber} of ${fileName}`;
     }
 
     dispatch(setError(errorMessage));
     dispatch(stopDraw());
     if (getInput()) {
-      const input = getInput()
-      input.removeAttribute("id")
-      input.removeAttribute("contentEditable")
+      const input = getInput();
+      input.removeAttribute("id");
+      input.removeAttribute("contentEditable");
     }
-  }
+  };
 
   const runCode = () => {
     // clear previous output
     dispatch(setError(""));
-    output.current.innerHTML = '';
-    dispatch(setSenseHatEnabled(false))
+    output.current.innerHTML = "";
+    dispatch(setSenseHatEnabled(false));
 
     var prog = projectCode[0].content;
 
-    if (prog.includes(`# ${t('input.comment.py5')}`)) {
-      prog = prog.replace(`# ${t('input.comment.py5')}`,'from py5_imported_mode import *')
+    if (prog.includes(`# ${t("input.comment.py5")}`)) {
+      prog = prog.replace(
+        `# ${t("input.comment.py5")}`,
+        "from py5_imported_mode import *",
+      );
 
-      if (! prog.match(/(run_sketch)/)) {
-        prog = prog.concat('\nrun_sketch()')
+      if (!prog.match(/(run_sketch)/)) {
+        prog = prog.concat("\nrun_sketch()");
       }
     }
 
@@ -281,25 +316,25 @@ const PythonRunner = () => {
       read: builtinRead,
       debugging: true,
       inputTakesPrompt: true,
-      uncaughtException: handleError
+      uncaughtException: handleError,
     });
 
-    var myPromise = Sk.misceval.asyncToPromise(() =>
-        Sk.importMainWithBody("main", false, prog, true), {
-          "*": () => {
-            if (store.getState().editor.codeRunStopped) {
-              throw new Error(t('output.errors.interrupted'));
-            }
+    var myPromise = Sk.misceval
+      .asyncToPromise(() => Sk.importMainWithBody("main", false, prog, true), {
+        "*": () => {
+          if (store.getState().editor.codeRunStopped) {
+            throw new Error(t("output.errors.interrupted"));
           }
         },
-    ).catch(err => {
-      handleError(err)
-    }).finally(()=>{
-      dispatch(codeRunHandled());
-    });
-    myPromise.then(function (_mod) {
-    })
-  }
+      })
+      .catch((err) => {
+        handleError(err);
+      })
+      .finally(() => {
+        dispatch(codeRunHandled());
+      });
+    myPromise.then(function (_mod) {});
+  };
 
   function shiftFocusToInput(e) {
     if (document.getSelection().toString().length > 0) {
@@ -308,82 +343,100 @@ const PythonRunner = () => {
 
     const inputBox = getInput();
     if (inputBox && e.target !== inputBox) {
-      const input = getInput()
+      const input = getInput();
       const selection = window.getSelection();
       selection.removeAllRanges();
 
-      if (input.innerText && input.innerText.length > 0){
+      if (input.innerText && input.innerText.length > 0) {
         const range = document.createRange();
         range.setStart(input, 1);
         range.collapse(true);
         selection.addRange(range);
       }
-      input.focus()
+      input.focus();
     }
   }
 
   return (
     <div className={`pythonrunner-container`}>
-      { isSplitView ?
+      {isSplitView ? (
         <>
-          {hasVisualOutput ? <div className='output-panel output-panel--visual'>
+          {hasVisualOutput ? (
+            <div className="output-panel output-panel--visual">
+              <Tabs forceRenderTabPanel={true}>
+                <div className="react-tabs__tab-container">
+                  <TabList>
+                    <Tab key={0}>
+                      <span className="react-tabs__tab-inner">
+                        {t("output.visualOutput")}
+                      </span>
+                    </Tab>
+                  </TabList>
+                  {!isEmbedded ? <OutputViewToggle /> : null}
+                </div>
+                <TabPanel key={0}>
+                  <VisualOutputPane />
+                </TabPanel>
+              </Tabs>
+            </div>
+          ) : null}
+          <div className="output-panel output-panel--text">
             <Tabs forceRenderTabPanel={true}>
-              <div className='react-tabs__tab-container'>
+              <div className="react-tabs__tab-container">
                 <TabList>
                   <Tab key={0}>
-                    <span className='react-tabs__tab-inner'>{t('output.visualOutput')}</span>
+                    <span className="react-tabs__tab-inner">
+                      {t("output.textOutput")}
+                    </span>
                   </Tab>
                 </TabList>
-                {!isEmbedded ? <OutputViewToggle/> : null }
-              </div>
-              <TabPanel key={0} >
-                <VisualOutputPane/>
-              </TabPanel>
-            </Tabs>
-          </div> : null}
-          <div className='output-panel output-panel--text'>
-            <Tabs forceRenderTabPanel={true}>
-              <div className='react-tabs__tab-container'>
-                <TabList>
-                  <Tab key={0}>
-                    <span className='react-tabs__tab-inner'>{t('output.textOutput')}</span>
-                  </Tab>
-                </TabList>
-                { hasVisualOutput || isEmbedded ? null : <OutputViewToggle /> }
+                {hasVisualOutput || isEmbedded ? null : <OutputViewToggle />}
               </div>
               <ErrorMessage />
               <TabPanel key={0}>
-                <pre className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`} onClick={shiftFocusToInput} ref={output}></pre>
+                <pre
+                  className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`}
+                  onClick={shiftFocusToInput}
+                  ref={output}
+                ></pre>
               </TabPanel>
             </Tabs>
           </div>
-      </>
-      :
-      <Tabs forceRenderTabPanel={true} defaultIndex={hasVisualOutput ? 0 : 1}>
-        <div className='react-tabs__tab-container'>
-          <TabList>
-            {hasVisualOutput ?
-              <Tab key={0}>
-                <span className='react-tabs__tab-inner'>{t('output.visualOutput')}</span>
-              </Tab> : null
-            }
-            <Tab key={1}>
-              <span className='react-tabs__tab-inner'>{t('output.textOutput')}</span>
-            </Tab>
-          </TabList>
-          {!isEmbedded ? <OutputViewToggle/> : null }
-        </div>
-        <ErrorMessage />
-        {hasVisualOutput ?
-          <TabPanel key={0} >
-            <VisualOutputPane/>
-          </TabPanel> : null
-        }
-        <TabPanel key={1}>
-          <pre className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`} onClick={shiftFocusToInput} ref={output}></pre>
-        </TabPanel>
-      </Tabs>
-      }
+        </>
+      ) : (
+        <Tabs forceRenderTabPanel={true} defaultIndex={hasVisualOutput ? 0 : 1}>
+          <div className="react-tabs__tab-container">
+            <TabList>
+              {hasVisualOutput ? (
+                <Tab key={0}>
+                  <span className="react-tabs__tab-inner">
+                    {t("output.visualOutput")}
+                  </span>
+                </Tab>
+              ) : null}
+              <Tab key={1}>
+                <span className="react-tabs__tab-inner">
+                  {t("output.textOutput")}
+                </span>
+              </Tab>
+            </TabList>
+            {!isEmbedded ? <OutputViewToggle /> : null}
+          </div>
+          <ErrorMessage />
+          {hasVisualOutput ? (
+            <TabPanel key={0}>
+              <VisualOutputPane />
+            </TabPanel>
+          ) : null}
+          <TabPanel key={1}>
+            <pre
+              className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`}
+              onClick={shiftFocusToInput}
+              ref={output}
+            ></pre>
+          </TabPanel>
+        </Tabs>
+      )}
     </div>
   );
 };
diff --git a/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js b/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js
index 00cb5ef50..bb013ca5c 100644
--- a/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js
+++ b/src/components/Editor/Runners/PythonRunner/PythonRunner.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import PythonRunner from "./PythonRunner";
 import { codeRunHandled, setError, triggerDraw } from "../../EditorSlice";
@@ -12,585 +12,679 @@ describe("Testing basic input span functionality", () => {
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "input()"
-            }
+              content: "input()",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-      }
-    }
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>);
+    render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    );
     input = document.getElementById("input");
-  })
+  });
 
   test("Input function in code makes editable input box appear", () => {
     expect(input).toHaveAttribute("contentEditable", "true");
-  })
+  });
 
   test("Input box has focus when it appears", () => {
     expect(input).toHaveFocus();
-  })
+  });
 
   test("Clicking output pane transfers focus to input", () => {
-    const outputPane = document.getElementsByClassName("pythonrunner-console")[0]
+    const outputPane = document.getElementsByClassName(
+      "pythonrunner-console",
+    )[0];
     fireEvent.click(outputPane);
     expect(input).toHaveFocus();
-  })
+  });
 
   test("Pressing enter stops the input box being editable", () => {
-    const inputText = 'hello world';
+    const inputText = "hello world";
     input.innerText = inputText;
-    fireEvent.keyDown(input, { key: 'Enter', code: 'Enter', charCode: 13 })
+    fireEvent.keyDown(input, { key: "Enter", code: "Enter", charCode: 13 });
 
     expect(input).not.toHaveAttribute("contentEditable", "true");
-    expect(input.innerText).toBe(inputText + '\n');
-  })
-})
+    expect(input.innerText).toBe(inputText + "\n");
+  });
+});
 
 test("Input box not there when input function not called", () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
         components: [
           {
-            content: "print('Hello')"
-          }
+            content: "print('Hello')",
+          },
         ],
-        image_list: []
+        image_list: [],
       },
-      codeRunTriggered: true
-    }
-  }
+      codeRunTriggered: true,
+    },
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><PythonRunner /></Provider>);
-  expect(document.getElementById("input")).toBeNull()
-
-})
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(document.getElementById("input")).toBeNull();
+});
 
 describe("Testing stopping the code run with input", () => {
   let store;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "input()"
-            }
+              content: "input()",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        codeRunStopped: true
-      }
-    }
+        codeRunStopped: true,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>);
-  })
+    render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    );
+  });
 
   test("Disables input span", () => {
     expect(document.getElementById("input")).toBeNull();
-  })
+  });
 
   test("Sets interruption error", () => {
-    expect(store.getActions()).toEqual(expect.arrayContaining([setError('output.errors.interrupted')]))
-  })
+    expect(store.getActions()).toEqual(
+      expect.arrayContaining([setError("output.errors.interrupted")]),
+    );
+  });
 
   test("Handles code run", () => {
-    expect(store.getActions()).toEqual(expect.arrayContaining([codeRunHandled()]))
-  })
-})
+    expect(store.getActions()).toEqual(
+      expect.arrayContaining([codeRunHandled()]),
+    );
+  });
+});
 
-describe('When in split view, no visual libraries used and code run', () => {
+describe("When in split view, no visual libraries used and code run", () => {
   let store;
   let queryByText;
-  
+
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "print('hello world')"
-            }
+              content: "print('hello world')",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not shown', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).not.toBeInTheDocument()
-  })
-})
-
-describe('When in split view, py5 imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not shown", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).not.toBeInTheDocument();
+  });
+});
+
+describe("When in split view, py5 imported and code run", () => {
   let store;
   let queryByText;
-  
+
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import py5"
-            }
+              content: "import py5",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is shown', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-
-  test('Draw is triggered', () => {
-    expect(store.getActions()).toEqual(expect.arrayContaining([triggerDraw()]))
-  })
-})
-
-describe('When in split view, py5_imported imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is shown", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+
+  test("Draw is triggered", () => {
+    expect(store.getActions()).toEqual(expect.arrayContaining([triggerDraw()]));
+  });
+});
+
+describe("When in split view, py5_imported imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import py5_imported"
-            }
+              content: "import py5_imported",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is shown', async () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in split view, pygal imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is shown", async () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in split view, pygal imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import pygal"
-            }
+              content: "import pygal",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is shown', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in split view, turtle imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is shown", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in split view, turtle imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import turtle"
-            }
+              content: "import turtle",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is shown', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in split view, sense_hat imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is shown", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in split view, sense_hat imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import _internal_sense_hat"
-            }
+              content: "import _internal_sense_hat",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: true
-      }
-    }
+        isSplitView: true,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is shown', async () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()  })
-})
-
-describe('When in tabbed view, no visual libraries used and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is shown", async () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in tabbed view, no visual libraries used and code run", () => {
   let store;
   let queryByText;
-  
+
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "print('hello world')"
-            }
+              content: "print('hello world')",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not shown', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).not.toBeInTheDocument()
-  })
-})
-
-describe('When in tabbed view, py5 imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not shown", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).not.toBeInTheDocument();
+  });
+});
+
+describe("When in tabbed view, py5 imported and code run", () => {
   let store;
   let queryByText;
-  
+
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import py5"
-            }
+              content: "import py5",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not hidden', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-
-  test('Draw is triggered', () => {
-    expect(store.getActions()).toEqual(expect.arrayContaining([triggerDraw()]))
-  })
-})
-
-describe('When in tabbed view, py5_imported imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not hidden", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+
+  test("Draw is triggered", () => {
+    expect(store.getActions()).toEqual(expect.arrayContaining([triggerDraw()]));
+  });
+});
+
+describe("When in tabbed view, py5_imported imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import py5_imported"
-            }
+              content: "import py5_imported",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not hidden', async () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in tabbed view, pygal imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not hidden", async () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in tabbed view, pygal imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import pygal"
-            }
+              content: "import pygal",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not hidden', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in tabbed view, turtle imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not hidden", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in tabbed view, turtle imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import turtle"
-            }
+              content: "import turtle",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
-
-  test('Visual tab is not hidden', () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
-
-describe('When in tabbed view, sense_hat imported and code run', () => {
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
+
+  test("Visual tab is not hidden", () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
+
+describe("When in tabbed view, sense_hat imported and code run", () => {
   let store;
   let queryByText;
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import _internal_sense_hat"
-            }
+              content: "import _internal_sense_hat",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
         codeRunTriggered: true,
-        isSplitView: false
-      }
-    }
+        isSplitView: false,
+      },
+    };
     store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><PythonRunner /></Provider>));
-  })
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <PythonRunner />
+      </Provider>,
+    ));
+  });
 
-  test('Visual tab is not hidden', async () => {
-    const visualTab = queryByText('output.visualOutput')
-    expect(visualTab).toBeInTheDocument()
-  })
-})
+  test("Visual tab is not hidden", async () => {
+    const visualTab = queryByText("output.visualOutput");
+    expect(visualTab).toBeInTheDocument();
+  });
+});
 
 test("When embedded in split view with visual output does not render output view toggle", () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {
-          components: [
-            {
-              content: "import p5"
-            }
-          ],
-        },
-        codeRUnTriggered: true,
-        isSplitView: true,
-        isEmbedded: true
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>)
-    expect(screen.queryByRole('button')).not.toBeInTheDocument()
-})
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {
+        components: [
+          {
+            content: "import p5",
+          },
+        ],
+      },
+      codeRUnTriggered: true,
+      isSplitView: true,
+      isEmbedded: true,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(screen.queryByRole("button")).not.toBeInTheDocument();
+});
 
 test("When embedded in split view with no visual output does not render output view toggle", () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {},
-        senseHatAlwaysEnabled: false,
-        isSplitView: true,
-        isEmbedded: true
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>)
-    expect(screen.queryByRole('button')).not.toBeInTheDocument()
-})
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {},
+      senseHatAlwaysEnabled: false,
+      isSplitView: true,
+      isEmbedded: true,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(screen.queryByRole("button")).not.toBeInTheDocument();
+});
 
 test("When embedded in tabbed view does not render output view toggle", () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {},
-        isSplitView: false,
-        isEmbedded: true
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>)
-    expect(screen.queryByRole('button')).not.toBeInTheDocument()
-})
-
-test('Tabbed view has text and visual tabs with same parent element', () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {},
-        senseHatAlwaysEnabled: true,
-        isSplitView: false
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>)
-    expect(screen.getByText('output.visualOutput').parentElement.parentElement).toEqual(screen.getByText('output.textOutput').parentElement.parentElement)
-})
-
-test('Split view has text and visual tabs with different parent elements', () => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {},
-        senseHatAlwaysEnabled: true,
-        isSplitView: true
-      }
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><PythonRunner /></Provider>)
-    expect(screen.getByText('output.visualOutput').parentElement).not.toEqual(screen.getByText('output.textOutput').parentElement)
-})
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {},
+      isSplitView: false,
+      isEmbedded: true,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(screen.queryByRole("button")).not.toBeInTheDocument();
+});
+
+test("Tabbed view has text and visual tabs with same parent element", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {},
+      senseHatAlwaysEnabled: true,
+      isSplitView: false,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(
+    screen.getByText("output.visualOutput").parentElement.parentElement,
+  ).toEqual(screen.getByText("output.textOutput").parentElement.parentElement);
+});
+
+test("Split view has text and visual tabs with different parent elements", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {},
+      senseHatAlwaysEnabled: true,
+      isSplitView: true,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <PythonRunner />
+    </Provider>,
+  );
+  expect(screen.getByText("output.visualOutput").parentElement).not.toEqual(
+    screen.getByText("output.textOutput").parentElement,
+  );
+});
+
+describe("When font size is set", () => {
+  let runnerContainer;
 
-describe('When font size is set', () => {
-  let runnerContainer
-  
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
-        project: {}
-      }
-    }
+        project: {},
+      },
+    };
     const store = mockStore(initialState);
     runnerContainer = render(
       <Provider store={store}>
-        <SettingsContext.Provider value={{ theme: 'dark', fontSize: 'myFontSize' }}>
+        <SettingsContext.Provider
+          value={{ theme: "dark", fontSize: "myFontSize" }}
+        >
           <PythonRunner />
         </SettingsContext.Provider>
-      </Provider>
-    )
-  })
-
-  test('Font size class is set correctly', () => {
-    const runnerConsole = runnerContainer.container.querySelector('.pythonrunner-console')
-    expect(runnerConsole).toHaveClass("pythonrunner-console--myFontSize")
-  })
-})
+      </Provider>,
+    );
+  });
+
+  test("Font size class is set correctly", () => {
+    const runnerConsole = runnerContainer.container.querySelector(
+      ".pythonrunner-console",
+    );
+    expect(runnerConsole).toHaveClass("pythonrunner-console--myFontSize");
+  });
+});
diff --git a/src/components/Editor/Runners/PythonRunner/VisualOutputPane.js b/src/components/Editor/Runners/PythonRunner/VisualOutputPane.js
index 923e4593a..8eb56f6ee 100644
--- a/src/components/Editor/Runners/PythonRunner/VisualOutputPane.js
+++ b/src/components/Editor/Runners/PythonRunner/VisualOutputPane.js
@@ -2,15 +2,18 @@ import React, { useEffect } from "react";
 import { useRef } from "react";
 import { useTranslation } from "react-i18next";
 import { useDispatch, useSelector } from "react-redux";
-import Sk from "skulpt"
+import Sk from "skulpt";
 import AstroPiModel from "../../../AstroPiModel/AstroPiModel";
 import { codeRunHandled, setError } from "../../EditorSlice";
 
 const VisualOutputPane = () => {
-
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered)
-  const drawTriggered = useSelector((state) => state.editor.drawTriggered)
-  const senseHatAlwaysEnabled = useSelector((state) => state.editor.senseHatAlwaysEnabled);
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
+  const drawTriggered = useSelector((state) => state.editor.drawTriggered);
+  const senseHatAlwaysEnabled = useSelector(
+    (state) => state.editor.senseHatAlwaysEnabled,
+  );
   const senseHatEnabled = useSelector((state) => state.editor.senseHatEnabled);
   const projectImages = useSelector((state) => state.editor.project.image_list);
   const error = useSelector((state) => state.editor.error);
@@ -19,56 +22,67 @@ const VisualOutputPane = () => {
   const pygalOutput = useRef();
   const p5Output = useRef();
   const dispatch = useDispatch();
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
   useEffect(() => {
     if (codeRunTriggered) {
-      outputCanvas.current.innerHTML = '';
-      pygalOutput.current.innerHTML = '';
-      p5Output.current.innerHTML = '';
+      outputCanvas.current.innerHTML = "";
+      pygalOutput.current.innerHTML = "";
+      p5Output.current.innerHTML = "";
 
-      Sk.py5 = {}
+      Sk.py5 = {};
       Sk.py5.sketch = "p5Sketch";
       Sk.py5.assets = projectImages;
 
-      Sk.p5 = {}
+      Sk.p5 = {};
       Sk.p5.sketch = "p5Sketch";
       Sk.p5.assets = projectImages;
-    
+
       (Sk.pygal || (Sk.pygal = {})).outputCanvas = pygalOutput.current;
-    
-      (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = 'outputCanvas';
-      Sk.TurtleGraphics.assets = Object.assign({}, ...projectImages.map((image) => ({[`${image.name}.${image.extension}`]: image.url})))
-    
+
+      (Sk.TurtleGraphics || (Sk.TurtleGraphics = {})).target = "outputCanvas";
+      Sk.TurtleGraphics.assets = Object.assign(
+        {},
+        ...projectImages.map((image) => ({
+          [`${image.name}.${image.extension}`]: image.url,
+        })),
+      );
     }
-  }, [codeRunTriggered, projectImages])
+  }, [codeRunTriggered, projectImages]);
 
   useEffect(() => {
-    if (!drawTriggered && p5Output.current && p5Output.current.innerHTML !== '') {
+    if (
+      !drawTriggered &&
+      p5Output.current &&
+      p5Output.current.innerHTML !== ""
+    ) {
       if (Sk.py5.stop) {
-        Sk.py5.stop()
+        Sk.py5.stop();
       } else {
-        Sk.p5.stop()
+        Sk.p5.stop();
       }
-      
-      if(error === ''){
-        dispatch(setError(t('output.errors.interrupted')))
+
+      if (error === "") {
+        dispatch(setError(t("output.errors.interrupted")));
       }
-      dispatch(codeRunHandled())
+      dispatch(codeRunHandled());
     }
-
-  }, [drawTriggered, dispatch, t, error])
+  }, [drawTriggered, dispatch, t, error]);
 
   return (
-    <div className='visual-output'>
-      <div id='p5Sketch' ref={p5Output} />
-      <div id='pygalOutput' ref={pygalOutput} />
+    <div className="visual-output">
+      <div id="p5Sketch" ref={p5Output} />
+      <div id="pygalOutput" ref={pygalOutput} />
       <div className="pythonrunner-canvas-container">
-        <div id='outputCanvas' ref={outputCanvas} className="pythonrunner-graphic" />
+        <div
+          id="outputCanvas"
+          ref={outputCanvas}
+          className="pythonrunner-graphic"
+        />
       </div>
-      {senseHatEnabled || senseHatAlwaysEnabled ?<AstroPiModel/>:null}
+      {senseHatEnabled || senseHatAlwaysEnabled ? <AstroPiModel /> : null}
     </div>
-  )
-}
+  );
+};
 
-export default VisualOutputPane
+export default VisualOutputPane;
diff --git a/src/components/Editor/Runners/PythonRunner/VisualOutputPane.test.js b/src/components/Editor/Runners/PythonRunner/VisualOutputPane.test.js
index 0b06504b1..a3d38c9f4 100644
--- a/src/components/Editor/Runners/PythonRunner/VisualOutputPane.test.js
+++ b/src/components/Editor/Runners/PythonRunner/VisualOutputPane.test.js
@@ -1,100 +1,111 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import VisualOutputPane from "./VisualOutputPane";
-import Sk from 'skulpt';
+import Sk from "skulpt";
 
 describe("When Sense Hat library used", () => {
   let canvas;
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "import _internal_sense_hat"
-            }
+              content: "import _internal_sense_hat",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
-        codeRunTriggered: true
-      }
-    }
+        codeRunTriggered: true,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><VisualOutputPane /></Provider>);
-    canvas = document.getElementsByClassName("sense-hat")[0]
-  })
+    render(
+      <Provider store={store}>
+        <VisualOutputPane />
+      </Provider>,
+    );
+    canvas = document.getElementsByClassName("sense-hat")[0];
+  });
 
   test("Astro Pi component appears", () => {
-    expect(canvas).not.toBeNull()
-  })
-})
+    expect(canvas).not.toBeNull();
+  });
+});
 
 describe("When Sense Hat library not used", () => {
   let canvas;
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              content: "print('Hello world')"
-            }
+              content: "print('Hello world')",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
-        codeRunTriggered: true
-      }
-    }
+        codeRunTriggered: true,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><VisualOutputPane /></Provider>);
-    canvas = document.getElementsByClassName("sense-hat")[0]
-  })
+    render(
+      <Provider store={store}>
+        <VisualOutputPane />
+      </Provider>,
+    );
+    canvas = document.getElementsByClassName("sense-hat")[0];
+  });
 
   test("Astro Pi component does not appear", () => {
-    expect(canvas).not.toBeDefined()
-  })
-})
-
-describe("When code run is triggered",() => {
+    expect(canvas).not.toBeDefined();
+  });
+});
 
+describe("When code run is triggered", () => {
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [],
-          image_list: []
+          image_list: [],
         },
-        codeRunTriggered: true
-      }
-    }
+        codeRunTriggered: true,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><VisualOutputPane /></Provider>);
-  })
+    render(
+      <Provider store={store}>
+        <VisualOutputPane />
+      </Provider>,
+    );
+  });
 
-  test('Sets up p5 canvas', () => {
-    expect(Sk.py5.sketch).not.toBeNull()
-  })
+  test("Sets up p5 canvas", () => {
+    expect(Sk.py5.sketch).not.toBeNull();
+  });
 
-  test('Sets up pygal canvas', () => {
-    expect(Sk.pygal.outputCanvas).not.toBeNull()
-  })
+  test("Sets up pygal canvas", () => {
+    expect(Sk.pygal.outputCanvas).not.toBeNull();
+  });
 
-  test('Sets up turtle canvas', () => {
-    expect(Sk.TurtleGraphics.target).not.toBeNull()
-  })
-})
+  test("Sets up turtle canvas", () => {
+    expect(Sk.TurtleGraphics.target).not.toBeNull();
+  });
+});
diff --git a/src/components/Editor/Runners/RunnerFactory.js b/src/components/Editor/Runners/RunnerFactory.js
index 0d66ce9f5..12f6aee4a 100644
--- a/src/components/Editor/Runners/RunnerFactory.js
+++ b/src/components/Editor/Runners/RunnerFactory.js
@@ -1,21 +1,18 @@
-import React from 'react';
-import PythonRunner from './PythonRunner/PythonRunner';
-import HtmlRunner from './HtmlRunner/HtmlRunner';
+import React from "react";
+import PythonRunner from "./PythonRunner/PythonRunner";
+import HtmlRunner from "./HtmlRunner/HtmlRunner";
 
 const RunnerFactory = ({ projectType }) => {
   const Runner = () => {
-    if (projectType === 'html') {
+    if (projectType === "html") {
       return HtmlRunner;
     }
     return PythonRunner;
-  }
+  };
 
   const Selected = Runner();
 
-  return (
-    <Selected />
-  )
-}
+  return <Selected />;
+};
 
 export default RunnerFactory;
-
diff --git a/src/components/Editor/editorDarkTheme.js b/src/components/Editor/editorDarkTheme.js
index bf4907d53..74b0e1c94 100644
--- a/src/components/Editor/editorDarkTheme.js
+++ b/src/components/Editor/editorDarkTheme.js
@@ -1,40 +1,43 @@
-import { EditorView } from '@codemirror/view';
-import '../../font-weight.scss';
-import '../../font-size.scss';
-import '../../line-height.scss';
+import { EditorView } from "@codemirror/view";
+import "../../font-weight.scss";
+import "../../font-size.scss";
+import "../../line-height.scss";
 
-export const editorDarkTheme = EditorView.theme({
-  ".cm-gutters": {
-    "background-color": "#2A2B32",
-    "color": "white",
-    "border": "none"
+export const editorDarkTheme = EditorView.theme(
+  {
+    ".cm-gutters": {
+      "background-color": "#2A2B32",
+      color: "white",
+      border: "none",
+    },
+    ".cm-activeLine": {
+      "background-color": "inherit",
+    },
+    ".cm-activeLineGutter": {
+      "background-color": "inherit",
+      color: "inherit",
+    },
+    "&.cm-focused .cm-selectionBackground, ::selection": {
+      background: "#144866",
+    },
+    "&.cm-focused .cm-cursor": {
+      borderLeftColor: "white",
+    },
+    ".cm-line .cm-indentation-marker": {
+      background: "none",
+      "border-left": "solid grey",
+      "&.active": {
+        background: "none",
+        "border-left": "solid lightgrey",
+      },
+    },
+    ".ͼb": { color: "#FF00A4" },
+    ".ͼc": { color: "#1498D0" },
+    ".ͼd": { color: "#1498D0" },
+    ".ͼe": { color: "#6CE68D" },
+    ".ͼg": { color: "#1498D0" },
+    ".ͼj": { color: "#1498D0" },
+    ".ͼm": { color: "#C1C1C1" },
   },
-  ".cm-activeLine": {
-    "background-color": "inherit",
-  },
-  ".cm-activeLineGutter": {
-    "background-color": "inherit",
-    "color": "inherit"
-  },
-  "&.cm-focused .cm-selectionBackground, ::selection": {
-    "background": "#144866"
-  },
-  "&.cm-focused .cm-cursor": {
-    borderLeftColor: "white"
-  },
-  ".cm-line .cm-indentation-marker": {
-    'background': 'none',
-    'border-left': 'solid grey',
-    "&.active": {
-      'background': 'none',
-      'border-left': 'solid lightgrey',
-    }
-  },
-  ".ͼb": {color: "#FF00A4"},
-  ".ͼc": {color: "#1498D0"},
-  ".ͼd": {color: "#1498D0"},
-  ".ͼe": {color: "#6CE68D"},
-  ".ͼg": {color: "#1498D0"},
-  ".ͼj": {color: "#1498D0"},
-  ".ͼm": {color: "#C1C1C1"},
-}, {dark: true})
+  { dark: true },
+);
diff --git a/src/components/Editor/editorLightTheme.js b/src/components/Editor/editorLightTheme.js
index 25d6b3c42..bdaf6b39e 100644
--- a/src/components/Editor/editorLightTheme.js
+++ b/src/components/Editor/editorLightTheme.js
@@ -1,24 +1,27 @@
-import { EditorView } from '@codemirror/view';
+import { EditorView } from "@codemirror/view";
 
-export const editorLightTheme = EditorView.theme({
-  ".cm-activeLine": {
-    "background-color": "inherit",
+export const editorLightTheme = EditorView.theme(
+  {
+    ".cm-activeLine": {
+      "background-color": "inherit",
+    },
+    ".cm-activeLineGutter": {
+      "background-color": "inherit",
+      color: "inherit",
+    },
+    ".cm-gutters": {
+      border: "none",
+      color: "black",
+      "background-color": "white",
+    },
+    ".cm-line .cm-indentation-marker": {
+      background: "none",
+      "border-left": "solid lightgrey",
+      "&.active": {
+        background: "none",
+        "border-left": "solid grey",
+      },
+    },
   },
-  ".cm-activeLineGutter": {
-    "background-color": "inherit",
-    "color": "inherit"
-  },
-  ".cm-gutters": {
-    "border": "none",
-    "color": "black",
-    "background-color": "white"
-  },
-  ".cm-line .cm-indentation-marker": {
-    'background': 'none',
-    'border-left': 'solid lightgrey',
-    "&.active": {
-      'background': 'none',
-      'border-left': 'solid grey',
-    }
-  },
-}, {dark: false})
+  { dark: false },
+);
diff --git a/src/components/EmbeddedViewer/EmbeddedControls/EmbeddedControls.js b/src/components/EmbeddedViewer/EmbeddedControls/EmbeddedControls.js
index 574b5d1b4..78ba5105a 100644
--- a/src/components/EmbeddedViewer/EmbeddedControls/EmbeddedControls.js
+++ b/src/components/EmbeddedViewer/EmbeddedControls/EmbeddedControls.js
@@ -1,12 +1,12 @@
-import './EmbeddedControls.css';
-import RunnerControls from '../../RunButton/RunnerControls';
+import "./EmbeddedControls.css";
+import RunnerControls from "../../RunButton/RunnerControls";
 
 const EmbeddedControls = () => {
-    return  (
-      <div className = "embedded-controls">
-          <RunnerControls/>
-      </div>
-    )
-}
+  return (
+    <div className="embedded-controls">
+      <RunnerControls />
+    </div>
+  );
+};
 
 export default EmbeddedControls;
diff --git a/src/components/EmbeddedViewer/EmbeddedViewer.test.js b/src/components/EmbeddedViewer/EmbeddedViewer.test.js
index 3747b57cb..c1a3f5ca2 100644
--- a/src/components/EmbeddedViewer/EmbeddedViewer.test.js
+++ b/src/components/EmbeddedViewer/EmbeddedViewer.test.js
@@ -1,33 +1,32 @@
-import React from 'react';
-import EmbeddedViewer from './EmbeddedViewer';
+import React from "react";
+import EmbeddedViewer from "./EmbeddedViewer";
 
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
-import { render } from '@testing-library/react';
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
+import { render } from "@testing-library/react";
 
-let store
+let store;
 
 beforeEach(() => {
   const middlewares = [];
   const mockStore = configureStore(middlewares);
 
   const initialState = {
-      editor: {
-        loading: 'success',
-        project: {
-          components: []
-        }
-      }
+    editor: {
+      loading: "success",
+      project: {
+        components: [],
+      },
+    },
   };
   store = mockStore(initialState);
+});
 
-})
-
-test('Renders without crashing', () => {
+test("Renders without crashing", () => {
   const { asFragment } = render(
     <Provider store={store}>
       <EmbeddedViewer />
-    </Provider>
+    </Provider>,
   );
   expect(asFragment()).toMatchSnapshot();
 });
diff --git a/src/components/ExternalFiles/ExternalFiles.js b/src/components/ExternalFiles/ExternalFiles.js
index fc3fd36d5..6c6683988 100644
--- a/src/components/ExternalFiles/ExternalFiles.js
+++ b/src/components/ExternalFiles/ExternalFiles.js
@@ -1,20 +1,23 @@
-import React from 'react';
-import { useSelector } from 'react-redux'
+import React from "react";
+import { useSelector } from "react-redux";
 
 const ExternalFiles = () => {
   const project = useSelector((state) => state.editor.project);
 
   return (
-  <div id='file-content' hidden>
-  {project.components.map((file, i) => {
-    if(['csv', 'txt'].includes(file.extension)) {
-      return <div id={`${file.name}.${file.extension}`} key={i}>{file.content}</div>
-    }
-    return null
-  })}
-
-  </div>
-  )
+    <div id="file-content" hidden>
+      {project.components.map((file, i) => {
+        if (["csv", "txt"].includes(file.extension)) {
+          return (
+            <div id={`${file.name}.${file.extension}`} key={i}>
+              {file.content}
+            </div>
+          );
+        }
+        return null;
+      })}
+    </div>
+  );
 };
 
-export default ExternalFiles
+export default ExternalFiles;
diff --git a/src/components/ExternalFiles/ExternalFiles.test.js b/src/components/ExternalFiles/ExternalFiles.test.js
index 3c182a1b7..a05e55d91 100644
--- a/src/components/ExternalFiles/ExternalFiles.test.js
+++ b/src/components/ExternalFiles/ExternalFiles.test.js
@@ -1,28 +1,32 @@
 import React from "react";
 import { render } from "@testing-library/react";
-import { Provider } from 'react-redux';
+import { Provider } from "react-redux";
 import configureStore from "redux-mock-store";
 import ExternalFiles from "./ExternalFiles";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
 test("External files component contains text from file with filename id", () => {
-    const initialState = {
-        editor: {
-            project: {
-              components: [
-                {
-                  name: "hello",
-                  extension: "txt",
-                  content: "hello world!"
-                }
-              ]
-            }
-        }
-    }
-    const store = mockStore(initialState)
-    const  {getByText} = render(<Provider store={store}><ExternalFiles /></Provider>);
-    const fileContent = getByText("hello world!")
-    expect(fileContent).toHaveAttribute('id', 'hello.txt')
-})
+  const initialState = {
+    editor: {
+      project: {
+        components: [
+          {
+            name: "hello",
+            extension: "txt",
+            content: "hello world!",
+          },
+        ],
+      },
+    },
+  };
+  const store = mockStore(initialState);
+  const { getByText } = render(
+    <Provider store={store}>
+      <ExternalFiles />
+    </Provider>,
+  );
+  const fileContent = getByText("hello world!");
+  expect(fileContent).toHaveAttribute("id", "hello.txt");
+});
diff --git a/src/components/Footer/Footer.js b/src/components/Footer/Footer.js
index 3d29b0ba6..6a844badb 100644
--- a/src/components/Footer/Footer.js
+++ b/src/components/Footer/Footer.js
@@ -1,20 +1,42 @@
 import React from "react";
 import { useTranslation } from "react-i18next";
-import './Footer.scss';
+import "./Footer.scss";
 
 const Footer = () => {
-  const { t } = useTranslation()
+  const { t } = useTranslation();
   return (
-    <footer className='editor-footer'>
-      <span className='editor-footer__name'>{t('footer.charityNameAndNumber')}</span>
-      <div className='editor-footer__links'>
-        <a className='editor-footer__links-link' href='https://www.raspberrypi.org/privacy/child-friendly'>{t('footer.privacy')}</a>
-        <a className='editor-footer__links-link' href='https://www.raspberrypi.org/cookies'>{t('footer.cookies')}</a>
-        <a className='editor-footer__links-link' href='https://www.raspberrypi.org/accessibility'>{t('footer.accessibility')}</a>
-        <a className='editor-footer__links-link' href='https://www.raspberrypi.org/safeguarding'>{t('footer.safeguarding')}</a>
+    <footer className="editor-footer">
+      <span className="editor-footer__name">
+        {t("footer.charityNameAndNumber")}
+      </span>
+      <div className="editor-footer__links">
+        <a
+          className="editor-footer__links-link"
+          href="https://www.raspberrypi.org/privacy/child-friendly"
+        >
+          {t("footer.privacy")}
+        </a>
+        <a
+          className="editor-footer__links-link"
+          href="https://www.raspberrypi.org/cookies"
+        >
+          {t("footer.cookies")}
+        </a>
+        <a
+          className="editor-footer__links-link"
+          href="https://www.raspberrypi.org/accessibility"
+        >
+          {t("footer.accessibility")}
+        </a>
+        <a
+          className="editor-footer__links-link"
+          href="https://www.raspberrypi.org/safeguarding"
+        >
+          {t("footer.safeguarding")}
+        </a>
       </div>
     </footer>
-  )
-}
+  );
+};
 
 export default Footer;
diff --git a/src/components/Footer/Footer.test.js b/src/components/Footer/Footer.test.js
index a2ed4dabd..3802b8bee 100644
--- a/src/components/Footer/Footer.test.js
+++ b/src/components/Footer/Footer.test.js
@@ -3,27 +3,39 @@ import React from "react";
 import { render, screen } from "@testing-library/react";
 import Footer from "./Footer";
 
-test('Footer renders', () => {
-  render(<Footer/>)
-  expect(screen.queryByText('footer.charityNameAndNumber')).toBeInTheDocument()
-})
+test("Footer renders", () => {
+  render(<Footer />);
+  expect(screen.queryByText("footer.charityNameAndNumber")).toBeInTheDocument();
+});
 
-test('Links to privacy policy', () => {
-  render(<Footer/>)
-  expect(screen.queryByText('footer.privacy')).toHaveAttribute('href', 'https://www.raspberrypi.org/privacy/child-friendly')
-})
+test("Links to privacy policy", () => {
+  render(<Footer />);
+  expect(screen.queryByText("footer.privacy")).toHaveAttribute(
+    "href",
+    "https://www.raspberrypi.org/privacy/child-friendly",
+  );
+});
 
-test('Links to cookie policy', () => {
-  render(<Footer/>)
-  expect(screen.queryByText('footer.cookies')).toHaveAttribute('href', 'https://www.raspberrypi.org/cookies')
-})
+test("Links to cookie policy", () => {
+  render(<Footer />);
+  expect(screen.queryByText("footer.cookies")).toHaveAttribute(
+    "href",
+    "https://www.raspberrypi.org/cookies",
+  );
+});
 
-test('Links to accessibility policy', () => {
-  render(<Footer/>)
-  expect(screen.queryByText('footer.accessibility')).toHaveAttribute('href', 'https://www.raspberrypi.org/accessibility')
-})
+test("Links to accessibility policy", () => {
+  render(<Footer />);
+  expect(screen.queryByText("footer.accessibility")).toHaveAttribute(
+    "href",
+    "https://www.raspberrypi.org/accessibility",
+  );
+});
 
-test('Links to safeguarding policy', () => {
-  render(<Footer/>)
-  expect(screen.queryByText('footer.safeguarding')).toHaveAttribute('href', 'https://www.raspberrypi.org/safeguarding')
-})
+test("Links to safeguarding policy", () => {
+  render(<Footer />);
+  expect(screen.queryByText("footer.safeguarding")).toHaveAttribute(
+    "href",
+    "https://www.raspberrypi.org/safeguarding",
+  );
+});
diff --git a/src/components/GlobalNav/GlobalNav.js b/src/components/GlobalNav/GlobalNav.js
index c5226cc7a..3abedc108 100644
--- a/src/components/GlobalNav/GlobalNav.js
+++ b/src/components/GlobalNav/GlobalNav.js
@@ -3,33 +3,42 @@ import { useSelector } from "react-redux";
 import { ChevronDown } from "../../Icons";
 import LoginMenu from "../Login/LoginMenu";
 import Dropdown from "../Menus/Dropdown/Dropdown";
-import './GlobalNav.scss';
-import rpf_logo from '../../assets/raspberrypi_logo.svg'
-import user_logo from '../../assets/unauthenticated_user.svg'
+import "./GlobalNav.scss";
+import rpf_logo from "../../assets/raspberrypi_logo.svg";
+import user_logo from "../../assets/unauthenticated_user.svg";
 import { useTranslation } from "react-i18next";
 
 const GlobalNav = () => {
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
-  const user = useSelector((state) => state.auth.user)
+  const user = useSelector((state) => state.auth.user);
   return (
     <div className="editor-global-nav-wrapper">
-      <div className='editor-global-nav'>
-        <a className='editor-global-nav__home' href='https://www.raspberrypi.org/'>
-          <img src={rpf_logo} alt={t('globalNav.raspberryPiLogoAltText')} />
+      <div className="editor-global-nav">
+        <a
+          className="editor-global-nav__home"
+          href="https://www.raspberrypi.org/"
+        >
+          <img src={rpf_logo} alt={t("globalNav.raspberryPiLogoAltText")} />
           <span>Raspberry Pi Foundation</span>
         </a>
-        <div className='editor-global-nav__account'>
+        <div className="editor-global-nav__account">
           <Dropdown
             buttonImage={user ? user.profile.picture : user_logo}
-            buttonImageAltText={user ? t('globalNav.accountMenuProfileAltText', { name: user.profile.name }) : t('globalNav.accountMenuDefaultAltText')}
+            buttonImageAltText={
+              user
+                ? t("globalNav.accountMenuProfileAltText", {
+                    name: user.profile.name,
+                  })
+                : t("globalNav.accountMenuDefaultAltText")
+            }
             ButtonIcon={ChevronDown}
             MenuContent={LoginMenu}
           />
         </div>
       </div>
     </div>
-  )
-}
+  );
+};
 
 export default GlobalNav;
diff --git a/src/components/GlobalNav/GlobalNav.test.js b/src/components/GlobalNav/GlobalNav.test.js
index a87292aff..0501de51f 100644
--- a/src/components/GlobalNav/GlobalNav.test.js
+++ b/src/components/GlobalNav/GlobalNav.test.js
@@ -1,44 +1,60 @@
 import React from "react";
-import { render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import GlobalNav from "./GlobalNav";
 
-test('Global nav renders', () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+test("Global nav renders", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><GlobalNav/></Provider>);
-  expect(screen.queryByText("Raspberry Pi Foundation")).toBeInTheDocument()
-})
+  render(
+    <Provider store={store}>
+      <GlobalNav />
+    </Provider>,
+  );
+  expect(screen.queryByText("Raspberry Pi Foundation")).toBeInTheDocument();
+});
 
-test('When not logged in renders generic profile image', () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+test("When not logged in renders generic profile image", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
-    auth: {}
-  }
+    auth: {},
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><GlobalNav/></Provider>);
-  expect(screen.queryByAltText('globalNav.accountMenuDefaultAltText')).toBeInTheDocument()
-})
+  render(
+    <Provider store={store}>
+      <GlobalNav />
+    </Provider>,
+  );
+  expect(
+    screen.queryByAltText("globalNav.accountMenuDefaultAltText"),
+  ).toBeInTheDocument();
+});
 
-test('When logged in renders user\'s profile image', () => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+test("When logged in renders user's profile image", () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     auth: {
       user: {
         profile: {
-          picture: 'image_url'
-        }
-      }
-    }
-  }
+          picture: "image_url",
+        },
+      },
+    },
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><GlobalNav/></Provider>);
-  expect(screen.queryByAltText('globalNav.accountMenuProfileAltText')).toHaveAttribute('src', 'image_url')
-})
+  render(
+    <Provider store={store}>
+      <GlobalNav />
+    </Provider>,
+  );
+  expect(
+    screen.queryByAltText("globalNav.accountMenuProfileAltText"),
+  ).toHaveAttribute("src", "image_url");
+});
diff --git a/src/components/Header/Autosave.js b/src/components/Header/Autosave.js
index 9550a75b7..7e7444341 100644
--- a/src/components/Header/Autosave.js
+++ b/src/components/Header/Autosave.js
@@ -1,44 +1,53 @@
-import { intlFormatDistance } from 'date-fns'
+import { intlFormatDistance } from "date-fns";
 
-import { useState, useEffect} from 'react'
-import { useSelector } from 'react-redux'
-import { useTranslation } from 'react-i18next';
-
-import { CloudUploadIcon, CloudTickIcon } from '../../Icons';
+import { useState, useEffect } from "react";
+import { useSelector } from "react-redux";
+import { useTranslation } from "react-i18next";
 
+import { CloudUploadIcon, CloudTickIcon } from "../../Icons";
 
 const Autosave = () => {
-  const { t } = useTranslation()
-  const lastSavedTime = useSelector((state) => state.editor.lastSavedTime)
-  const saving = useSelector((state) => state.editor.saving)
+  const { t } = useTranslation();
+  const lastSavedTime = useSelector((state) => state.editor.lastSavedTime);
+  const saving = useSelector((state) => state.editor.saving);
   const [time, setTime] = useState(Date.now());
 
-  const isPending = saving === 'pending'
+  const isPending = saving === "pending";
 
   useEffect(() => {
-    setTime(Date.now())
+    setTime(Date.now());
 
     const statusTick = setInterval(() => {
-      setTime(Date.now())
+      setTime(Date.now());
     }, 10000);
 
-    return () => clearInterval(statusTick)
+    return () => clearInterval(statusTick);
   }, [lastSavedTime]);
 
   return (
-    <div className='autosave'>
-      { isPending ?
+    <div className="autosave">
+      {isPending ? (
         <>
-          <div className='autosave__icon'><CloudUploadIcon /></div>
-          <div className='autosave__status'>{t('header.autoSaving')}&hellip;</div>
-        </> :
+          <div className="autosave__icon">
+            <CloudUploadIcon />
+          </div>
+          <div className="autosave__status">
+            {t("header.autoSaving")}&hellip;
+          </div>
+        </>
+      ) : (
         <>
-          <div className='autosave__icon'><CloudTickIcon /></div>
-          <div className='autosave__status'>{t('header.autoSaved')} {intlFormatDistance(lastSavedTime, time, { style: 'narrow' })}</div>
+          <div className="autosave__icon">
+            <CloudTickIcon />
+          </div>
+          <div className="autosave__status">
+            {t("header.autoSaved")}{" "}
+            {intlFormatDistance(lastSavedTime, time, { style: "narrow" })}
+          </div>
         </>
-      }
+      )}
     </div>
-  )
-}
+  );
+};
 
-export default Autosave
\ No newline at end of file
+export default Autosave;
diff --git a/src/components/Header/DownloadButton.js b/src/components/Header/DownloadButton.js
index 40a076153..32bbd3d76 100644
--- a/src/components/Header/DownloadButton.js
+++ b/src/components/Header/DownloadButton.js
@@ -10,41 +10,51 @@ import Button from "../Button/Button";
 import { closeLoginToSaveModal } from "../Editor/EditorSlice";
 
 const DownloadButton = (props) => {
-  const { buttonText, className, Icon } = props
-  const { t } = useTranslation()
-  const project = useSelector((state) => state.editor.project)
-  const loginToSaveModalShowing = useSelector((state) => state.editor.loginToSaveModalShowing)
-  const dispatch = useDispatch()
+  const { buttonText, className, Icon } = props;
+  const { t } = useTranslation();
+  const project = useSelector((state) => state.editor.project);
+  const loginToSaveModalShowing = useSelector(
+    (state) => state.editor.loginToSaveModalShowing,
+  );
+  const dispatch = useDispatch();
 
   const urlToPromise = (url) => {
-    return new Promise(function(resolve, reject) {
+    return new Promise(function (resolve, reject) {
       JSZipUtils.getBinaryContent(url, function (err, data) {
-        if(err) {
+        if (err) {
           reject(err);
         } else {
           resolve(data);
         }
       });
     });
-  }
+  };
 
   const onClickDownload = async () => {
     if (loginToSaveModalShowing) {
-      dispatch(closeLoginToSaveModal())
+      dispatch(closeLoginToSaveModal());
     }
-    const zip = new JSZip()
+    const zip = new JSZip();
 
     project.components.forEach((file) => {
-      zip.file(`${file.name}.${file.extension}`, file.content)
-    })
+      zip.file(`${file.name}.${file.extension}`, file.content);
+    });
 
     project.image_list.forEach((image) => {
-      zip.file(image.filename, urlToPromise(image.url), {binary: true} )
-    })
+      zip.file(image.filename, urlToPromise(image.url), { binary: true });
+    });
 
-    const content = await zip.generateAsync({type: 'blob'})
-    FileSaver.saveAs(content, `${toSnakeCase(project.name || t('header.downloadFileNameDefault', {project_type: project.project_type}))}`)
-  }
+    const content = await zip.generateAsync({ type: "blob" });
+    FileSaver.saveAs(
+      content,
+      `${toSnakeCase(
+        project.name ||
+          t("header.downloadFileNameDefault", {
+            project_type: project.project_type,
+          }),
+      )}`,
+    );
+  };
 
   return (
     <Button
@@ -53,7 +63,7 @@ const DownloadButton = (props) => {
       buttonText={buttonText}
       ButtonIcon={Icon}
     />
-  )
-}
+  );
+};
 
-export default DownloadButton
+export default DownloadButton;
diff --git a/src/components/Header/DownloadButton.test.js b/src/components/Header/DownloadButton.test.js
index 46b4d669c..cb85cab10 100644
--- a/src/components/Header/DownloadButton.test.js
+++ b/src/components/Header/DownloadButton.test.js
@@ -1,123 +1,150 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import DownloadButton from "./DownloadButton";
-import FileSaver from 'file-saver';
-import JSZip from 'jszip'
-import JSZipUtils from 'jszip-utils'
+import FileSaver from "file-saver";
+import JSZip from "jszip";
+import JSZipUtils from "jszip-utils";
 import { closeLoginToSaveModal } from "../Editor/EditorSlice";
 
-jest.mock("file-saver")
-jest.mock("jszip")
+jest.mock("file-saver");
+jest.mock("jszip");
 jest.mock("jszip-utils", () => ({
-  getBinaryContent: jest.fn()
-}))
-
-describe('Downloading project with name set', () => {
+  getBinaryContent: jest.fn(),
+}));
 
+describe("Downloading project with name set", () => {
   let downloadButton;
 
   beforeEach(() => {
     JSZip.mockClear();
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
-          name: 'My epic project',
+          name: "My epic project",
           identifier: "hello-world-project",
           components: [
             {
-              name: 'main',
-              extension: 'py',
-              content: 'print(\'hello world\')'
-  
-            }
+              name: "main",
+              extension: "py",
+              content: "print('hello world')",
+            },
           ],
           image_list: [
             {
-              url: 'a.com/b'
-            }
-          ]
+              url: "a.com/b",
+            },
+          ],
         },
       },
-    }
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><DownloadButton buttonText='Download'/></Provider>)
-    downloadButton = screen.queryByText('Download').parentElement
-  })
-  
-  test('Download button renders', ()=> {
-    expect(downloadButton).toBeInTheDocument()
-  })
-  
-  test('Clicking download zips project file content', async () => {
-    fireEvent.click(downloadButton)
+    render(
+      <Provider store={store}>
+        <DownloadButton buttonText="Download" />
+      </Provider>,
+    );
+    downloadButton = screen.queryByText("Download").parentElement;
+  });
+
+  test("Download button renders", () => {
+    expect(downloadButton).toBeInTheDocument();
+  });
+
+  test("Clicking download zips project file content", async () => {
+    fireEvent.click(downloadButton);
     const JSZipInstance = JSZip.mock.instances[0];
     const mockFile = JSZipInstance.file;
-    await waitFor( () => expect(mockFile).toHaveBeenCalledWith('main.py', 'print(\'hello world\')'))
-  })
-  
-  test('Clicking download triggers request for image', async () => {
-    fireEvent.click(downloadButton)
-    await waitFor(() => expect(JSZipUtils.getBinaryContent).toHaveBeenCalledWith('a.com/b', expect.anything()))
-  })
-  
-  test('Clicking download button creates download with correct name', async () => {
-    fireEvent.click(downloadButton)
-    await waitFor( () => expect(FileSaver.saveAs).toHaveBeenCalledWith(undefined, 'my_epic_project'))
-  })
-})
+    await waitFor(() =>
+      expect(mockFile).toHaveBeenCalledWith("main.py", "print('hello world')"),
+    );
+  });
+
+  test("Clicking download triggers request for image", async () => {
+    fireEvent.click(downloadButton);
+    await waitFor(() =>
+      expect(JSZipUtils.getBinaryContent).toHaveBeenCalledWith(
+        "a.com/b",
+        expect.anything(),
+      ),
+    );
+  });
+
+  test("Clicking download button creates download with correct name", async () => {
+    fireEvent.click(downloadButton);
+    await waitFor(() =>
+      expect(FileSaver.saveAs).toHaveBeenCalledWith(
+        undefined,
+        "my_epic_project",
+      ),
+    );
+  });
+});
 
-describe('Downloading project with no name set', () => {
+describe("Downloading project with no name set", () => {
   let downloadButton;
 
   beforeEach(() => {
     JSZip.mockClear();
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
-              name: 'main',
-              extension: 'py',
-              content: ''
-            }
+              name: "main",
+              extension: "py",
+              content: "",
+            },
           ],
-          image_list: []
+          image_list: [],
         },
       },
-    }
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><DownloadButton buttonText='Download'/></Provider>)
-    downloadButton = screen.queryByText('Download').parentElement
-  })
+    render(
+      <Provider store={store}>
+        <DownloadButton buttonText="Download" />
+      </Provider>,
+    );
+    downloadButton = screen.queryByText("Download").parentElement;
+  });
 
-  test('Clicking download button creates download with default name', async () => {
-    fireEvent.click(downloadButton)
-    await waitFor( () => expect(FileSaver.saveAs).toHaveBeenCalledWith(undefined, 'header_download_file_name_default'))
-  })
-})
+  test("Clicking download button creates download with default name", async () => {
+    fireEvent.click(downloadButton);
+    await waitFor(() =>
+      expect(FileSaver.saveAs).toHaveBeenCalledWith(
+        undefined,
+        "header_download_file_name_default",
+      ),
+    );
+  });
+});
 
-test('If login to save modal open, closes it when download clicked', () => {
+test("If login to save modal open, closes it when download clicked", () => {
   JSZip.mockClear();
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
       project: {
         components: [],
-        image_list: []
+        image_list: [],
       },
-      loginToSaveModalShowing: true
+      loginToSaveModalShowing: true,
     },
-  }
+  };
   const store = mockStore(initialState);
-  render(<Provider store={store}><DownloadButton buttonText='Download'/></Provider>)
-  const downloadButton = screen.queryByText('Download').parentElement
-  fireEvent.click(downloadButton)
-  expect(store.getActions()).toEqual([closeLoginToSaveModal()])
-})
+  render(
+    <Provider store={store}>
+      <DownloadButton buttonText="Download" />
+    </Provider>,
+  );
+  const downloadButton = screen.queryByText("Download").parentElement;
+  fireEvent.click(downloadButton);
+  expect(store.getActions()).toEqual([closeLoginToSaveModal()]);
+});
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
index 1cb2a0e03..076f59956 100644
--- a/src/components/Header/Header.js
+++ b/src/components/Header/Header.js
@@ -1,68 +1,104 @@
-import './Header.scss'
-import { useSelector, useDispatch } from 'react-redux'
-import { useTranslation } from 'react-i18next';
-import Autosave from './Autosave';
-import Button from '../Button/Button';
-import { DownloadIcon, HomeIcon, SettingsIcon } from '../../Icons';
-import { syncProject, showLoginToSaveModal } from '../Editor/EditorSlice';
-import Dropdown from '../Menus/Dropdown/Dropdown';
-import SettingsMenu from '../Menus/SettingsMenu/SettingsMenu';
-import ProjectName from './ProjectName';
-import htmlLogo from '../../assets/html_icon.svg'
-import pythonLogo from '../../assets/python_icon.svg'
-import DownloadButton from './DownloadButton';
-import { isOwner } from '../../utils/projectHelpers'
-import { Link } from 'react-router-dom';
+import "./Header.scss";
+import { useSelector, useDispatch } from "react-redux";
+import { useTranslation } from "react-i18next";
+import Autosave from "./Autosave";
+import Button from "../Button/Button";
+import { DownloadIcon, HomeIcon, SettingsIcon } from "../../Icons";
+import { syncProject, showLoginToSaveModal } from "../Editor/EditorSlice";
+import Dropdown from "../Menus/Dropdown/Dropdown";
+import SettingsMenu from "../Menus/SettingsMenu/SettingsMenu";
+import ProjectName from "./ProjectName";
+import htmlLogo from "../../assets/html_icon.svg";
+import pythonLogo from "../../assets/python_icon.svg";
+import DownloadButton from "./DownloadButton";
+import { isOwner } from "../../utils/projectHelpers";
+import { Link } from "react-router-dom";
 
 const Header = () => {
-  const dispatch = useDispatch()
-  const { t, i18n } = useTranslation()
-  
-  const user = useSelector((state) => state.auth.user)
-  const project = useSelector((state) => state.editor.project)
-  const loading = useSelector((state) => state.editor.loading)
-  const saving = useSelector((state) => state.editor.saving)
-  const lastSavedTime = useSelector((state) => state.editor.lastSavedTime)
-  const locale = i18n.language
+  const dispatch = useDispatch();
+  const { t, i18n } = useTranslation();
+
+  const user = useSelector((state) => state.auth.user);
+  const project = useSelector((state) => state.editor.project);
+  const loading = useSelector((state) => state.editor.loading);
+  const saving = useSelector((state) => state.editor.saving);
+  const lastSavedTime = useSelector((state) => state.editor.lastSavedTime);
+  const locale = i18n.language;
 
   const onClickSave = async () => {
-    window.plausible('Save button')
+    window.plausible("Save button");
 
     if (isOwner(user, project)) {
-      dispatch(syncProject('save')({project, accessToken: user.access_token, autosave: false}))
+      dispatch(
+        syncProject("save")({
+          project,
+          accessToken: user.access_token,
+          autosave: false,
+        }),
+      );
     } else if (user && project.identifier) {
-      dispatch(syncProject('remix')({project, accessToken: user.access_token}))
+      dispatch(
+        syncProject("remix")({ project, accessToken: user.access_token }),
+      );
     } else {
-      dispatch(showLoginToSaveModal())
+      dispatch(showLoginToSaveModal());
     }
-  }
+  };
 
-  return loading === 'success' && (
-    <div className='editor-header-wrapper'>
-      <header className='editor-header'>
-        <img className='editor-logo' src={project.project_type === 'python' ? pythonLogo : htmlLogo } alt={t('header.editorLogoAltText')}/>
-        { user !== null ? (
-          <Link to={`${locale}/projects`} className='project-gallery-link' reloadDocument>
-            {<><HomeIcon />
-            <span className='editor-header__text'>{t('header.projects')}</span></>}</Link>
-        ) : null }
-        { loading === 'success' ? <ProjectName /> : null }
-        <div className='editor-header__right'>
-          { lastSavedTime && user ? <Autosave saving={saving} lastSavedTime={lastSavedTime} /> : null }
-          { loading === 'success' ?
-          <DownloadButton buttonText={t('header.download')} className='btn--tertiary' Icon={DownloadIcon}/>
-          : null }
-          <Dropdown
-            ButtonIcon={SettingsIcon}
-            buttonText={t('header.settings')}
-            MenuContent={SettingsMenu} />
-          {loading === 'success' ?
-            <Button className='btn--primary btn--save' onClickHandler = {onClickSave} buttonText = {t('header.save')} />
-          : null }
-        </div>
-      </header>
-    </div>
-  )
+  return (
+    loading === "success" && (
+      <div className="editor-header-wrapper">
+        <header className="editor-header">
+          <img
+            className="editor-logo"
+            src={project.project_type === "python" ? pythonLogo : htmlLogo}
+            alt={t("header.editorLogoAltText")}
+          />
+          {user !== null ? (
+            <Link
+              to={`${locale}/projects`}
+              className="project-gallery-link"
+              reloadDocument
+            >
+              {
+                <>
+                  <HomeIcon />
+                  <span className="editor-header__text">
+                    {t("header.projects")}
+                  </span>
+                </>
+              }
+            </Link>
+          ) : null}
+          {loading === "success" ? <ProjectName /> : null}
+          <div className="editor-header__right">
+            {lastSavedTime && user ? (
+              <Autosave saving={saving} lastSavedTime={lastSavedTime} />
+            ) : null}
+            {loading === "success" ? (
+              <DownloadButton
+                buttonText={t("header.download")}
+                className="btn--tertiary"
+                Icon={DownloadIcon}
+              />
+            ) : null}
+            <Dropdown
+              ButtonIcon={SettingsIcon}
+              buttonText={t("header.settings")}
+              MenuContent={SettingsMenu}
+            />
+            {loading === "success" ? (
+              <Button
+                className="btn--primary btn--save"
+                onClickHandler={onClickSave}
+                buttonText={t("header.save")}
+              />
+            ) : null}
+          </div>
+        </header>
+      </div>
+    )
+  );
 };
 
 export default Header;
diff --git a/src/components/Header/Header.test.js b/src/components/Header/Header.test.js
index fcd847ee5..80fdc0207 100644
--- a/src/components/Header/Header.test.js
+++ b/src/components/Header/Header.test.js
@@ -1,227 +1,264 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import Header from "./Header";
 import { syncProject, showLoginToSaveModal } from "../Editor/EditorSlice";
 import { MemoryRouter } from "react-router-dom";
 
-jest.mock('axios');
+jest.mock("axios");
 
-jest.mock('react-router-dom', () => ({
-  ...jest.requireActual('react-router-dom'),
-  useNavigate: () => jest.fn()
+jest.mock("react-router-dom", () => ({
+  ...jest.requireActual("react-router-dom"),
+  useNavigate: () => jest.fn(),
 }));
 
-jest.mock('../Editor/EditorSlice', () => ({
-  ...jest.requireActual('../Editor/EditorSlice'),
-  syncProject: jest.fn((_) => jest.fn())
-}))
+jest.mock("../Editor/EditorSlice", () => ({
+  ...jest.requireActual("../Editor/EditorSlice"),
+  syncProject: jest.fn((_) => jest.fn()),
+}));
 
 const project = {
-  name: 'Hello world',
+  name: "Hello world",
   identifier: "hello-world-project",
   components: [],
   image_list: [],
-  user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-}
+  user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+};
 const user = {
   access_token: "39a09671-be55-4847-baf5-8919a0c24a25",
   profile: {
-    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-  }
-}
-
+    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+  },
+};
 
 describe("When logged in and user owns project", () => {
   let store;
   let saveButton;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        loading: 'success',
+        loading: "success",
       },
       auth: {
-        user: user
-      }
-    }
+        user: user,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><Header/></MemoryRouter></Provider>);
-    saveButton = screen.queryByText('header.save')
-  })
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <Header />
+        </MemoryRouter>
+      </Provider>,
+    );
+    saveButton = screen.queryByText("header.save");
+  });
 
   test("Renders project gallery link", () => {
-    expect(screen.queryByText('header.projects')).not.toBeNull();
-  })
+    expect(screen.queryByText("header.projects")).not.toBeNull();
+  });
 
-  test('Project name is shown', () => {
-    expect(screen.queryByText(project.name)).toBeInTheDocument()
-  })
+  test("Project name is shown", () => {
+    expect(screen.queryByText(project.name)).toBeInTheDocument();
+  });
 
-  test('Download button shown', () => {
-    expect(screen.queryByText('header.download')).toBeInTheDocument()
-  })
+  test("Download button shown", () => {
+    expect(screen.queryByText("header.download")).toBeInTheDocument();
+  });
 
   test("Clicking save dispatches saveProject with correct parameters", async () => {
-    const saveAction = {type: 'SAVE_PROJECT' }
-    const saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    fireEvent.click(saveButton)
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({
-      project,
-      accessToken: user.access_token,
-      autosave: false
-    }))
-    expect(store.getActions()[0]).toEqual(saveAction)
-  })
-})
+    const saveAction = { type: "SAVE_PROJECT" };
+    const saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    fireEvent.click(saveButton);
+    await waitFor(() =>
+      expect(saveProject).toHaveBeenCalledWith({
+        project,
+        accessToken: user.access_token,
+        autosave: false,
+      }),
+    );
+    expect(store.getActions()[0]).toEqual(saveAction);
+  });
+});
 
 describe("When logged in and no project identifier", () => {
   let store;
-  const project_without_id = { ...project, identifier: null }
+  const project_without_id = { ...project, identifier: null };
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project_without_id,
-        loading: 'success',
+        loading: "success",
       },
       auth: {
-        user: user
-      }
-    }
+        user: user,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><Header/></MemoryRouter></Provider>);
-  })
-
-  test('Download button shown', () => {
-    expect(screen.queryByText('header.download')).toBeInTheDocument()
-  })
-
-  test('Project name is shown', () => {
-    expect(screen.queryByText(project.name)).toBeInTheDocument()
-   })
-
-   test("Clicking save dispatches saveProject with correct parameters", async () => {
-    const saveAction = {type: 'SAVE_PROJECT' }
-    const saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    const saveButton = screen.getByText('header.save')
-    fireEvent.click(saveButton)
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({
-      project: project_without_id,
-      accessToken: user.access_token,
-      autosave: false
-    }))
-    expect(store.getActions()[0]).toEqual(saveAction)
-  })
-})
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <Header />
+        </MemoryRouter>
+      </Provider>,
+    );
+  });
+
+  test("Download button shown", () => {
+    expect(screen.queryByText("header.download")).toBeInTheDocument();
+  });
+
+  test("Project name is shown", () => {
+    expect(screen.queryByText(project.name)).toBeInTheDocument();
+  });
+
+  test("Clicking save dispatches saveProject with correct parameters", async () => {
+    const saveAction = { type: "SAVE_PROJECT" };
+    const saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    const saveButton = screen.getByText("header.save");
+    fireEvent.click(saveButton);
+    await waitFor(() =>
+      expect(saveProject).toHaveBeenCalledWith({
+        project: project_without_id,
+        accessToken: user.access_token,
+        autosave: false,
+      }),
+    );
+    expect(store.getActions()[0]).toEqual(saveAction);
+  });
+});
 
 describe("When logged in and user does not own project", () => {
-  const another_project = { ...project, user_id: '5254370e-26d2-4c8a-9526-8dbafea43aa9'}
+  const another_project = {
+    ...project,
+    user_id: "5254370e-26d2-4c8a-9526-8dbafea43aa9",
+  };
   let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: another_project,
-        loading: 'success',
+        loading: "success",
       },
       auth: {
-        user: user
-      }
-    }
+        user: user,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><Header/></MemoryRouter></Provider>);
-  })
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <Header />
+        </MemoryRouter>
+      </Provider>,
+    );
+  });
 
   test("Clicking save dispatches remixProject with correct parameters", async () => {
-    const remixAction = {type: 'REMIX_PROJECT' }
-    const remixProject = jest.fn(() => (remixAction))
-    syncProject.mockImplementationOnce(jest.fn((_) => remixProject))
-    const saveButton = screen.getByText('header.save')
-    fireEvent.click(saveButton)
-    await waitFor(() => expect(remixProject).toHaveBeenCalledWith({
-      project: another_project,
-      accessToken: user.access_token
-    }))
-    expect(store.getActions()[0]).toEqual(remixAction)
-  })
-})
+    const remixAction = { type: "REMIX_PROJECT" };
+    const remixProject = jest.fn(() => remixAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => remixProject));
+    const saveButton = screen.getByText("header.save");
+    fireEvent.click(saveButton);
+    await waitFor(() =>
+      expect(remixProject).toHaveBeenCalledWith({
+        project: another_project,
+        accessToken: user.access_token,
+      }),
+    );
+    expect(store.getActions()[0]).toEqual(remixAction);
+  });
+});
 
 describe("When not logged in", () => {
-  let store
+  let store;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
-        editor: {
-          project: project,
-          loading: 'success',
-        },
-        auth: {
-          user: null
-        }
-      }
+      editor: {
+        project: project,
+        loading: "success",
+      },
+      auth: {
+        user: null,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><Header/></MemoryRouter></Provider>);
-  })
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <Header />
+        </MemoryRouter>
+      </Provider>,
+    );
+  });
 
   test("No project gallery link", () => {
-    expect(screen.queryByText('header.projects')).toBeNull();
-  })
+    expect(screen.queryByText("header.projects")).toBeNull();
+  });
 
-  test('Download button shown', () => {
-    expect(screen.queryByText('header.download')).toBeInTheDocument()
-  })
+  test("Download button shown", () => {
+    expect(screen.queryByText("header.download")).toBeInTheDocument();
+  });
 
-  test('Project name is shown', () => {
-    expect(screen.queryByText(project.name)).toBeInTheDocument()
-  })
+  test("Project name is shown", () => {
+    expect(screen.queryByText(project.name)).toBeInTheDocument();
+  });
 
-  test('Clicking save opens login to save modal', () => {
-    const saveButton = screen.getByText('header.save')
-    fireEvent.click(saveButton)
-    expect(store.getActions()).toEqual([showLoginToSaveModal()])
-  })
-})
-
-describe('When no project loaded', () => {
+  test("Clicking save opens login to save modal", () => {
+    const saveButton = screen.getByText("header.save");
+    fireEvent.click(saveButton);
+    expect(store.getActions()).toEqual([showLoginToSaveModal()]);
+  });
+});
 
+describe("When no project loaded", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
-        editor: {
-          project: {},
-          loading: 'idle',
-        },
-        auth: {
-          user: user
-        }
-      }
+      editor: {
+        project: {},
+        loading: "idle",
+      },
+      auth: {
+        user: user,
+      },
+    };
     const store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><Header/></MemoryRouter></Provider>);
-  })
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <Header />
+        </MemoryRouter>
+      </Provider>,
+    );
+  });
 
-  test('No project name', () => {
-    expect(screen.queryByText(project.name)).not.toBeInTheDocument()
-  })
+  test("No project name", () => {
+    expect(screen.queryByText(project.name)).not.toBeInTheDocument();
+  });
 
-  test('No download button', () => {
-    expect(screen.queryByText('header.download')).not.toBeInTheDocument()
-  })
+  test("No download button", () => {
+    expect(screen.queryByText("header.download")).not.toBeInTheDocument();
+  });
 
-  test('No save button', () => {
-    expect(screen.queryByText('header.save')).not.toBeInTheDocument()
-  })
-})
+  test("No save button", () => {
+    expect(screen.queryByText("header.save")).not.toBeInTheDocument();
+  });
+});
diff --git a/src/components/Header/ProjectName.js b/src/components/Header/ProjectName.js
index 918989cf8..eeb3f6d6c 100644
--- a/src/components/Header/ProjectName.js
+++ b/src/components/Header/ProjectName.js
@@ -1,61 +1,70 @@
-import React, { useEffect, useRef, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { useDispatch, useSelector } from 'react-redux'
-import { PencilIcon } from '../../Icons';
-import Button from '../Button/Button';
-import { updateProjectName } from '../Editor/EditorSlice';
+import React, { useEffect, useRef, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useDispatch, useSelector } from "react-redux";
+import { PencilIcon } from "../../Icons";
+import Button from "../Button/Button";
+import { updateProjectName } from "../Editor/EditorSlice";
 
-import './ProjectName.scss';
+import "./ProjectName.scss";
 
 const ProjectName = () => {
-  const project = useSelector((state) => state.editor.project)
+  const project = useSelector((state) => state.editor.project);
   const dispatch = useDispatch();
-  const { t } = useTranslation()
-  const nameInput= useRef();
-  const [isEditable, setEditable] = useState(false)
+  const { t } = useTranslation();
+  const nameInput = useRef();
+  const [isEditable, setEditable] = useState(false);
 
   useEffect(() => {
     if (isEditable) {
-      nameInput.current.focus()
+      nameInput.current.focus();
     }
-  })
+  });
 
   const updateName = () => {
-    setEditable(false)
-    dispatch(updateProjectName(nameInput.current.value))
-  }
+    setEditable(false);
+    dispatch(updateProjectName(nameInput.current.value));
+  };
   const onEditNameButtonClick = () => {
-    setEditable(true)
-  }
+    setEditable(true);
+  };
 
   const handleKeyDown = (event) => {
-    if (event.key === 'Enter') {
-      event.preventDefault()
-      nameInput.current.blur()
-    } else if (event.key === 'Escape') {
-      event.preventDefault()
-      setEditable(false)
+    if (event.key === "Enter") {
+      event.preventDefault();
+      nameInput.current.blur();
+    } else if (event.key === "Escape") {
+      event.preventDefault();
+      setEditable(false);
     }
-  }
+  };
 
   return (
-   <div className='project-name'>
-    {isEditable ? 
-      <input
-        className='project-name__input'
-        ref={nameInput}
-        type='text'
-        onBlur={updateName}
-        onKeyDown={handleKeyDown}
-        defaultValue={project.name} />
-      :
-      <>
-        <h1 className='project-name__title'>{project.name||t('header.newProject')}</h1>
-        <Button className='btn--tertiary project-name__button' label={t('header.buttonLabel')} title={t('header.buttonTitle')} ButtonIcon={PencilIcon} onClickHandler={onEditNameButtonClick} />
-      </>
-      }
+    <div className="project-name">
+      {isEditable ? (
+        <input
+          className="project-name__input"
+          ref={nameInput}
+          type="text"
+          onBlur={updateName}
+          onKeyDown={handleKeyDown}
+          defaultValue={project.name}
+        />
+      ) : (
+        <>
+          <h1 className="project-name__title">
+            {project.name || t("header.newProject")}
+          </h1>
+          <Button
+            className="btn--tertiary project-name__button"
+            label={t("header.buttonLabel")}
+            title={t("header.buttonTitle")}
+            ButtonIcon={PencilIcon}
+            onClickHandler={onEditNameButtonClick}
+          />
+        </>
+      )}
     </div>
-  )
+  );
 };
 
 export default ProjectName;
diff --git a/src/components/Header/ProjectName.test.js b/src/components/Header/ProjectName.test.js
index 9712fb3c1..0050ba6ab 100644
--- a/src/components/Header/ProjectName.test.js
+++ b/src/components/Header/ProjectName.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import ProjectName from "./ProjectName";
 import { updateProjectName } from "../Editor/EditorSlice";
@@ -9,83 +9,89 @@ import { updateProjectName } from "../Editor/EditorSlice";
 const project = {
   identifier: "hello-world-project",
   name: "Hello world",
-  user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-}
+  user_id: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+};
 
-let store
-let editButton
+let store;
+let editButton;
 
 beforeEach(() => {
-  const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: project,
-      }
-    }
-    store = mockStore(initialState);
-    render(<Provider store={store}><ProjectName/></Provider>);
-    editButton = screen.queryByRole('button')
-})
-
-test('Project name renders in a heading', () => {
-  expect(screen.queryByText(project.name).tagName).toBe('H1')
-})
-
-test('Clicking edit button changes the project name to an input field', () => {
-  fireEvent.click(editButton)
-  expect(screen.queryByRole('textbox')).toHaveValue(project.name)
-})
-
-test('Clicking edit button transfers focus to input field', () => {
-  fireEvent.click(editButton)
-  expect(screen.queryByRole('textbox')).toHaveFocus()
-})
-
-describe('When input field loses focus', () => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: project,
+    },
+  };
+  store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <ProjectName />
+    </Provider>,
+  );
+  editButton = screen.queryByRole("button");
+});
+
+test("Project name renders in a heading", () => {
+  expect(screen.queryByText(project.name).tagName).toBe("H1");
+});
+
+test("Clicking edit button changes the project name to an input field", () => {
+  fireEvent.click(editButton);
+  expect(screen.queryByRole("textbox")).toHaveValue(project.name);
+});
+
+test("Clicking edit button transfers focus to input field", () => {
+  fireEvent.click(editButton);
+  expect(screen.queryByRole("textbox")).toHaveFocus();
+});
+
+describe("When input field loses focus", () => {
   beforeEach(() => {
-    fireEvent.click(editButton)
-    const inputField = screen.queryByRole('textbox')
-    inputField.blur()
-  })
-
-  test('Updates project name', () => {
-    expect(store.getActions()).toEqual([updateProjectName(project.name)])
-  })
-
-  test('Changes project name to heading', async () => {
-    await waitFor(() => expect(screen.queryByText(project.name).tagName).toBe('H1'))
-  })
-})
-
-describe('When Enter is pressed', () => {
+    fireEvent.click(editButton);
+    const inputField = screen.queryByRole("textbox");
+    inputField.blur();
+  });
+
+  test("Updates project name", () => {
+    expect(store.getActions()).toEqual([updateProjectName(project.name)]);
+  });
+
+  test("Changes project name to heading", async () => {
+    await waitFor(() =>
+      expect(screen.queryByText(project.name).tagName).toBe("H1"),
+    );
+  });
+});
+
+describe("When Enter is pressed", () => {
   beforeEach(() => {
-    fireEvent.click(editButton)
-    const inputField = screen.queryByRole('textbox')
-    fireEvent.keyDown(inputField, { key: 'Enter'})
-  })
+    fireEvent.click(editButton);
+    const inputField = screen.queryByRole("textbox");
+    fireEvent.keyDown(inputField, { key: "Enter" });
+  });
 
-  test('Updates project name', () => {
-    expect(store.getActions()).toEqual([updateProjectName(project.name)])
-  })
+  test("Updates project name", () => {
+    expect(store.getActions()).toEqual([updateProjectName(project.name)]);
+  });
 
-  test('Changes project name to heading', () => {
-    expect(screen.queryByText(project.name).tagName).toBe('H1')
-  })
-})
+  test("Changes project name to heading", () => {
+    expect(screen.queryByText(project.name).tagName).toBe("H1");
+  });
+});
 
-describe('When Escape is pressed', () => {
+describe("When Escape is pressed", () => {
   beforeEach(() => {
-    fireEvent.click(editButton)
-    const inputField = screen.queryByRole('textbox')
-    fireEvent.keyDown(inputField, { key: 'Escape'})
-  })
-
-  test('Updates project name', () => {
-    expect(store.getActions()).toEqual([])
-  })
-
-  test('Changes project name to heading', () => {
-    expect(screen.queryByText(project.name).tagName).toBe('H1')
-  })
-})
+    fireEvent.click(editButton);
+    const inputField = screen.queryByRole("textbox");
+    fireEvent.keyDown(inputField, { key: "Escape" });
+  });
+
+  test("Updates project name", () => {
+    expect(store.getActions()).toEqual([]);
+  });
+
+  test("Changes project name to heading", () => {
+    expect(screen.queryByText(project.name).tagName).toBe("H1");
+  });
+});
diff --git a/src/components/LocaleLayout/LocaleLayout.test.js b/src/components/LocaleLayout/LocaleLayout.test.js
index 6f9ac422e..b28108817 100644
--- a/src/components/LocaleLayout/LocaleLayout.test.js
+++ b/src/components/LocaleLayout/LocaleLayout.test.js
@@ -38,7 +38,7 @@ describe("When locale is allowed", () => {
     render(
       <MemoryRouter>
         <LocaleLayout />
-      </MemoryRouter>
+      </MemoryRouter>,
     );
   });
 
@@ -75,13 +75,13 @@ describe("When locale is not allowed", () => {
     render(
       <MemoryRouter>
         <LocaleLayout />
-      </MemoryRouter>
+      </MemoryRouter>,
     );
   });
 
   test("Redirects to default language", () => {
     expect(mockNavigate).toHaveBeenCalledWith(
-      "/default/projects/my-amazing-project"
+      "/default/projects/my-amazing-project",
     );
   });
 });
diff --git a/src/components/Login/LoginButton.js b/src/components/Login/LoginButton.js
index c12c93c95..d897532fc 100644
--- a/src/components/Login/LoginButton.js
+++ b/src/components/Login/LoginButton.js
@@ -1,23 +1,29 @@
-import React from 'react';
-import { useLocation } from 'react-router-dom';
-import { useSelector } from 'react-redux';
-import Button from '../Button/Button';
-import { login } from '../../utils/login';
+import React from "react";
+import { useLocation } from "react-router-dom";
+import { useSelector } from "react-redux";
+import Button from "../Button/Button";
+import { login } from "../../utils/login";
 
 const LoginButton = (props) => {
   const { buttonText, className, triggerSave } = props;
-  const location = useLocation()
-  const project = useSelector((state) => state.editor.project)
-  const accessDeniedData = useSelector((state) => state.editor.modals.accessDenied)
+  const location = useLocation();
+  const project = useSelector((state) => state.editor.project);
+  const accessDeniedData = useSelector(
+    (state) => state.editor.modals.accessDenied,
+  );
 
   const onLoginButtonClick = (event) => {
     event.preventDefault();
-    login({project, location, triggerSave, accessDeniedData})
-  }
+    login({ project, location, triggerSave, accessDeniedData });
+  };
 
   return (
-    <Button buttonText={buttonText} className={className} onClickHandler={onLoginButtonClick} />
-  )
-}
+    <Button
+      buttonText={buttonText}
+      className={className}
+      onClickHandler={onLoginButtonClick}
+    />
+  );
+};
 
 export default LoginButton;
diff --git a/src/components/Login/LoginButton.test.js b/src/components/Login/LoginButton.test.js
index d5bd33e6d..28b8892bc 100644
--- a/src/components/Login/LoginButton.test.js
+++ b/src/components/Login/LoginButton.test.js
@@ -1,144 +1,170 @@
 import React from "react";
 import { MemoryRouter } from "react-router-dom";
-import configureStore from 'redux-mock-store';
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
+import configureStore from "redux-mock-store";
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
 import userManager from "../../utils/userManager";
 import LoginButton from "./LoginButton";
 
 jest.mock("../../utils/userManager", () => ({
-  signinRedirect: jest.fn()
-}))
+  signinRedirect: jest.fn(),
+}));
 
 const project = {
   components: [
     {
-      name: 'main',
-      extension: 'py',
-      content: 'print("hello world")'
-    }
-  ]
-}
+      name: "main",
+      extension: "py",
+      content: 'print("hello world")',
+    },
+  ],
+};
 let loginButton;
 
-describe('When accessDeniedData is false', () => {
+describe("When accessDeniedData is false", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        modals: {}
+        modals: {},
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/my_project']}><Provider store={store}><LoginButton buttonText='Login' /></Provider></MemoryRouter>)
-    loginButton = screen.queryByText('Login')
-  })
+    render(
+      <MemoryRouter initialEntries={["/my_project"]}>
+        <Provider store={store}>
+          <LoginButton buttonText="Login" />
+        </Provider>
+      </MemoryRouter>,
+    );
+    loginButton = screen.queryByText("Login");
+  });
 
   test("Login button shown", () => {
-    expect(loginButton).toBeInTheDocument()
-  })
+    expect(loginButton).toBeInTheDocument();
+  });
 
   test("Clicking login button signs the user in", () => {
-    fireEvent.click(loginButton)
-    expect(userManager.signinRedirect).toHaveBeenCalled()
-  })
+    fireEvent.click(loginButton);
+    expect(userManager.signinRedirect).toHaveBeenCalled();
+  });
 
   test("Clicking login button saves the user's project content in local storage", () => {
-    fireEvent.click(loginButton)
-    expect(localStorage.getItem('project')).toBe(JSON.stringify(project))
-  })
+    fireEvent.click(loginButton);
+    expect(localStorage.getItem("project")).toBe(JSON.stringify(project));
+  });
 
   test("Clicking login button saves user's location to local storage", () => {
-    fireEvent.click(loginButton)
-    expect(localStorage.getItem('location')).toBe('/my_project')
-  })
-})
+    fireEvent.click(loginButton);
+    expect(localStorage.getItem("location")).toBe("/my_project");
+  });
+});
 
-describe('When accessDeniedData is true', () => {
+describe("When accessDeniedData is true", () => {
   beforeEach(() => {
-    project.identifier = 'hello-world-project'
-    project.projectType = 'python'
+    project.identifier = "hello-world-project";
+    project.projectType = "python";
 
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
         modals: {
           accessDenied: {
             identifier: project.identifier,
-            projectType: project.projectType
-          }
-        }
+            projectType: project.projectType,
+          },
+        },
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/hello-world-project']}><Provider store={store}><LoginButton buttonText='Login' /></Provider></MemoryRouter>)
-    loginButton = screen.queryByText('Login')
-  })
+    render(
+      <MemoryRouter initialEntries={["/hello-world-project"]}>
+        <Provider store={store}>
+          <LoginButton buttonText="Login" />
+        </Provider>
+      </MemoryRouter>,
+    );
+    loginButton = screen.queryByText("Login");
+  });
 
   test("Clicking the login button saves user's location to local storage", () => {
-    fireEvent.click(loginButton)
-    expect(localStorage.getItem('location')).toBe('/projects/hello-world-project')
-  })
-})
+    fireEvent.click(loginButton);
+    expect(localStorage.getItem("location")).toBe(
+      "/projects/hello-world-project",
+    );
+  });
+});
 
-describe('When login button has triggerSave set', () => {
+describe("When login button has triggerSave set", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        modals: {}
+        modals: {},
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/my_project']}><Provider store={store}><LoginButton buttonText='Login' triggerSave/></Provider></MemoryRouter>)
-    loginButton = screen.queryByText('Login')
-  })
+    render(
+      <MemoryRouter initialEntries={["/my_project"]}>
+        <Provider store={store}>
+          <LoginButton buttonText="Login" triggerSave />
+        </Provider>
+      </MemoryRouter>,
+    );
+    loginButton = screen.queryByText("Login");
+  });
 
   test("Clicking login button sets 'awaitingSave' in local storage", () => {
-    fireEvent.click(loginButton)
-    expect(localStorage.getItem('awaitingSave')).toBe('true')
-  })
-})
+    fireEvent.click(loginButton);
+    expect(localStorage.getItem("awaitingSave")).toBe("true");
+  });
+});
 
-describe('When login button does not have triggerSave set', () => {
+describe("When login button does not have triggerSave set", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: project,
-        modals: {}
+        modals: {},
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/my_project']}><Provider store={store}><LoginButton buttonText='Login'/></Provider></MemoryRouter>)
-    loginButton = screen.queryByText('Login')
-  })
+    render(
+      <MemoryRouter initialEntries={["/my_project"]}>
+        <Provider store={store}>
+          <LoginButton buttonText="Login" />
+        </Provider>
+      </MemoryRouter>,
+    );
+    loginButton = screen.queryByText("Login");
+  });
 
   test("Clicking login button does not set 'awaitingSave' in local storage", () => {
-    fireEvent.click(loginButton)
-    expect(localStorage.getItem('awaitingSave')).toBeNull()
-  })
-})
+    fireEvent.click(loginButton);
+    expect(localStorage.getItem("awaitingSave")).toBeNull();
+  });
+});
 
 afterEach(() => {
-  localStorage.clear()
-})
+  localStorage.clear();
+});
diff --git a/src/components/Login/LoginMenu.js b/src/components/Login/LoginMenu.js
index 8a888beef..af5a67abb 100644
--- a/src/components/Login/LoginMenu.js
+++ b/src/components/Login/LoginMenu.js
@@ -3,26 +3,35 @@ import { useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 import LogoutButton from "./LogoutButton";
 import LoginButton from "./LoginButton";
-import './LoginMenu.scss'
+import "./LoginMenu.scss";
 
 const LoginMenu = () => {
-
-  const { t } = useTranslation()
-  const user = useSelector((state) => state.auth.user)
+  const { t } = useTranslation();
+  const user = useSelector((state) => state.auth.user);
 
   return (
-    <div className = 'dropdown-container dropdown-container--bottom dropdown-container--list login-menu'>
-      {user !== null ?
-      <>
-        <a className='dropdown-container--list__item' href={`${user.profile.profile}/edit`}>{t('globalNav.accountMenu.profile')}</a>
-        <a className='dropdown-container--list__item' href='/projects'>{t('globalNav.accountMenu.projects')}</a>
-        <LogoutButton className='btn--tertiary dropdown-container--list__item' />
-      </>
-      :
-      <LoginButton buttonText={t('globalNav.accountMenu.login')} className='btn--tertiary dropdown-container--list__item'/>
-    }
+    <div className="dropdown-container dropdown-container--bottom dropdown-container--list login-menu">
+      {user !== null ? (
+        <>
+          <a
+            className="dropdown-container--list__item"
+            href={`${user.profile.profile}/edit`}
+          >
+            {t("globalNav.accountMenu.profile")}
+          </a>
+          <a className="dropdown-container--list__item" href="/projects">
+            {t("globalNav.accountMenu.projects")}
+          </a>
+          <LogoutButton className="btn--tertiary dropdown-container--list__item" />
+        </>
+      ) : (
+        <LoginButton
+          buttonText={t("globalNav.accountMenu.login")}
+          className="btn--tertiary dropdown-container--list__item"
+        />
+      )}
     </div>
-  ) 
-}
+  );
+};
 
-export default LoginMenu
+export default LoginMenu;
diff --git a/src/components/Login/LoginMenu.test.js b/src/components/Login/LoginMenu.test.js
index 7f8484bd2..b8b145a35 100644
--- a/src/components/Login/LoginMenu.test.js
+++ b/src/components/Login/LoginMenu.test.js
@@ -1,71 +1,94 @@
 import React from "react";
-import { render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import { MemoryRouter } from "react-router-dom";
 import LoginMenu from "./LoginMenu";
 
-describe('When not logged in', () => {
-
+describe("When not logged in", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {},
-        modals: {}
+        modals: {},
       },
       auth: {
-        user: null
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/']}><Provider store={store}><LoginMenu/></Provider></MemoryRouter>);
-  })
-
-  test('Login button renders', () => {
-    expect(screen.queryByText('globalNav.accountMenu.login')).toBeInTheDocument()
-  })
+    render(
+      <MemoryRouter initialEntries={["/"]}>
+        <Provider store={store}>
+          <LoginMenu />
+        </Provider>
+      </MemoryRouter>,
+    );
+  });
 
-  test('My profile does not render', () => {
-    expect(screen.queryByText('globalNav.accountMenu.profile')).not.toBeInTheDocument()
-  })
+  test("Login button renders", () => {
+    expect(
+      screen.queryByText("globalNav.accountMenu.login"),
+    ).toBeInTheDocument();
+  });
 
-  test('My projects does not render', () => {
-    expect(screen.queryByText('globalNav.accountMenu.projects')).not.toBeInTheDocument()
-  })
-})
+  test("My profile does not render", () => {
+    expect(
+      screen.queryByText("globalNav.accountMenu.profile"),
+    ).not.toBeInTheDocument();
+  });
 
-describe('When logged in', () => {
+  test("My projects does not render", () => {
+    expect(
+      screen.queryByText("globalNav.accountMenu.projects"),
+    ).not.toBeInTheDocument();
+  });
+});
 
+describe("When logged in", () => {
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
-        project: {}
+        project: {},
       },
       auth: {
         user: {
           profile: {
-            profile: 'profile_url'
-          }
-        }
-      }
-    }
+            profile: "profile_url",
+          },
+        },
+      },
+    };
     const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/']}><Provider store={store}><LoginMenu/></Provider></MemoryRouter>);
-  })
+    render(
+      <MemoryRouter initialEntries={["/"]}>
+        <Provider store={store}>
+          <LoginMenu />
+        </Provider>
+      </MemoryRouter>,
+    );
+  });
 
-  test('Logout button renders', () => {
-    expect(screen.queryByText('globalNav.accountMenu.logout')).toBeInTheDocument()
-  })
+  test("Logout button renders", () => {
+    expect(
+      screen.queryByText("globalNav.accountMenu.logout"),
+    ).toBeInTheDocument();
+  });
 
-  test('My profile renders with correct link', () => {
-    expect(screen.queryByText('globalNav.accountMenu.profile')).toHaveAttribute('href', 'profile_url/edit')
-  })
+  test("My profile renders with correct link", () => {
+    expect(screen.queryByText("globalNav.accountMenu.profile")).toHaveAttribute(
+      "href",
+      "profile_url/edit",
+    );
+  });
 
-  test('My projects renders with correct link', () => {
-    expect(screen.queryByText('globalNav.accountMenu.projects')).toHaveAttribute('href', '/projects')
-  })
-})
+  test("My projects renders with correct link", () => {
+    expect(
+      screen.queryByText("globalNav.accountMenu.projects"),
+    ).toHaveAttribute("href", "/projects");
+  });
+});
diff --git a/src/components/Login/LogoutButton.js b/src/components/Login/LogoutButton.js
index d148e5771..f8adbc770 100644
--- a/src/components/Login/LogoutButton.js
+++ b/src/components/Login/LogoutButton.js
@@ -1,24 +1,28 @@
-import React from 'react';
-import userManager from '../../utils/userManager'
-import { useTranslation } from 'react-i18next';
-import Button from '../Button/Button';
-import { useNavigate } from 'react-router-dom';
+import React from "react";
+import userManager from "../../utils/userManager";
+import { useTranslation } from "react-i18next";
+import Button from "../Button/Button";
+import { useNavigate } from "react-router-dom";
 
 const LogoutButton = (props) => {
   const { className } = props;
-  const { t } = useTranslation()
-  const navigate = useNavigate()
+  const { t } = useTranslation();
+  const navigate = useNavigate();
 
   const onLogoutButtonClick = async (event) => {
     event.preventDefault();
-    await userManager.removeUser()
-    localStorage.clear()
-    navigate('/')
-  }
+    await userManager.removeUser();
+    localStorage.clear();
+    navigate("/");
+  };
 
   return (
-    <Button buttonText={t('globalNav.accountMenu.logout')} className={className} onClickHandler={onLogoutButtonClick} />
-  )
-}
+    <Button
+      buttonText={t("globalNav.accountMenu.logout")}
+      className={className}
+      onClickHandler={onLogoutButtonClick}
+    />
+  );
+};
 
 export default LogoutButton;
diff --git a/src/components/Login/LogoutButton.test.js b/src/components/Login/LogoutButton.test.js
index f723d4484..33a19bbff 100644
--- a/src/components/Login/LogoutButton.test.js
+++ b/src/components/Login/LogoutButton.test.js
@@ -1,38 +1,44 @@
 import React from "react";
 import { MemoryRouter } from "react-router-dom";
-import configureStore from 'redux-mock-store';
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
+import configureStore from "redux-mock-store";
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
 import userManager from "../../utils/userManager";
 import LogoutButton from "./LogoutButton";
 
 jest.mock("../../utils/userManager", () => ({
-  removeUser: jest.fn()
-}))
+  removeUser: jest.fn(),
+}));
 
 let logoutButton;
 
-  beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
-    const initialState = {
-      editor: {
-        project: {}
-      },
-      auth: {
-        user: {}
-      }
-    }
-    const store = mockStore(initialState);
-    render(<MemoryRouter initialEntries={['/']}><Provider store={store}><LogoutButton /></Provider></MemoryRouter>)
-    logoutButton = screen.queryByText('globalNav.accountMenu.logout')
-  })
+beforeEach(() => {
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
+  const initialState = {
+    editor: {
+      project: {},
+    },
+    auth: {
+      user: {},
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <MemoryRouter initialEntries={["/"]}>
+      <Provider store={store}>
+        <LogoutButton />
+      </Provider>
+    </MemoryRouter>,
+  );
+  logoutButton = screen.queryByText("globalNav.accountMenu.logout");
+});
 
-  test("Log out button shown", () => {
-    expect(logoutButton).toBeInTheDocument()
-  })
+test("Log out button shown", () => {
+  expect(logoutButton).toBeInTheDocument();
+});
 
-  test("Clicking log out button signs the user out", () => {
-    fireEvent.click(logoutButton)
-    expect(userManager.removeUser).toHaveBeenCalled()
-  })
+test("Clicking log out button signs the user out", () => {
+  fireEvent.click(logoutButton);
+  expect(userManager.removeUser).toHaveBeenCalled();
+});
diff --git a/src/components/Menus/ContextMenu/ContextMenu.js b/src/components/Menus/ContextMenu/ContextMenu.js
index 641666ca1..31f8dc9ae 100644
--- a/src/components/Menus/ContextMenu/ContextMenu.js
+++ b/src/components/Menus/ContextMenu/ContextMenu.js
@@ -2,64 +2,79 @@ import React, { useContext, useRef, useState } from "react";
 import { ControlledMenu, MenuItem } from "@szhsin/react-menu";
 import { SettingsContext } from "../../../settings";
 
-import './ContextMenu.scss'
+import "./ContextMenu.scss";
 
 const ContextMenu = (props) => {
-
-  const { align, direction, menuButtonLabel, menuButtonClassName, MenuButtonIcon, menuOptions, offsetX, offsetY,} = props
-  const settings = useContext(SettingsContext)
-  const menuButton = useRef(null)
-  const contextMenu = useRef()
-  const [isOpen, setOpen] = useState(false)
+  const {
+    align,
+    direction,
+    menuButtonLabel,
+    menuButtonClassName,
+    MenuButtonIcon,
+    menuOptions,
+    offsetX,
+    offsetY,
+  } = props;
+  const settings = useContext(SettingsContext);
+  const menuButton = useRef(null);
+  const contextMenu = useRef();
+  const [isOpen, setOpen] = useState(false);
   const setMenuOpenState = (isMenuOpen) => {
-    setOpen(isMenuOpen)
+    setOpen(isMenuOpen);
     if (isMenuOpen) {
-      const hiddenDiv = contextMenu.current.firstChild
-      hiddenDiv.setAttribute('role', 'menuitem')
-      hiddenDiv.setAttribute('aria-hidden', 'true')
+      const hiddenDiv = contextMenu.current.firstChild;
+      hiddenDiv.setAttribute("role", "menuitem");
+      hiddenDiv.setAttribute("aria-hidden", "true");
     } else {
-      menuButton.current.focus()
+      menuButton.current.focus();
     }
-  }
+  };
 
   return (
     <>
       <button
         aria-haspopup="menu"
         aria-label={menuButtonLabel}
-        className = {`btn btn-tertiary context-menu__drop${menuButtonClassName ? ` ${menuButtonClassName}` : ''}`}
+        className={`btn btn-tertiary context-menu__drop${
+          menuButtonClassName ? ` ${menuButtonClassName}` : ""
+        }`}
         title={menuButtonLabel}
         type="button"
         ref={menuButton}
         onClick={() => setMenuOpenState(true)}
       >
-        <MenuButtonIcon/>
+        <MenuButtonIcon />
       </button>
       <ControlledMenu
         transition
         align={align}
         direction={direction}
-        menuStyle={{padding: '5px'}}
+        menuStyle={{ padding: "5px" }}
         offsetX={offsetX}
         offsetY={offsetY}
-        position='anchor'
-        viewScroll='initial'
+        position="anchor"
+        viewScroll="initial"
         portal={true}
         menuClassName={`context-menu context-menu--${settings.theme}`}
-        menuItemFocus={{position: 'first'}}
-        state={isOpen ? 'open' : 'closed'}
+        menuItemFocus={{ position: "first" }}
+        state={isOpen ? "open" : "closed"}
         anchorRef={menuButton}
         ref={contextMenu}
         onClose={() => setMenuOpenState(false)}
       >
-      {menuOptions.map((option, i) => (
-        <MenuItem key={i} className='btn context-menu__item'  onClick={option.action} >
-          <option.icon/>&nbsp;{option.text}
-        </MenuItem>
-      ))}
-    </ControlledMenu>
-  </>
-  )
-}
+        {menuOptions.map((option, i) => (
+          <MenuItem
+            key={i}
+            className="btn context-menu__item"
+            onClick={option.action}
+          >
+            <option.icon />
+            &nbsp;{option.text}
+          </MenuItem>
+        ))}
+      </ControlledMenu>
+    </>
+  );
+};
 
-export default ContextMenu
+export default ContextMenu;
diff --git a/src/components/Menus/ContextMenu/ContextMenu.test.js b/src/components/Menus/ContextMenu/ContextMenu.test.js
index a097291ec..f14830fe2 100644
--- a/src/components/Menus/ContextMenu/ContextMenu.test.js
+++ b/src/components/Menus/ContextMenu/ContextMenu.test.js
@@ -1,50 +1,49 @@
-import React from 'react'
-import { fireEvent, render, screen } from '@testing-library/react'
-import { axe, toHaveNoViolations }from 'jest-axe'
-import ContextMenu from './ContextMenu'
+import React from "react";
+import { fireEvent, render, screen } from "@testing-library/react";
+import { axe, toHaveNoViolations } from "jest-axe";
+import ContextMenu from "./ContextMenu";
 
-expect.extend(toHaveNoViolations)
-const action1 = jest.fn()
+expect.extend(toHaveNoViolations);
+const action1 = jest.fn();
 
 describe("With file items", () => {
-
   beforeEach(() => {
     render(
       <ContextMenu
-        MenuButtonIcon = {() => {}}
-        menuButtonLabel = 'button'
-        menuOptions={[{text: 'option1', action: action1, icon: () => {}}]}
-      />
-    )
-  })
+        MenuButtonIcon={() => {}}
+        menuButtonLabel="button"
+        menuOptions={[{ text: "option1", action: action1, icon: () => {} }]}
+      />,
+    );
+  });
 
   test("Menu is not visible initially", () => {
-    expect(screen.queryByRole('menu')).not.toBeInTheDocument()
-  })
+    expect(screen.queryByRole("menu")).not.toBeInTheDocument();
+  });
 
   test("Clicking button makes menu content appear", () => {
-    const button = screen.getByRole('button')
-    fireEvent.click(button)
-    expect(screen.queryByRole('menu')).toBeInTheDocument()
-  })
+    const button = screen.getByRole("button");
+    fireEvent.click(button);
+    expect(screen.queryByRole("menu")).toBeInTheDocument();
+  });
 
   test("Clicking option button calls action", () => {
-    const button = screen.getByRole('button')
-    fireEvent.click(button)
-    const menuOption = screen.queryByText('option1')
-    fireEvent.click(menuOption)
-    expect(action1).toHaveBeenCalled()
-  })
+    const button = screen.getByRole("button");
+    fireEvent.click(button);
+    const menuOption = screen.queryByText("option1");
+    fireEvent.click(menuOption);
+    expect(action1).toHaveBeenCalled();
+  });
 
   test("It passes AXE accessibility testing when menu is closed", async () => {
-    const axeResults = await axe(screen.queryByRole("button"))
-    expect(axeResults).toHaveNoViolations()
-  })
+    const axeResults = await axe(screen.queryByRole("button"));
+    expect(axeResults).toHaveNoViolations();
+  });
 
   test("It passes AXE accessibility testing when menu is open", async () => {
-    const button = screen.getByRole('button')
-    fireEvent.click(button)
-    const axeResults = await axe(screen.queryByRole("menu"))
-    expect(axeResults).toHaveNoViolations()
-  })
-})
+    const button = screen.getByRole("button");
+    fireEvent.click(button);
+    const axeResults = await axe(screen.queryByRole("menu"));
+    expect(axeResults).toHaveNoViolations();
+  });
+});
diff --git a/src/components/Menus/Dropdown/Dropdown.js b/src/components/Menus/Dropdown/Dropdown.js
index 8f432ad40..34e201bbe 100644
--- a/src/components/Menus/Dropdown/Dropdown.js
+++ b/src/components/Menus/Dropdown/Dropdown.js
@@ -1,20 +1,26 @@
 import React, { useEffect, useRef, useState } from "react";
 import Button from "../../Button/Button";
 
-import './Dropdown.scss'
+import "./Dropdown.scss";
 
 const Dropdown = (props) => {
-  const {ButtonIcon, buttonImage, buttonImageAltText, buttonText, MenuContent} = props
-  const [isOpen, setOpen] = useState(false)
-  const dropdown = useRef()
-  
+  const {
+    ButtonIcon,
+    buttonImage,
+    buttonImageAltText,
+    buttonText,
+    MenuContent,
+  } = props;
+  const [isOpen, setOpen] = useState(false);
+  const dropdown = useRef();
+
   useEffect(() => {
     /**
      * Close menu if clicked outside of element
      */
     function handleClickOutside(event) {
       if (dropdown.current && !dropdown.current.contains(event.target)) {
-        setOpen(false)
+        setOpen(false);
       }
     }
     // Bind the event listener
@@ -26,29 +32,35 @@ const Dropdown = (props) => {
   }, [dropdown]);
 
   const handleKeyDown = (event) => {
-    if (event.key === 'Escape'){
+    if (event.key === "Escape") {
       setOpen(false);
     }
-  }
+  };
 
   return (
-    <div className='dropdown' ref={dropdown} onKeyDown={handleKeyDown}>
+    <div className="dropdown" ref={dropdown} onKeyDown={handleKeyDown}>
       <Button
-        className={`btn--tertiary dropdown-button${isOpen ? ' dropdown-button--active' : ''}`}
+        className={`btn--tertiary dropdown-button${
+          isOpen ? " dropdown-button--active" : ""
+        }`}
         onClickHandler={() => setOpen(!isOpen)}
         buttonText={buttonText}
         ButtonIcon={ButtonIcon}
         buttonImage={buttonImage}
         buttonImageAltText={buttonImageAltText}
       />
-      
-      {isOpen ? 
-      <>
-        <div className='dropdown-backdrop' onClick={() => setOpen(false)}></div>
-        <MenuContent />
-      </> : null}
+
+      {isOpen ? (
+        <>
+          <div
+            className="dropdown-backdrop"
+            onClick={() => setOpen(false)}
+          ></div>
+          <MenuContent />
+        </>
+      ) : null}
     </div>
-  )
-}
+  );
+};
 
-export default Dropdown
+export default Dropdown;
diff --git a/src/components/Menus/Dropdown/Dropdown.test.js b/src/components/Menus/Dropdown/Dropdown.test.js
index 20f995715..510967268 100644
--- a/src/components/Menus/Dropdown/Dropdown.test.js
+++ b/src/components/Menus/Dropdown/Dropdown.test.js
@@ -5,47 +5,50 @@ import Dropdown from "./Dropdown";
 
 const buttonIcon = () => {
   return (
-  <svg><title>my icon</title></svg>
-  )
-}
+    <svg>
+      <title>my icon</title>
+    </svg>
+  );
+};
 const MenuContent = () => {
-  return (
-    <h1>Menu</h1>
-  )
-}
+  return <h1>Menu</h1>;
+};
 let queryByTitle;
 let queryByText;
 let getByText;
 let queryByRole;
 
 beforeEach(() => {
-  ({getByText, queryByRole, queryByText, queryByTitle} = render(<Dropdown
-    ButtonIcon={buttonIcon}
-    buttonText='my button'
-    MenuContent={MenuContent}/>))
-})
+  ({ getByText, queryByRole, queryByText, queryByTitle } = render(
+    <Dropdown
+      ButtonIcon={buttonIcon}
+      buttonText="my button"
+      MenuContent={MenuContent}
+    />,
+  ));
+});
 
 test("Button icon renders", () => {
-  expect(queryByTitle('my icon')).not.toBeNull()
-})
+  expect(queryByTitle("my icon")).not.toBeNull();
+});
 
 test("Button text renders", () => {
-  expect(queryByText('my button')).not.toBeNull()
-})
+  expect(queryByText("my button")).not.toBeNull();
+});
 
 test("Menu content not disable intially", () => {
-  expect(queryByRole('heading', {level: 1, name: "Menu"})).toBeNull()
-})
+  expect(queryByRole("heading", { level: 1, name: "Menu" })).toBeNull();
+});
 
 test("Clicking button makes menu content appear", () => {
-  const button = getByText('my button').parentElement
-  fireEvent.click(button)
-  expect(queryByRole('heading', {level: 1, name: "Menu"})).not.toBeNull()
-})
+  const button = getByText("my button").parentElement;
+  fireEvent.click(button);
+  expect(queryByRole("heading", { level: 1, name: "Menu" })).not.toBeNull();
+});
 
 test("Clicking outside menu makes it close", () => {
-  const button = getByText('my button').parentElement
-  fireEvent.click(button)
-  userEvent.click(document.body)
-  expect(queryByRole('heading', {level: 1, name: "Menu"})).toBeNull()
-})
+  const button = getByText("my button").parentElement;
+  fireEvent.click(button);
+  userEvent.click(document.body);
+  expect(queryByRole("heading", { level: 1, name: "Menu" })).toBeNull();
+});
diff --git a/src/components/Menus/FileMenu/FileMenu.js b/src/components/Menus/FileMenu/FileMenu.js
index 6fbecdc5d..cdd4ca74f 100644
--- a/src/components/Menus/FileMenu/FileMenu.js
+++ b/src/components/Menus/FileMenu/FileMenu.js
@@ -1,38 +1,38 @@
-import React from "react"
-import { useDispatch } from 'react-redux'
+import React from "react";
+import { useDispatch } from "react-redux";
 import { useTranslation } from "react-i18next";
 
-import { showRenameFileModal } from '../../Editor/EditorSlice'
-import { EllipsisVerticalIcon, PencilIcon } from '../../../Icons';
+import { showRenameFileModal } from "../../Editor/EditorSlice";
+import { EllipsisVerticalIcon, PencilIcon } from "../../../Icons";
 import ContextMenu from "../ContextMenu/ContextMenu";
 
 const FileMenu = (props) => {
-  const dispatch = useDispatch()
-  const { t } = useTranslation()
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
 
   const onClickRenameFile = () => {
-    dispatch(showRenameFileModal(props))
-  }
+    dispatch(showRenameFileModal(props));
+  };
 
   return (
-    <div onClick = {(e) => e.stopPropagation()}>
+    <div onClick={(e) => e.stopPropagation()}>
       <ContextMenu
-        align = 'start'
-        direction = 'right'
-        menuButtonLabel={t('filePane.fileMenu.label')}
-        MenuButtonIcon = {EllipsisVerticalIcon}
-        menuOptions = {[
+        align="start"
+        direction="right"
+        menuButtonLabel={t("filePane.fileMenu.label")}
+        MenuButtonIcon={EllipsisVerticalIcon}
+        menuOptions={[
           {
             icon: PencilIcon,
-            text: t('filePane.fileMenu.renameItem'),
-            action: onClickRenameFile
-          }
+            text: t("filePane.fileMenu.renameItem"),
+            action: onClickRenameFile,
+          },
         ]}
         offsetX={15}
         offsetY={-10}
       />
     </div>
-  )
-}
-  
-export default FileMenu
+  );
+};
+
+export default FileMenu;
diff --git a/src/components/Menus/FileMenu/FileMenu.test.js b/src/components/Menus/FileMenu/FileMenu.test.js
index e55ba2338..a6c242739 100644
--- a/src/components/Menus/FileMenu/FileMenu.test.js
+++ b/src/components/Menus/FileMenu/FileMenu.test.js
@@ -1,66 +1,68 @@
-import { fireEvent, render, screen } from '@testing-library/react'
-import { Provider } from 'react-redux'
-import { MemoryRouter } from 'react-router-dom'
-import configureStore from 'redux-mock-store'
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import { MemoryRouter } from "react-router-dom";
+import configureStore from "redux-mock-store";
 
-import FileMenu from './FileMenu'
-import { showRenameFileModal } from '../../Editor/EditorSlice'
-import { SettingsContext } from '../../../settings'
+import FileMenu from "./FileMenu";
+import { showRenameFileModal } from "../../Editor/EditorSlice";
+import { SettingsContext } from "../../../settings";
 
 describe("with file item", () => {
   let store;
 
   beforeEach(() => {
-    const mockStore = configureStore([])
+    const mockStore = configureStore([]);
     const initialState = {
       editor: {
         project: {
           components: [],
-          imageList: []
+          imageList: [],
         },
         isEmbedded: false,
         renameFileModalShowing: false,
         modals: {},
-      }
-    }
-    store = mockStore(initialState)
+      },
+    };
+    store = mockStore(initialState);
     render(
-      <MemoryRouter initialEntries={['/']}>
+      <MemoryRouter initialEntries={["/"]}>
         <Provider store={store}>
-          <SettingsContext.Provider value={{ theme: 'dark', fontSize: 'small' }}>
+          <SettingsContext.Provider
+            value={{ theme: "dark", fontSize: "small" }}
+          >
             <div id="app">
-              <FileMenu fileKey={0} name={'file1'} ext={'py'} />
+              <FileMenu fileKey={0} name={"file1"} ext={"py"} />
             </div>
           </SettingsContext.Provider>
         </Provider>
-      </MemoryRouter>
-    )
-  })
+      </MemoryRouter>,
+    );
+  });
 
   test("Menu is not visible initially", () => {
-    expect(screen.queryByRole('menu')).toBeNull()
-  })
+    expect(screen.queryByRole("menu")).toBeNull();
+  });
 
   test("Clicking button makes menu content appear", () => {
-    const button = screen.getByRole('button')
-    fireEvent.click(button)
-    expect(screen.queryByRole('menu')).not.toBeNull()
-  })
+    const button = screen.getByRole("button");
+    fireEvent.click(button);
+    expect(screen.queryByRole("menu")).not.toBeNull();
+  });
 
   test("All file functions are listed", () => {
-    const button = screen.getByRole('button')
-    fireEvent.click(button)
-    expect(screen.getByText('filePane.fileMenu.renameItem')).not.toBeNull()
-  })
+    const button = screen.getByRole("button");
+    fireEvent.click(button);
+    expect(screen.getByText("filePane.fileMenu.renameItem")).not.toBeNull();
+  });
 
   test("Clicking rename dispatches modal show with file details", () => {
-    const menuButton = screen.getByRole('button')
-    fireEvent.click(menuButton)
-    const renameButton = screen.getByText('filePane.fileMenu.renameItem')
-    fireEvent.click(renameButton)
+    const menuButton = screen.getByRole("button");
+    fireEvent.click(menuButton);
+    const renameButton = screen.getByText("filePane.fileMenu.renameItem");
+    fireEvent.click(renameButton);
     const expectedActions = [
-      showRenameFileModal({fileKey: 0, ext: "py", name: "file1"})
-    ]
+      showRenameFileModal({ fileKey: 0, ext: "py", name: "file1" }),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
-})
+  });
+});
diff --git a/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.js b/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.js
index 43b2d1c0d..02cc07b4e 100644
--- a/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.js
+++ b/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.js
@@ -2,44 +2,47 @@ import React from "react";
 import { useTranslation } from "react-i18next";
 import { useDispatch } from "react-redux";
 import { BinIcon, EllipsisVerticalIcon, PencilIcon } from "../../../Icons";
-import { showDeleteProjectModal, showRenameProjectModal } from "../../Editor/EditorSlice";
+import {
+  showDeleteProjectModal,
+  showRenameProjectModal,
+} from "../../Editor/EditorSlice";
 import ContextMenu from "../ContextMenu/ContextMenu";
 
 const ProjectActionsMenu = (props) => {
-  const { project } = props
-  const { t } = useTranslation()
-  const dispatch = useDispatch()
+  const { project } = props;
+  const { t } = useTranslation();
+  const dispatch = useDispatch();
 
   const openRenameProjectModal = () => {
-    dispatch(showRenameProjectModal(project))
-  }
+    dispatch(showRenameProjectModal(project));
+  };
 
   const openDeleteProjectModal = () => {
-    dispatch(showDeleteProjectModal(project))
-  }
+    dispatch(showDeleteProjectModal(project));
+  };
 
   return (
     <ContextMenu
-      align = 'end'
-      direction = 'bottom'
-      menuButtonLabel = {t('projectList.label')}
-      menuButtonClassName = 'editor-project-list__menu'
-      MenuButtonIcon = {EllipsisVerticalIcon}
-      menuOptions = {[
+      align="end"
+      direction="bottom"
+      menuButtonLabel={t("projectList.label")}
+      menuButtonClassName="editor-project-list__menu"
+      MenuButtonIcon={EllipsisVerticalIcon}
+      menuOptions={[
         {
           icon: PencilIcon,
-          text: t('projectList.rename'),
-          action: openRenameProjectModal
+          text: t("projectList.rename"),
+          action: openRenameProjectModal,
         },
         {
           icon: BinIcon,
-          text: t('projectList.delete'),
-          action: openDeleteProjectModal
-        }
+          text: t("projectList.delete"),
+          action: openDeleteProjectModal,
+        },
       ]}
       offsetX={-10}
     />
-  )
-}
+  );
+};
 
-export default ProjectActionsMenu
+export default ProjectActionsMenu;
diff --git a/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.test.js b/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.test.js
index 43bdd71c6..02d8c0bb4 100644
--- a/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.test.js
+++ b/src/components/Menus/ProjectActionsMenu/ProjectActionsMenu.test.js
@@ -2,40 +2,54 @@ import { fireEvent, render, screen } from "@testing-library/react";
 import React from "react";
 import { Provider } from "react-redux";
 import ProjectActionsMenu from "./ProjectActionsMenu";
-import configureStore from 'redux-mock-store';
+import configureStore from "redux-mock-store";
 
-let store
+let store;
 
 beforeEach(() => {
-  const mockStore = configureStore([])
-  const initialState = {}
+  const mockStore = configureStore([]);
+  const initialState = {};
   store = mockStore(initialState);
 
-  render(<Provider store={store}><ProjectActionsMenu project = {{name: 'my amazing project'}}/></Provider>)
-})
+  render(
+    <Provider store={store}>
+      <ProjectActionsMenu project={{ name: "my amazing project" }} />
+    </Provider>,
+  );
+});
 
 test("Menu is not visible initially", () => {
-  expect(screen.queryByRole('menu')).toBeNull()
-})
+  expect(screen.queryByRole("menu")).toBeNull();
+});
 
 test("Clicking button makes menu content appear", () => {
-  const button = screen.getByRole('button')
-  fireEvent.click(button)
-  expect(screen.queryByRole('menu')).not.toBeNull()
-})
+  const button = screen.getByRole("button");
+  fireEvent.click(button);
+  expect(screen.queryByRole("menu")).not.toBeNull();
+});
 
-test('Clicking rename option opens the rename project modal', () => {
-  const button = screen.getByRole('button')
-  fireEvent.click(button)
-  const renameOption = screen.getByText('projectList.rename')
-  fireEvent.click(renameOption)
-  expect(store.getActions()).toEqual([{type: "editor/showRenameProjectModal", payload: {"name": "my amazing project"}}])
-})
+test("Clicking rename option opens the rename project modal", () => {
+  const button = screen.getByRole("button");
+  fireEvent.click(button);
+  const renameOption = screen.getByText("projectList.rename");
+  fireEvent.click(renameOption);
+  expect(store.getActions()).toEqual([
+    {
+      type: "editor/showRenameProjectModal",
+      payload: { name: "my amazing project" },
+    },
+  ]);
+});
 
-test('Clicking delete option opens the delete project modal', () => {
-  const button = screen.getByRole('button')
-  fireEvent.click(button)
-  const deleteOption = screen.getByText('projectList.delete')
-  fireEvent.click(deleteOption)
-  expect(store.getActions()).toEqual([{type: "editor/showDeleteProjectModal", payload: {"name": "my amazing project"}}])
-})
+test("Clicking delete option opens the delete project modal", () => {
+  const button = screen.getByRole("button");
+  fireEvent.click(button);
+  const deleteOption = screen.getByText("projectList.delete");
+  fireEvent.click(deleteOption);
+  expect(store.getActions()).toEqual([
+    {
+      type: "editor/showDeleteProjectModal",
+      payload: { name: "my amazing project" },
+    },
+  ]);
+});
diff --git a/src/components/Menus/SettingsMenu/SettingsMenu.js b/src/components/Menus/SettingsMenu/SettingsMenu.js
index 5e71e7de2..32b1f4a85 100644
--- a/src/components/Menus/SettingsMenu/SettingsMenu.js
+++ b/src/components/Menus/SettingsMenu/SettingsMenu.js
@@ -2,26 +2,25 @@ import React from "react";
 
 import FontSizeSelector from "../../Editor/FontSizeSelector/FontSizeSelector";
 import ThemeToggle from "../../ThemeToggle/ThemeToggle";
-import './SettingsMenu.scss'
-import { useTranslation } from 'react-i18next';
+import "./SettingsMenu.scss";
+import { useTranslation } from "react-i18next";
 
 const SettingsMenu = () => {
-
-  const {t} = useTranslation()
+  const { t } = useTranslation();
 
   return (
-    <div className='dropdown-container dropdown-container--bottom settings-menu'>
-      <h2>{t('header.settingsMenu.heading')}</h2>
-      <div className='settings-menu__theme'>
-        <h3>{t('header.settingsMenu.theme')}</h3>
+    <div className="dropdown-container dropdown-container--bottom settings-menu">
+      <h2>{t("header.settingsMenu.heading")}</h2>
+      <div className="settings-menu__theme">
+        <h3>{t("header.settingsMenu.theme")}</h3>
         <ThemeToggle />
       </div>
-      <div className='settings-menu__font-size'>
-        <h3>{t('header.settingsMenu.textSize')}</h3>
+      <div className="settings-menu__font-size">
+        <h3>{t("header.settingsMenu.textSize")}</h3>
         <FontSizeSelector />
       </div>
     </div>
-  )
-}
+  );
+};
 
-export default SettingsMenu
+export default SettingsMenu;
diff --git a/src/components/Menus/SettingsMenu/SettingsMenu.test.js b/src/components/Menus/SettingsMenu/SettingsMenu.test.js
index 9a620c331..7d9daa37c 100644
--- a/src/components/Menus/SettingsMenu/SettingsMenu.test.js
+++ b/src/components/Menus/SettingsMenu/SettingsMenu.test.js
@@ -1,15 +1,15 @@
 import React from "react";
-import { render } from "@testing-library/react"
+import { render } from "@testing-library/react";
 
-import SettingsMenu from './SettingsMenu'
+import SettingsMenu from "./SettingsMenu";
 
 test("Renders heading", () => {
-  const {queryByText} = render(<SettingsMenu />)
+  const { queryByText } = render(<SettingsMenu />);
   expect(queryByText("header.settingsMenu.heading")).not.toBeNull();
-})
+});
 
 test("Renders section headings", () => {
-  const {queryByText} = render(<SettingsMenu />)
+  const { queryByText } = render(<SettingsMenu />);
   expect(queryByText("header.settingsMenu.theme")).not.toBeNull();
   expect(queryByText("header.settingsMenu.textSize")).not.toBeNull();
-})
+});
diff --git a/src/components/Menus/SideMenu/FilePane/FilePane.js b/src/components/Menus/SideMenu/FilePane/FilePane.js
index 02513aa1c..a4b73729a 100644
--- a/src/components/Menus/SideMenu/FilePane/FilePane.js
+++ b/src/components/Menus/SideMenu/FilePane/FilePane.js
@@ -1,21 +1,22 @@
-import React from "react"
-import { useSelector } from "react-redux"
-import ProjectImages from "./ProjectImages/ProjectImages"
-import FilesList from "./FilesList"
+import React from "react";
+import { useSelector } from "react-redux";
+import ProjectImages from "./ProjectImages/ProjectImages";
+import FilesList from "./FilesList";
 
-import './FilePane.scss'
+import "./FilePane.scss";
 
 const FilePane = (props) => {
-
-  const project = useSelector((state) => state.editor.project)
-  const {openFileTab} = props
+  const project = useSelector((state) => state.editor.project);
+  const { openFileTab } = props;
 
   return (
-    <div className='file-pane'>
-      <FilesList openFileTab = {openFileTab}/>
-      {project.image_list && project.image_list.length>0? <ProjectImages /> : null}
+    <div className="file-pane">
+      <FilesList openFileTab={openFileTab} />
+      {project.image_list && project.image_list.length > 0 ? (
+        <ProjectImages />
+      ) : null}
     </div>
-  )
-}
+  );
+};
 
-export default FilePane
+export default FilePane;
diff --git a/src/components/Menus/SideMenu/FilePane/FilePane.test.js b/src/components/Menus/SideMenu/FilePane/FilePane.test.js
index 500cb1ba0..68c36f4e7 100644
--- a/src/components/Menus/SideMenu/FilePane/FilePane.test.js
+++ b/src/components/Menus/SideMenu/FilePane/FilePane.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { render} from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import { MemoryRouter } from "react-router-dom";
 
 import FilePane from "./FilePane";
@@ -10,65 +10,79 @@ describe("When no project images", () => {
   let queryByText;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
-          components: []
+          components: [],
         },
-        isEmbedded: false
+        isEmbedded: false,
       },
       auth: {
-        user: null 
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><MemoryRouter><div id="app"><FilePane /></div></MemoryRouter></Provider>))
-  })
-
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <div id="app">
+            <FilePane />
+          </div>
+        </MemoryRouter>
+      </Provider>,
+    ));
+  });
 
   test("Renders project files section", () => {
-    expect(queryByText("filePane.files")).not.toBeNull()
-  })
+    expect(queryByText("filePane.files")).not.toBeNull();
+  });
 
   test("No project images section", () => {
-    expect(queryByText("filePane.images")).toBeNull()
-  })
-})
+    expect(queryByText("filePane.images")).toBeNull();
+  });
+});
 
 describe("When project images", () => {
   let queryByText;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [],
           image_list: [
             {
-              filename: "hello_world.png"
-            }
-          ]
+              filename: "hello_world.png",
+            },
+          ],
         },
-        isEmbedded: false
+        isEmbedded: false,
       },
       auth: {
-        user: null 
-      }
-    }
+        user: null,
+      },
+    };
     const store = mockStore(initialState);
-    ({queryByText} = render(<Provider store={store}><MemoryRouter><div id="app"><FilePane /></div></MemoryRouter></Provider>))
-  })
-
+    ({ queryByText } = render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <div id="app">
+            <FilePane />
+          </div>
+        </MemoryRouter>
+      </Provider>,
+    ));
+  });
 
   test("Renders project files section", () => {
-    expect(queryByText("filePane.files")).not.toBeNull()
-  })
+    expect(queryByText("filePane.files")).not.toBeNull();
+  });
 
   test("Renders project images section", () => {
-    expect(queryByText("filePane.images")).not.toBeNull()
-  })
-})
+    expect(queryByText("filePane.images")).not.toBeNull();
+  });
+});
diff --git a/src/components/Menus/SideMenu/FilePane/FilesList.js b/src/components/Menus/SideMenu/FilePane/FilesList.js
index 0447be2ec..b9b438399 100644
--- a/src/components/Menus/SideMenu/FilePane/FilesList.js
+++ b/src/components/Menus/SideMenu/FilePane/FilesList.js
@@ -1,43 +1,50 @@
 import { useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 
-import { ChevronDown, FileIcon } from '../../../../Icons';
-import FileMenu from '../../FileMenu/FileMenu';
+import { ChevronDown, FileIcon } from "../../../../Icons";
+import FileMenu from "../../FileMenu/FileMenu";
 import NewComponentButton from "../../../Editor/NewComponentButton/NewComponentButton";
 
-import './FilesList.scss'
+import "./FilesList.scss";
 
 const FilesList = (props) => {
-  const project = useSelector((state) => state.editor.project)
-  const {openFileTab} = props
-  const { t } = useTranslation()
+  const project = useSelector((state) => state.editor.project);
+  const { openFileTab } = props;
+  const { t } = useTranslation();
 
   return (
-    <details className = "file-pane-section file-pane-section__files" open>
+    <details className="file-pane-section file-pane-section__files" open>
       <summary>
-        <h2>{t('filePane.files')}</h2>
+        <h2>{t("filePane.files")}</h2>
         <div className="accordion-icon">
           <ChevronDown />
         </div>
       </summary>
       <NewComponentButton />
-      <div className='files-list'>
-      { project.components.map((file, i) => (
-        <div className='files-list-item' key={i} onClick={() => openFileTab(`${file.name}.${file.extension}`)}>
-          <div className='files-list-icon'>
-            <FileIcon ext={file.extension} />
-          </div>
-          <span className='files-list-item__name'>{file.name}.{file.extension}</span>
-          {((file.name === 'main' && file.extension === 'py') || (file.name === 'index' && file.extension === 'html')) ? null :
-            <div className='files-list-item__menu'>
-              <FileMenu fileKey={i} name={file.name} ext={file.extension} />
+      <div className="files-list">
+        {project.components.map((file, i) => (
+          <div
+            className="files-list-item"
+            key={i}
+            onClick={() => openFileTab(`${file.name}.${file.extension}`)}
+          >
+            <div className="files-list-icon">
+              <FileIcon ext={file.extension} />
             </div>
-          }
-        </div>
-      ))}
+            <span className="files-list-item__name">
+              {file.name}.{file.extension}
+            </span>
+            {(file.name === "main" && file.extension === "py") ||
+            (file.name === "index" && file.extension === "html") ? null : (
+              <div className="files-list-item__menu">
+                <FileMenu fileKey={i} name={file.name} ext={file.extension} />
+              </div>
+            )}
+          </div>
+        ))}
       </div>
     </details>
-  )
-}
+  );
+};
 
-export default FilesList
+export default FilesList;
diff --git a/src/components/Menus/SideMenu/FilePane/FilesList.test.js b/src/components/Menus/SideMenu/FilePane/FilesList.test.js
index 64610d62b..cfc6631c8 100644
--- a/src/components/Menus/SideMenu/FilePane/FilesList.test.js
+++ b/src/components/Menus/SideMenu/FilePane/FilesList.test.js
@@ -1,115 +1,148 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import FilesList from "./FilesList";
 
-const openFileTab = jest.fn()
+const openFileTab = jest.fn();
 
-const createMockStore = function(components) {
-  const mockStore = configureStore([])
+const createMockStore = function (components) {
+  const mockStore = configureStore([]);
   return mockStore({
     editor: {
       project: {
-        components: components
+        components: components,
       },
-      isEmbedded: false
+      isEmbedded: false,
     },
     auth: {
-      user: null
-    }
+      user: null,
+    },
   });
-}
+};
 
 describe("When project has multiple files", () => {
   beforeEach(() => {
-    const store = createMockStore(
-      [
-        {
-          name: "a",
-          extension: "py"
-        },
-        {
-          name: "b",
-          extension: "html"
-        },
-        {
-          name: "c",
-          extension: "css"
-        },
-        {
-          name: "d",
-          extension: "csv"
-        }
-      ]
-    )
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-  })
+    const store = createMockStore([
+      {
+        name: "a",
+        extension: "py",
+      },
+      {
+        name: "b",
+        extension: "html",
+      },
+      {
+        name: "c",
+        extension: "css",
+      },
+      {
+        name: "d",
+        extension: "csv",
+      },
+    ]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+  });
 
   test("Renders all file names", () => {
-    expect(screen.queryByText("a.py")).not.toBeNull()
-    expect(screen.queryByText("b.html")).not.toBeNull()
-    expect(screen.queryByText("c.css")).not.toBeNull()
-    expect(screen.queryByText("d.csv")).not.toBeNull()
-  })
+    expect(screen.queryByText("a.py")).not.toBeNull();
+    expect(screen.queryByText("b.html")).not.toBeNull();
+    expect(screen.queryByText("c.css")).not.toBeNull();
+    expect(screen.queryByText("d.csv")).not.toBeNull();
+  });
 
   test("Renders a menu button for each file", () => {
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(4)
-  })
-
-  test('Clicking file name opens file tab',() => {
-    fireEvent.click(screen.queryByText('a.py').parentElement)
-    expect(openFileTab).toHaveBeenCalledWith('a.py')
-  })
-
-  test('it renders with the expected icons', () => {
-    expect(screen.getByTestId('pythonIcon')).toBeTruthy()
-    expect(screen.getByTestId('htmlIcon')).toBeTruthy()
-    expect(screen.getByTestId('cssIcon')).toBeTruthy()
-    expect(screen.getByTestId('csvIcon')).toBeTruthy()
-  })
-})
-
-describe('it renders the expected icon for individual files', () => {
-  test('it renders the expected icon for an individual python file', () => {
-    const store = createMockStore([ { name: "a", extension: "py" } ])
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(1)
-    expect(screen.getByTestId('pythonIcon')).toBeTruthy()
-  })
-
-  test('it renders the expected icon for an individual html file', () => {
-    const store = createMockStore([ { name: "a", extension: "html" } ])
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(1)
-    expect(screen.getByTestId('htmlIcon')).toBeTruthy()
-  })
-
-  test('it renders the expected icon for an individual css file', () => {
-    const store = createMockStore([ { name: "a", extension: "css" } ])
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(1)
-    expect(screen.getByTestId('cssIcon')).toBeTruthy()
-  })
-
-  test('it renders the expected icon for an individual csv file', () => {
-    const store = createMockStore([ { name: "a", extension: "csv" } ])
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(1)
-    expect(screen.getByTestId('csvIcon')).toBeTruthy()
-  })
-
-  test('it renders the expected icon for any other file type', () => {
-    const store = createMockStore([ { name: "a", extension: "docx" } ])
-    render(<Provider store={store}><div id="app"><FilesList openFileTab={openFileTab}/></div></Provider>)
-
-    expect(screen.getAllByTitle('filePane.fileMenu.label').length).toBe(1)
-    expect(screen.getByTestId('defaultFileIcon')).toBeTruthy()
-  })
-})
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(4);
+  });
+
+  test("Clicking file name opens file tab", () => {
+    fireEvent.click(screen.queryByText("a.py").parentElement);
+    expect(openFileTab).toHaveBeenCalledWith("a.py");
+  });
 
+  test("it renders with the expected icons", () => {
+    expect(screen.getByTestId("pythonIcon")).toBeTruthy();
+    expect(screen.getByTestId("htmlIcon")).toBeTruthy();
+    expect(screen.getByTestId("cssIcon")).toBeTruthy();
+    expect(screen.getByTestId("csvIcon")).toBeTruthy();
+  });
+});
+
+describe("it renders the expected icon for individual files", () => {
+  test("it renders the expected icon for an individual python file", () => {
+    const store = createMockStore([{ name: "a", extension: "py" }]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(1);
+    expect(screen.getByTestId("pythonIcon")).toBeTruthy();
+  });
+
+  test("it renders the expected icon for an individual html file", () => {
+    const store = createMockStore([{ name: "a", extension: "html" }]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(1);
+    expect(screen.getByTestId("htmlIcon")).toBeTruthy();
+  });
+
+  test("it renders the expected icon for an individual css file", () => {
+    const store = createMockStore([{ name: "a", extension: "css" }]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(1);
+    expect(screen.getByTestId("cssIcon")).toBeTruthy();
+  });
+
+  test("it renders the expected icon for an individual csv file", () => {
+    const store = createMockStore([{ name: "a", extension: "csv" }]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(1);
+    expect(screen.getByTestId("csvIcon")).toBeTruthy();
+  });
+
+  test("it renders the expected icon for any other file type", () => {
+    const store = createMockStore([{ name: "a", extension: "docx" }]);
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <FilesList openFileTab={openFileTab} />
+        </div>
+      </Provider>,
+    );
+
+    expect(screen.getAllByTitle("filePane.fileMenu.label").length).toBe(1);
+    expect(screen.getByTestId("defaultFileIcon")).toBeTruthy();
+  });
+});
diff --git a/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.js b/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.js
index e0eb87ef1..a0ba1493a 100644
--- a/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.js
+++ b/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.js
@@ -1,33 +1,37 @@
-import './ProjectImages.scss';
+import "./ProjectImages.scss";
 
-import { useSelector } from 'react-redux'
-import { ChevronDown } from '../../../../../Icons';
-import { useTranslation } from 'react-i18next'
+import { useSelector } from "react-redux";
+import { ChevronDown } from "../../../../../Icons";
+import { useTranslation } from "react-i18next";
 
 const ProjectImages = () => {
   const projectImages = useSelector((state) => state.editor.project.image_list);
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
   return (
-    <details className='file-pane-section file-pane-section__images' open>
+    <details className="file-pane-section file-pane-section__images" open>
       <summary>
-        <h2 className='menu-pop-out-subheading'>{t('filePane.images')}</h2>
-        <div className='accordion-icon'>
+        <h2 className="menu-pop-out-subheading">{t("filePane.images")}</h2>
+        <div className="accordion-icon">
           <ChevronDown />
         </div>
       </summary>
-      <div className='project-images'>
+      <div className="project-images">
         {projectImages.map((image, i) => (
-          <div key={i} className='project-images__block'>
-            <div className='project-images__image-wrapper'>
-              <img className='project-images__image' src={image.url} alt={image.filename}/>
+          <div key={i} className="project-images__block">
+            <div className="project-images__image-wrapper">
+              <img
+                className="project-images__image"
+                src={image.url}
+                alt={image.filename}
+              />
             </div>
             <p>{image.filename}</p>
           </div>
         ))}
       </div>
     </details>
-  )
-}
+  );
+};
 
-export default ProjectImages
+export default ProjectImages;
diff --git a/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.test.js b/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.test.js
index 16f2a71f2..2c401318d 100644
--- a/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.test.js
+++ b/src/components/Menus/SideMenu/FilePane/ProjectImages/ProjectImages.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import ProjectImages from "./ProjectImages";
 
@@ -10,46 +10,50 @@ describe("Project with images", () => {
   let queryByText;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
               name: "main",
-              extension: "py"
-            }
+              extension: "py",
+            },
           ],
           image_list: [
             {
               filename: "image1.jpg",
-              url: "image1_url"
+              url: "image1_url",
             },
             {
               filename: "image2.jpg",
-              url: "image2_url"
+              url: "image2_url",
             },
-          ]
-        }
+          ],
+        },
       },
-    }
+    };
     const store = mockStore(initialState);
-    ({ queryByAltText, queryByText } = render(<Provider store={store}><ProjectImages /></Provider>))
-  })
+    ({ queryByAltText, queryByText } = render(
+      <Provider store={store}>
+        <ProjectImages />
+      </Provider>,
+    ));
+  });
 
   test("Image names are rendered", () => {
-    expect(queryByText("image1.jpg")).not.toBeNull()
-    expect(queryByText("image2.jpg")).not.toBeNull()
-  })
+    expect(queryByText("image1.jpg")).not.toBeNull();
+    expect(queryByText("image2.jpg")).not.toBeNull();
+  });
 
   test("Images are rendered", () => {
-    expect(queryByAltText("image1.jpg")).not.toBeNull()
-    expect(queryByAltText("image2.jpg")).not.toBeNull()
-  })
+    expect(queryByAltText("image1.jpg")).not.toBeNull();
+    expect(queryByAltText("image2.jpg")).not.toBeNull();
+  });
 
   test("Images have the expected source", () => {
-    expect(queryByAltText("image1.jpg")).toHaveAttribute('src', 'image1_url')
-    expect(queryByAltText("image2.jpg")).toHaveAttribute('src', 'image2_url')
-  })
-})
+    expect(queryByAltText("image1.jpg")).toHaveAttribute("src", "image1_url");
+    expect(queryByAltText("image2.jpg")).toHaveAttribute("src", "image2_url");
+  });
+});
diff --git a/src/components/Menus/SideMenu/MenuSideBar.js b/src/components/Menus/SideMenu/MenuSideBar.js
index 5bf0a65f6..7254f27b0 100644
--- a/src/components/Menus/SideMenu/MenuSideBar.js
+++ b/src/components/Menus/SideMenu/MenuSideBar.js
@@ -1,36 +1,60 @@
-import React from "react"
-import { useTranslation } from "react-i18next"
-import { DoubleChevronRight } from "../../../Icons"
-import Button from "../../Button/Button"
-import MenuSideBarOption from "./MenuSideBarOption"
-
+import React from "react";
+import { useTranslation } from "react-i18next";
+import { DoubleChevronRight } from "../../../Icons";
+import Button from "../../Button/Button";
+import MenuSideBarOption from "./MenuSideBarOption";
 
 const MenuSideBar = (props) => {
-  const {menuOptions, option, toggleOption} = props
-  const { t } = useTranslation()
-  const topMenuOptions = menuOptions.filter((menuOption => menuOption.position === "top"))
-  const bottomMenuOptions = menuOptions.filter((menuOption => menuOption.position === "bottom"))
+  const { menuOptions, option, toggleOption } = props;
+  const { t } = useTranslation();
+  const topMenuOptions = menuOptions.filter(
+    (menuOption) => menuOption.position === "top",
+  );
+  const bottomMenuOptions = menuOptions.filter(
+    (menuOption) => menuOption.position === "bottom",
+  );
 
   const expandPopOut = () => {
-    toggleOption('file')
-    window.plausible('Expand file pane')
-  }
+    toggleOption("file");
+    window.plausible("Expand file pane");
+  };
 
   return (
     <div className="menu-sidebar">
       <div className={`menu-options-top`}>
         {topMenuOptions.map((menuOption, i) => (
-            <MenuSideBarOption key={i} Icon={menuOption.icon} title={menuOption.title} isActive={option === menuOption.name} toggleOption={toggleOption} name={menuOption.name}/>
-          ))}
+          <MenuSideBarOption
+            key={i}
+            Icon={menuOption.icon}
+            title={menuOption.title}
+            isActive={option === menuOption.name}
+            toggleOption={toggleOption}
+            name={menuOption.name}
+          />
+        ))}
       </div>
       <div className={`menu-options-bottom`}>
         {bottomMenuOptions.map((menuOption, i) => (
-            <MenuSideBarOption key={i} Icon={menuOption.icon} title={menuOption.title} isActive={option === menuOption.name} toggleOption={toggleOption} name={menuOption.name}/>
-          ))}
-        <Button className='btn--secondary btn--small' ButtonIcon={DoubleChevronRight} title={t('sideMenu.expand')} buttonOuter buttonOuterClassName = 'menu-expand-button' onClickHandler={expandPopOut}/>
+          <MenuSideBarOption
+            key={i}
+            Icon={menuOption.icon}
+            title={menuOption.title}
+            isActive={option === menuOption.name}
+            toggleOption={toggleOption}
+            name={menuOption.name}
+          />
+        ))}
+        <Button
+          className="btn--secondary btn--small"
+          ButtonIcon={DoubleChevronRight}
+          title={t("sideMenu.expand")}
+          buttonOuter
+          buttonOuterClassName="menu-expand-button"
+          onClickHandler={expandPopOut}
+        />
       </div>
     </div>
-  )
-}
+  );
+};
 
-export default MenuSideBar
+export default MenuSideBar;
diff --git a/src/components/Menus/SideMenu/MenuSideBar.test.js b/src/components/Menus/SideMenu/MenuSideBar.test.js
index fe9c01b90..106c13ec7 100644
--- a/src/components/Menus/SideMenu/MenuSideBar.test.js
+++ b/src/components/Menus/SideMenu/MenuSideBar.test.js
@@ -2,19 +2,19 @@ import React from "react";
 import { fireEvent, render, screen } from "@testing-library/react";
 import MenuSideBar from "./MenuSideBar";
 
-const toggleOption = jest.fn()
+const toggleOption = jest.fn();
 
 beforeEach(() => {
   render(
-  <MenuSideBar
-    menuOptions = {[{name: 'file', title: 'my_title', popOut: () => {}}]}
-    toggleOption = {toggleOption}
-  />)
-})
-
-test('Clicking expand button opens file pane', () => {
-  const expandButton = screen.getByTitle('sideMenu.expand')
-  fireEvent.click(expandButton)
-  expect(toggleOption).toHaveBeenCalledWith('file')
-})
+    <MenuSideBar
+      menuOptions={[{ name: "file", title: "my_title", popOut: () => {} }]}
+      toggleOption={toggleOption}
+    />,
+  );
+});
 
+test("Clicking expand button opens file pane", () => {
+  const expandButton = screen.getByTitle("sideMenu.expand");
+  fireEvent.click(expandButton);
+  expect(toggleOption).toHaveBeenCalledWith("file");
+});
diff --git a/src/components/Menus/SideMenu/MenuSideBarOption.js b/src/components/Menus/SideMenu/MenuSideBarOption.js
index 7596386f5..6bf5f59fc 100644
--- a/src/components/Menus/SideMenu/MenuSideBarOption.js
+++ b/src/components/Menus/SideMenu/MenuSideBarOption.js
@@ -1,24 +1,26 @@
-import React from "react"
-import Button from "../../Button/Button"
+import React from "react";
+import Button from "../../Button/Button";
 
 const MenuSideBarOption = (props) => {
-  const { Icon, isActive, name, title, toggleOption } = props
+  const { Icon, isActive, name, title, toggleOption } = props;
 
   const onClickHandler = () => {
-    toggleOption(name)
-    if (name === 'file') {
-      window.plausible('Side menu open project files')
+    toggleOption(name);
+    if (name === "file") {
+      window.plausible("Side menu open project files");
     }
-  }
+  };
 
   return (
     <Button
-      className = {`btn--tertiary menu-sidebar-option${isActive ? " menu-sidebar-option--active" : ""}`}
-      ButtonIcon = {Icon}
-      title = {title}
-      onClickHandler = {onClickHandler}
+      className={`btn--tertiary menu-sidebar-option${
+        isActive ? " menu-sidebar-option--active" : ""
+      }`}
+      ButtonIcon={Icon}
+      title={title}
+      onClickHandler={onClickHandler}
     />
-  )
-}
+  );
+};
 
-export default MenuSideBarOption
+export default MenuSideBarOption;
diff --git a/src/components/Menus/SideMenu/MenuSidebarOption.test.js b/src/components/Menus/SideMenu/MenuSidebarOption.test.js
index 759a5f9c1..de01e5af7 100644
--- a/src/components/Menus/SideMenu/MenuSidebarOption.test.js
+++ b/src/components/Menus/SideMenu/MenuSidebarOption.test.js
@@ -2,20 +2,20 @@ import React from "react";
 import { fireEvent, render, screen } from "@testing-library/react";
 import MenuSideBarOption from "./MenuSideBarOption";
 
-const toggleOption = jest.fn()
+const toggleOption = jest.fn();
 
 beforeEach(() => {
   render(
     <MenuSideBarOption
-      name = 'file'
-      title = 'my_title'
-      toggleOption = {toggleOption}
-    />
-  )
-})
+      name="file"
+      title="my_title"
+      toggleOption={toggleOption}
+    />,
+  );
+});
 
-test('Clicking expand button with correct title opens file pane', () => {
-  const optionButton = screen.getByTitle('my_title')
-  fireEvent.click(optionButton)
-  expect(toggleOption).toHaveBeenCalledWith('file')
-})
+test("Clicking expand button with correct title opens file pane", () => {
+  const optionButton = screen.getByTitle("my_title");
+  fireEvent.click(optionButton);
+  expect(toggleOption).toHaveBeenCalledWith("file");
+});
diff --git a/src/components/Menus/SideMenu/SideMenu.js b/src/components/Menus/SideMenu/SideMenu.js
index 270182214..00c797051 100644
--- a/src/components/Menus/SideMenu/SideMenu.js
+++ b/src/components/Menus/SideMenu/SideMenu.js
@@ -1,45 +1,62 @@
-import React, { useState } from "react"
-import { useTranslation } from "react-i18next"
-import { DoubleChevronLeft, FileIcon } from "../../../Icons"
-import Button from "../../Button/Button"
-import FilePane from "./FilePane/FilePane"
-import MenuSideBar from "./MenuSideBar"
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { DoubleChevronLeft, FileIcon } from "../../../Icons";
+import Button from "../../Button/Button";
+import FilePane from "./FilePane/FilePane";
+import MenuSideBar from "./MenuSideBar";
 
-import './SideMenu.scss'
+import "./SideMenu.scss";
 
 const SideMenu = (props) => {
-  const { openFileTab } = props
-  const { t } = useTranslation()
+  const { openFileTab } = props;
+  const { t } = useTranslation();
   const menuOptions = [
-    { name: "file", icon: FileIcon, title: t('sideMenu.file'), position: "top", popOut: () => FilePane({ openFileTab: openFileTab }) }
-  ]
-  const [option, setOption] = useState('file')
+    {
+      name: "file",
+      icon: FileIcon,
+      title: t("sideMenu.file"),
+      position: "top",
+      popOut: () => FilePane({ openFileTab: openFileTab }),
+    },
+  ];
+  const [option, setOption] = useState("file");
   const toggleOption = (newOption) => {
-    option !== newOption ? setOption(newOption) : setOption(null)
-  }
+    option !== newOption ? setOption(newOption) : setOption(null);
+  };
 
   const optionDict = menuOptions.find((menuOption) => {
-    return menuOption.name === option
-  })
-  const MenuPopOut = optionDict && optionDict.popOut ? optionDict.popOut : () => {}
+    return menuOption.name === option;
+  });
+  const MenuPopOut =
+    optionDict && optionDict.popOut ? optionDict.popOut : () => {};
 
   const collapsePopOut = () => {
-    toggleOption(option)
-    window.plausible('Collapse file pane')
-  }
+    toggleOption(option);
+    window.plausible("Collapse file pane");
+  };
 
   return (
-    <div className='menu'>
-      { option ? null :
-        <MenuSideBar menuOptions={menuOptions} option={option} toggleOption = {toggleOption}/>
-      }
+    <div className="menu">
+      {option ? null : (
+        <MenuSideBar
+          menuOptions={menuOptions}
+          option={option}
+          toggleOption={toggleOption}
+        />
+      )}
       <MenuPopOut />
-      {option ?
-        <Button className='btn--secondary btn--small' ButtonIcon={DoubleChevronLeft} buttonOuter buttonOuterClassName = 'menu-collapse-button' title={t('sideMenu.collapse')} onClickHandler={collapsePopOut} />
-      : null
-      }
+      {option ? (
+        <Button
+          className="btn--secondary btn--small"
+          ButtonIcon={DoubleChevronLeft}
+          buttonOuter
+          buttonOuterClassName="menu-collapse-button"
+          title={t("sideMenu.collapse")}
+          onClickHandler={collapsePopOut}
+        />
+      ) : null}
     </div>
-  )
-}
+  );
+};
 
-export default SideMenu
+export default SideMenu;
diff --git a/src/components/Menus/SideMenu/SideMenu.test.js b/src/components/Menus/SideMenu/SideMenu.test.js
index bbb643636..530c8c757 100644
--- a/src/components/Menus/SideMenu/SideMenu.test.js
+++ b/src/components/Menus/SideMenu/SideMenu.test.js
@@ -1,28 +1,34 @@
 import React from "react";
 import { fireEvent, render, screen } from "@testing-library/react";
 import SideMenu from "./SideMenu";
-import configureStore from 'redux-mock-store';
+import configureStore from "redux-mock-store";
 import { Provider } from "react-redux";
 
 beforeEach(() => {
-  const mockStore = configureStore([])
-    const initialState = {
-      editor: {
-        project: {
-          components: []
-        },
+  const mockStore = configureStore([]);
+  const initialState = {
+    editor: {
+      project: {
+        components: [],
       },
-    }
-    const store = mockStore(initialState);
-    render(<Provider store={store}><div id="app"><SideMenu/></div></Provider>)
-})
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <div id="app">
+        <SideMenu />
+      </div>
+    </Provider>,
+  );
+});
 
-test('File pane open by default', () => {
-  expect(screen.getByRole('heading')).toHaveTextContent('filePane.files')
-})
+test("File pane open by default", () => {
+  expect(screen.getByRole("heading")).toHaveTextContent("filePane.files");
+});
 
-test('Clicking collapse closes the file pane', () => {
-  const collapseButton = screen.getByTitle('sideMenu.collapse')
-  fireEvent.click(collapseButton)
-  expect(screen.queryByText('filePane.files')).not.toBeInTheDocument()
-})
+test("Clicking collapse closes the file pane", () => {
+  const collapseButton = screen.getByTitle("sideMenu.collapse");
+  fireEvent.click(collapseButton);
+  expect(screen.queryByText("filePane.files")).not.toBeInTheDocument();
+});
diff --git a/src/components/Modals/AccessDeniedNoAuthModal.js b/src/components/Modals/AccessDeniedNoAuthModal.js
index 9b0e0aa7f..70c1ffd3d 100644
--- a/src/components/Modals/AccessDeniedNoAuthModal.js
+++ b/src/components/Modals/AccessDeniedNoAuthModal.js
@@ -3,41 +3,60 @@ import { useDispatch, useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 
 import Button from "../Button/Button";
-import '../../Modal.scss';
+import "../../Modal.scss";
 import { closeAccessDeniedNoAuthModal } from "../Editor/EditorSlice";
 import LoginButton from "../Login/LoginButton";
 import GeneralModal from "./GeneralModal";
 import { login } from "../../utils/login";
 
 const AccessDeniedNoAuthModal = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  
-  const isModalOpen = useSelector((state) => state.editor.accessDeniedNoAuthModalShowing)
-  const accessDeniedData = useSelector((state) => state.editor.modals.accessDenied)
+
+  const isModalOpen = useSelector(
+    (state) => state.editor.accessDeniedNoAuthModalShowing,
+  );
+  const accessDeniedData = useSelector(
+    (state) => state.editor.modals.accessDenied,
+  );
   const closeModal = () => dispatch(closeAccessDeniedNoAuthModal());
 
   const defaultCallback = () => {
-    login({accessDeniedData})
-  }
+    login({ accessDeniedData });
+  };
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('project.accessDeniedNoAuthModal.heading')}
+      heading={t("project.accessDeniedNoAuthModal.heading")}
       text={[
-        {type: 'paragraph', content: t('project.accessDeniedNoAuthModal.text')}
+        {
+          type: "paragraph",
+          content: t("project.accessDeniedNoAuthModal.text"),
+        },
       ]}
       buttons={[
-        <LoginButton buttonText={t('project.accessDeniedNoAuthModal.loginButtonText')} className = 'btn--primary'/>,
-        <a className='btn btn--secondary' href='https://projects.raspberrypi.org'>{t('project.accessDeniedNoAuthModal.projectsSiteLinkText')}</a>,
-        <Button buttonText = {t('project.accessDeniedNoAuthModal.newProject')} className='btn--tertiary' onClickHandler={closeModal}/>
+        <LoginButton
+          buttonText={t("project.accessDeniedNoAuthModal.loginButtonText")}
+          className="btn--primary"
+        />,
+        <a
+          className="btn btn--secondary"
+          href="https://projects.raspberrypi.org"
+        >
+          {t("project.accessDeniedNoAuthModal.projectsSiteLinkText")}
+        </a>,
+        <Button
+          buttonText={t("project.accessDeniedNoAuthModal.newProject")}
+          className="btn--tertiary"
+          onClickHandler={closeModal}
+        />,
       ]}
       defaultCallback={defaultCallback}
     />
   );
-}
+};
 
 export default AccessDeniedNoAuthModal;
diff --git a/src/components/Modals/AccessDeniedNoAuthModal.test.js b/src/components/Modals/AccessDeniedNoAuthModal.test.js
index c829780b8..fa09dfb45 100644
--- a/src/components/Modals/AccessDeniedNoAuthModal.test.js
+++ b/src/components/Modals/AccessDeniedNoAuthModal.test.js
@@ -1,18 +1,18 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import AccessDeniedNoAuthModal from "./AccessDeniedNoAuthModal";
 
-jest.mock('react-router-dom', () => ({
-  useLocation: jest.fn()
-}))
+jest.mock("react-router-dom", () => ({
+  useLocation: jest.fn(),
+}));
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
-describe('When accessDeniedNoAuthModalShowing is true', () => {
-  let store
+describe("When accessDeniedNoAuthModalShowing is true", () => {
+  let store;
 
   beforeEach(() => {
     const initialState = {
@@ -20,23 +20,35 @@ describe('When accessDeniedNoAuthModalShowing is true', () => {
         accessDeniedNoAuthModalShowing: true,
         modals: {
           accessDenied: {
-            identifer: 'my-amazing-project',
-            projectType: 'python'
-          }
-        }
-      }
-    }
+            identifer: "my-amazing-project",
+            projectType: "python",
+          },
+        },
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><AccessDeniedNoAuthModal /></div></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <AccessDeniedNoAuthModal />
+        </div>
+      </Provider>,
+    );
+  });
 
-  test('Modal rendered', () => {
-    expect(screen.queryByText('project.accessDeniedNoAuthModal.heading')).toBeInTheDocument()
-  })
+  test("Modal rendered", () => {
+    expect(
+      screen.queryByText("project.accessDeniedNoAuthModal.heading"),
+    ).toBeInTheDocument();
+  });
 
-  test('Clicking new project dispatches close modal action', () => {
-    const newProjectLink = screen.queryByText('project.accessDeniedNoAuthModal.newProject')
-    fireEvent.click(newProjectLink)
-    expect(store.getActions()).toEqual([{type: 'editor/closeAccessDeniedNoAuthModal'}])
-  })
-})
+  test("Clicking new project dispatches close modal action", () => {
+    const newProjectLink = screen.queryByText(
+      "project.accessDeniedNoAuthModal.newProject",
+    );
+    fireEvent.click(newProjectLink);
+    expect(store.getActions()).toEqual([
+      { type: "editor/closeAccessDeniedNoAuthModal" },
+    ]);
+  });
+});
diff --git a/src/components/Modals/AccessDeniedWithAuthModal.js b/src/components/Modals/AccessDeniedWithAuthModal.js
index 2a04ae246..e77b808c5 100644
--- a/src/components/Modals/AccessDeniedWithAuthModal.js
+++ b/src/components/Modals/AccessDeniedWithAuthModal.js
@@ -3,39 +3,62 @@ import { useDispatch, useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 
 import Button from "../Button/Button";
-import '../../Modal.scss';
-import { closeAccessDeniedWithAuthModal, syncProject } from "../Editor/EditorSlice";
+import "../../Modal.scss";
+import {
+  closeAccessDeniedWithAuthModal,
+  syncProject,
+} from "../Editor/EditorSlice";
 import { defaultPythonProject } from "../../utils/defaultProjects";
 import GeneralModal from "./GeneralModal";
 
 const AccessDeniedWithAuthModal = () => {
-  const dispatch = useDispatch()
-  const { t } = useTranslation()
-  const user = useSelector((state) => state.auth.user)
-  
-  const isModalOpen = useSelector((state) => state.editor.accessDeniedWithAuthModalShowing)
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
+  const user = useSelector((state) => state.auth.user);
+
+  const isModalOpen = useSelector(
+    (state) => state.editor.accessDeniedWithAuthModalShowing,
+  );
   const closeModal = () => dispatch(closeAccessDeniedWithAuthModal());
 
   const createNewProject = async () => {
-    dispatch(syncProject('save')({ project: defaultPythonProject, accessToken: user.access_token, autosave: false }))
-  }
+    dispatch(
+      syncProject("save")({
+        project: defaultPythonProject,
+        accessToken: user.access_token,
+        autosave: false,
+      }),
+    );
+  };
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('project.accessDeniedWithAuthModal.heading')}
+      heading={t("project.accessDeniedWithAuthModal.heading")}
       text={[
-        {type: 'paragraph', content: t('project.accessDeniedWithAuthModal.text')}
+        {
+          type: "paragraph",
+          content: t("project.accessDeniedWithAuthModal.text"),
+        },
       ]}
       buttons={[
-        <Button className='btn--primary' buttonText={t('project.accessDeniedWithAuthModal.newProject')} onClickHandler={createNewProject} />,
-        <a className='btn btn--secondary' href='https://projects.raspberrypi.org'>{t('project.accessDeniedWithAuthModal.projectsSiteLinkText')}</a>
+        <Button
+          className="btn--primary"
+          buttonText={t("project.accessDeniedWithAuthModal.newProject")}
+          onClickHandler={createNewProject}
+        />,
+        <a
+          className="btn btn--secondary"
+          href="https://projects.raspberrypi.org"
+        >
+          {t("project.accessDeniedWithAuthModal.projectsSiteLinkText")}
+        </a>,
       ]}
       defaultCallback={createNewProject}
     />
   );
-}
+};
 
 export default AccessDeniedWithAuthModal;
diff --git a/src/components/Modals/AccessDeniedWithAuthModal.test.js b/src/components/Modals/AccessDeniedWithAuthModal.test.js
index 5c0437a7a..227f64e47 100644
--- a/src/components/Modals/AccessDeniedWithAuthModal.test.js
+++ b/src/components/Modals/AccessDeniedWithAuthModal.test.js
@@ -1,28 +1,28 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import AccessDeniedWithAuthModal from "./AccessDeniedWithAuthModal";
 import { syncProject } from "../Editor/EditorSlice";
 import { defaultPythonProject } from "../../utils/defaultProjects";
 
-jest.mock('../Editor/EditorSlice', () => ({
-  ...jest.requireActual('../Editor/EditorSlice'),
-  syncProject: jest.fn((_) => jest.fn())
-}))
+jest.mock("../Editor/EditorSlice", () => ({
+  ...jest.requireActual("../Editor/EditorSlice"),
+  syncProject: jest.fn((_) => jest.fn()),
+}));
 
 const user = {
   access_token: "39a09671-be55-4847-baf5-8919a0c24a25",
   profile: {
-    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-  }
-}
+    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+  },
+};
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
-describe('When accessDeniedWithAuthModalShowing is true', () => {
-  let store
+describe("When accessDeniedWithAuthModalShowing is true", () => {
+  let store;
 
   beforeEach(() => {
     const initialState = {
@@ -30,28 +30,40 @@ describe('When accessDeniedWithAuthModalShowing is true', () => {
         accessDeniedWithAuthModalShowing: true,
       },
       auth: {
-        user: user
-      }
-    }
+        user: user,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><AccessDeniedWithAuthModal /></div></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <AccessDeniedWithAuthModal />
+        </div>
+      </Provider>,
+    );
+  });
 
-  test('Modal rendered', () => {
-    expect(screen.queryByText('project.accessDeniedWithAuthModal.heading')).toBeInTheDocument()
-  })
+  test("Modal rendered", () => {
+    expect(
+      screen.queryByText("project.accessDeniedWithAuthModal.heading"),
+    ).toBeInTheDocument();
+  });
 
-  test('Clicking new project creates a new project', async () => {
-    const newProjectLink = screen.queryByText('project.accessDeniedWithAuthModal.newProject')
-    const saveAction = {type: 'SAVE_PROJECT' }
-    const saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    fireEvent.click(newProjectLink)
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({
-      project: defaultPythonProject,
-      accessToken: user.access_token,
-      autosave: false
-    }))
-    expect(store.getActions()[0]).toEqual(saveAction)
-  })
-})
+  test("Clicking new project creates a new project", async () => {
+    const newProjectLink = screen.queryByText(
+      "project.accessDeniedWithAuthModal.newProject",
+    );
+    const saveAction = { type: "SAVE_PROJECT" };
+    const saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    fireEvent.click(newProjectLink);
+    await waitFor(() =>
+      expect(saveProject).toHaveBeenCalledWith({
+        project: defaultPythonProject,
+        accessToken: user.access_token,
+        autosave: false,
+      }),
+    );
+    expect(store.getActions()[0]).toEqual(saveAction);
+  });
+});
diff --git a/src/components/Modals/BetaModal.js b/src/components/Modals/BetaModal.js
index 2b0d2ecd9..1b8035f18 100644
--- a/src/components/Modals/BetaModal.js
+++ b/src/components/Modals/BetaModal.js
@@ -5,32 +5,36 @@ import { useTranslation } from "react-i18next";
 import Button from "../Button/Button";
 import { closeBetaModal } from "../Editor/EditorSlice";
 import GeneralModal from "./GeneralModal";
-import '../../Modal.scss';
+import "../../Modal.scss";
 
 const BetaModal = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  
-  const isModalOpen = useSelector((state) => state.editor.betaModalShowing)
+
+  const isModalOpen = useSelector((state) => state.editor.betaModalShowing);
   const closeModal = () => dispatch(closeBetaModal());
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
-      heading={t('betaBanner.modal.heading')}
+      heading={t("betaBanner.modal.heading")}
       text={[
-        {type: 'subheading', content: t('betaBanner.modal.meaningHeading')},
-        {type: 'paragraph', content: t('betaBanner.modal.meaningText')},
-        {type: 'subheading', content: t('betaBanner.modal.whatNextHeading')},
-        {type: 'paragraph', content: t('betaBanner.modal.whatNextText')}
+        { type: "subheading", content: t("betaBanner.modal.meaningHeading") },
+        { type: "paragraph", content: t("betaBanner.modal.meaningText") },
+        { type: "subheading", content: t("betaBanner.modal.whatNextHeading") },
+        { type: "paragraph", content: t("betaBanner.modal.whatNextText") },
       ]}
       buttons={[
-        <Button className='btn--primary' buttonText={t('betaBanner.modal.close')} onClickHandler={closeModal} />
+        <Button
+          className="btn--primary"
+          buttonText={t("betaBanner.modal.close")}
+          onClickHandler={closeModal}
+        />,
       ]}
       defaultCallback={closeModal}
     />
   );
-}
+};
 
 export default BetaModal;
diff --git a/src/components/Modals/BetaModal.test.js b/src/components/Modals/BetaModal.test.js
index 3148a8486..e69ecbc17 100644
--- a/src/components/Modals/BetaModal.test.js
+++ b/src/components/Modals/BetaModal.test.js
@@ -1,36 +1,48 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import BetaModal from "./BetaModal";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
-test('Modal rendered when betaModalShowing is true', () => {
+test("Modal rendered when betaModalShowing is true", () => {
   const initialState = {
     editor: {
-      betaModalShowing: true
-    }
-  }
+      betaModalShowing: true,
+    },
+  };
   const store = mockStore(initialState);
 
-  render(<Provider store={store}><div id='app'><BetaModal /></div></Provider>)
+  render(
+    <Provider store={store}>
+      <div id="app">
+        <BetaModal />
+      </div>
+    </Provider>,
+  );
 
-  expect(screen.queryByText('betaBanner.modal.heading')).toBeInTheDocument()
-})
+  expect(screen.queryByText("betaBanner.modal.heading")).toBeInTheDocument();
+});
 
-test('Clicking close dispatches close modal action', () => {
+test("Clicking close dispatches close modal action", () => {
   const initialState = {
     editor: {
-      betaModalShowing: true
-    }
-  }
+      betaModalShowing: true,
+    },
+  };
   const store = mockStore(initialState);
 
-  render(<Provider store={store}><div id='app'><BetaModal /></div></Provider>)
+  render(
+    <Provider store={store}>
+      <div id="app">
+        <BetaModal />
+      </div>
+    </Provider>,
+  );
 
-  const closeButton = screen.queryByText('betaBanner.modal.close')
-  fireEvent.click(closeButton)
-  expect(store.getActions()).toEqual([{type: 'editor/closeBetaModal'}])
-})
+  const closeButton = screen.queryByText("betaBanner.modal.close");
+  fireEvent.click(closeButton);
+  expect(store.getActions()).toEqual([{ type: "editor/closeBetaModal" }]);
+});
diff --git a/src/components/Modals/DeleteProjectModal.js b/src/components/Modals/DeleteProjectModal.js
index f88c2a48f..70f2f0593 100644
--- a/src/components/Modals/DeleteProjectModal.js
+++ b/src/components/Modals/DeleteProjectModal.js
@@ -1,5 +1,5 @@
 import React from "react";
-import { gql, useMutation } from '@apollo/client';
+import { gql, useMutation } from "@apollo/client";
 import { useTranslation } from "react-i18next";
 import { useDispatch, useSelector } from "react-redux";
 import { closeDeleteProjectModal } from "../Editor/EditorSlice";
@@ -9,44 +9,62 @@ import GeneralModal from "./GeneralModal";
 // Define mutation
 export const DELETE_PROJECT_MUTATION = gql`
   mutation DeleteProject($id: String!) {
-    deleteProject(input: {id: $id}) {
+    deleteProject(input: { id: $id }) {
       id
     }
   }
 `;
 
 export const DeleteProjectModal = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  const isModalOpen = useSelector((state) => state.editor.deleteProjectModalShowing)
-  const project = useSelector((state) => state.editor.modals.deleteProject)
+  const isModalOpen = useSelector(
+    (state) => state.editor.deleteProjectModalShowing,
+  );
+  const project = useSelector((state) => state.editor.modals.deleteProject);
 
   const closeModal = () => dispatch(closeDeleteProjectModal());
 
   // This can capture data, error, loading as per normal queries, but we're not
   // using them yet.
-  const [deleteProjectMutation] = useMutation(DELETE_PROJECT_MUTATION, {refetchQueries: ["ProjectIndexQuery"]})
+  const [deleteProjectMutation] = useMutation(DELETE_PROJECT_MUTATION, {
+    refetchQueries: ["ProjectIndexQuery"],
+  });
 
   const onClickDelete = async () => {
-    deleteProjectMutation({variables: {id: project.id}, onCompleted: closeModal})
-  }
+    deleteProjectMutation({
+      variables: { id: project.id },
+      onCompleted: closeModal,
+    });
+  };
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('projectList.deleteProjectModal.heading')}
+      heading={t("projectList.deleteProjectModal.heading")}
       text={[
-        {type: 'paragraph', content: t('projectList.deleteProjectModal.text')}
+        {
+          type: "paragraph",
+          content: t("projectList.deleteProjectModal.text"),
+        },
       ]}
       buttons={[
-        <Button className='btn--danger' buttonText={t('projectList.deleteProjectModal.delete')} onClickHandler={onClickDelete} />,
-        <Button className='btn--secondary' buttonText={t('projectList.deleteProjectModal.cancel')} onClickHandler={closeModal} />
+        <Button
+          className="btn--danger"
+          buttonText={t("projectList.deleteProjectModal.delete")}
+          onClickHandler={onClickDelete}
+        />,
+        <Button
+          className="btn--secondary"
+          buttonText={t("projectList.deleteProjectModal.cancel")}
+          onClickHandler={closeModal}
+        />,
       ]}
       defaultCallback={onClickDelete}
     />
   );
-}
+};
 
-export default DeleteProjectModal
+export default DeleteProjectModal;
diff --git a/src/components/Modals/DeleteProjectModal.test.js b/src/components/Modals/DeleteProjectModal.test.js
index 9ddf7d971..62889cc5a 100644
--- a/src/components/Modals/DeleteProjectModal.test.js
+++ b/src/components/Modals/DeleteProjectModal.test.js
@@ -1,77 +1,94 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import { MockedProvider } from "@apollo/client/testing";
 
-import { DeleteProjectModal, DELETE_PROJECT_MUTATION } from "./DeleteProjectModal";
+import {
+  DeleteProjectModal,
+  DELETE_PROJECT_MUTATION,
+} from "./DeleteProjectModal";
 
 describe("Testing the delete project modal", () => {
   let store;
   let mocks;
-  let project = { id: 'abc', name: 'my first project' }
+  let project = { id: "abc", name: "my first project" };
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         modals: {
-          deleteProject: project
+          deleteProject: project,
         },
-        deleteProjectModalShowing: true
-      }
-    }
+        deleteProjectModalShowing: true,
+      },
+    };
 
     mocks = [
       {
         request: {
           query: DELETE_PROJECT_MUTATION,
-          variables: { id: project.id }
+          variables: { id: project.id },
         },
-        result:  jest.fn(() => ({
+        result: jest.fn(() => ({
           data: {
             deleteProject: {
-              id: project.id
-            }
-          }
-        }))
-      }
-    ]
+              id: project.id,
+            },
+          },
+        })),
+      },
+    ];
 
     store = mockStore(initialState);
 
     render(
       <MockedProvider mocks={mocks}>
         <Provider store={store}>
-          <div id='app'>
+          <div id="app">
             <DeleteProjectModal />
           </div>
         </Provider>
-      </MockedProvider>
-    )
-  })
+      </MockedProvider>,
+    );
+  });
 
-  test('Modal renders', () => {
-    expect(screen.queryByText('projectList.deleteProjectModal.heading')).toBeInTheDocument()
-  })
+  test("Modal renders", () => {
+    expect(
+      screen.queryByText("projectList.deleteProjectModal.heading"),
+    ).toBeInTheDocument();
+  });
 
-  test('Clicking cancel button closes modal and does not save', () => {
-    const cancelButton = screen.queryByText('projectList.deleteProjectModal.cancel')
-    fireEvent.click(cancelButton)
-    expect(store.getActions()).toEqual([{type: 'editor/closeDeleteProjectModal'}])
-  })
+  test("Clicking cancel button closes modal and does not save", () => {
+    const cancelButton = screen.queryByText(
+      "projectList.deleteProjectModal.cancel",
+    );
+    fireEvent.click(cancelButton);
+    expect(store.getActions()).toEqual([
+      { type: "editor/closeDeleteProjectModal" },
+    ]);
+  });
 
   test("Clicking delete button (eventually) closes the modal", async () => {
-    const deleteButton = screen.getByText('projectList.deleteProjectModal.delete')
-    fireEvent.click(deleteButton)
-    await waitFor(() => expect(store.getActions()).toEqual([{type: 'editor/closeDeleteProjectModal'}]))
-  })
+    const deleteButton = screen.getByText(
+      "projectList.deleteProjectModal.delete",
+    );
+    fireEvent.click(deleteButton);
+    await waitFor(() =>
+      expect(store.getActions()).toEqual([
+        { type: "editor/closeDeleteProjectModal" },
+      ]),
+    );
+  });
 
   test("Clicking delete button calls the mutation", async () => {
-    const deleteButton = screen.getByText('projectList.deleteProjectModal.delete')
-    const deleteProjectMutationMock = mocks[0].result
-    fireEvent.click(deleteButton)
-    await waitFor(() => expect(deleteProjectMutationMock).toHaveBeenCalled())
-  })
-})
+    const deleteButton = screen.getByText(
+      "projectList.deleteProjectModal.delete",
+    );
+    const deleteProjectMutationMock = mocks[0].result;
+    fireEvent.click(deleteButton);
+    await waitFor(() => expect(deleteProjectMutationMock).toHaveBeenCalled());
+  });
+});
diff --git a/src/components/Modals/ErrorModal.test.js b/src/components/Modals/ErrorModal.test.js
index 7513fa5c8..2a9df7776 100644
--- a/src/components/Modals/ErrorModal.test.js
+++ b/src/components/Modals/ErrorModal.test.js
@@ -20,12 +20,12 @@ test("Modal rendered when errorModalShowing is true", () => {
       <div id="app">
         <ErrorModal />
       </div>
-    </Provider>
+    </Provider>,
   );
 
   expect(screen.queryByText("modal.error.heading")).toBeInTheDocument();
   expect(
-    screen.queryByText("modal.error.null.message")
+    screen.queryByText("modal.error.null.message"),
   ).not.toBeInTheDocument();
 });
 
@@ -42,7 +42,7 @@ test("Modal not rendered when errorModalShowing is false", () => {
       <div id="app">
         <ErrorModal />
       </div>
-    </Provider>
+    </Provider>,
   );
 
   expect(screen.queryByText("modal.error.heading")).not.toBeInTheDocument();
@@ -61,7 +61,7 @@ test("Clicking close dispatches close modal action", () => {
       <div id="app">
         <ErrorModal />
       </div>
-    </Provider>
+    </Provider>,
   );
 
   const closeButton = screen.queryByText("modal.close");
@@ -82,11 +82,11 @@ test("Error message shown", () => {
       <div id="app">
         <ErrorModal errorType="someTestError" />
       </div>
-    </Provider>
+    </Provider>,
   );
 
   expect(
-    screen.queryByText("modal.error.someTestError.message")
+    screen.queryByText("modal.error.someTestError.message"),
   ).toBeInTheDocument();
 });
 
@@ -104,7 +104,7 @@ test("Additional closeModal function fired", () => {
       <div id="app">
         <ErrorModal additionalOnClose={testOnClose} />
       </div>
-    </Provider>
+    </Provider>,
   );
 
   const closeButton = screen.queryByText("modal.close");
diff --git a/src/components/Modals/GeneralModal.js b/src/components/Modals/GeneralModal.js
index e7795fc95..e376a6efa 100644
--- a/src/components/Modals/GeneralModal.js
+++ b/src/components/Modals/GeneralModal.js
@@ -1,57 +1,76 @@
 import React from "react";
-import Modal from 'react-modal';
+import Modal from "react-modal";
 
 import Button from "../Button/Button";
-import '../../Modal.scss';
+import "../../Modal.scss";
 import { CloseIcon } from "../../Icons";
 import { useTranslation } from "react-i18next";
 
-const GeneralModal = ({buttons=[], children, defaultCallback, heading, isOpen, text=[], withCloseButton = false, closeModal }) => {
-  const { t } = useTranslation()
-  const buttonComponents = buttons.map((ButtonFromProps) => (
-    () => ButtonFromProps
-  ))
+const GeneralModal = ({
+  buttons = [],
+  children,
+  defaultCallback,
+  heading,
+  isOpen,
+  text = [],
+  withCloseButton = false,
+  closeModal,
+}) => {
+  const { t } = useTranslation();
+  const buttonComponents = buttons.map(
+    (ButtonFromProps) => () => ButtonFromProps,
+  );
   const onKeyDown = (e) => {
-    if (e.key === 'Enter' && defaultCallback) {
-      defaultCallback()
+    if (e.key === "Enter" && defaultCallback) {
+      defaultCallback();
     }
-  }
+  };
 
   return (
     <div onKeyDown={onKeyDown}>
       <Modal
         isOpen={isOpen}
         onRequestClose={closeModal}
-        className='modal-content'
-        overlayClassName='modal-overlay'
+        className="modal-content"
+        overlayClassName="modal-overlay"
         contentLabel={heading}
-        parentSelector={() => document.querySelector('#app')}
-        appElement={document.getElementById('app') || undefined}
+        parentSelector={() => document.querySelector("#app")}
+        appElement={document.getElementById("app") || undefined}
       >
-        <div className='modal-content__header'>
-          <h2 className='modal-content__heading'>{heading}</h2>
-          { withCloseButton ? 
-            <Button className='btn--tertiary' onClickHandler={closeModal} ButtonIcon = {CloseIcon} label={t('modals.close')} title={t('modals.close')}/>
-            : null
-          }
+        <div className="modal-content__header">
+          <h2 className="modal-content__heading">{heading}</h2>
+          {withCloseButton ? (
+            <Button
+              className="btn--tertiary"
+              onClickHandler={closeModal}
+              ButtonIcon={CloseIcon}
+              label={t("modals.close")}
+              title={t("modals.close")}
+            />
+          ) : null}
         </div>
-        <div className='modal-content__body'>
-          {text.map((textItem, i) => (
-            textItem.type === 'subheading' ?
-              <h3 className='modal-content__subheading' key={i}>{textItem.content}</h3>
-            :
-              <p className='modal-content__text' key={i}>{textItem.content}</p>
-          ))}
+        <div className="modal-content__body">
+          {text.map((textItem, i) =>
+            textItem.type === "subheading" ? (
+              <h3 className="modal-content__subheading" key={i}>
+                {textItem.content}
+              </h3>
+            ) : (
+              <p className="modal-content__text" key={i}>
+                {textItem.content}
+              </p>
+            ),
+          )}
           {children}
         </div>
-        <div className='modal-content__buttons' >
+        <div className="modal-content__buttons">
           {buttonComponents.map((ButtonComponent, i) => (
-            <ButtonComponent key={i}/>
+            <ButtonComponent key={i} />
           ))}
         </div>
       </Modal>
     </div>
   );
-}
+};
 
 export default GeneralModal;
diff --git a/src/components/Modals/GeneralModal.test.js b/src/components/Modals/GeneralModal.test.js
index 36e94fd0a..20c65e8df 100644
--- a/src/components/Modals/GeneralModal.test.js
+++ b/src/components/Modals/GeneralModal.test.js
@@ -2,42 +2,38 @@ import { fireEvent, render, screen } from "@testing-library/react";
 import React from "react";
 import GeneralModal from "./GeneralModal";
 
-const defaultCallback = jest.fn()
-const closeModal = jest.fn()
+const defaultCallback = jest.fn();
+const closeModal = jest.fn();
 
 beforeEach(() => {
   render(
-    <div id='app'>
+    <div id="app">
       <GeneralModal
         isOpen={true}
         closeModal={closeModal}
         withCloseButton
         defaultCallback={defaultCallback}
-        heading='My modal heading'
-        text={[
-          { content: 'Paragraph1', type: 'paragraph' }
-        ]}
-        buttons={[
-          <button onClick={jest.fn()}>My amazing button</button>
-        ]}
+        heading="My modal heading"
+        text={[{ content: "Paragraph1", type: "paragraph" }]}
+        buttons={[<button onClick={jest.fn()}>My amazing button</button>]}
       />
-    </div>
-  )
-})
+    </div>,
+  );
+});
 
-test('Renders', () => {
-  expect(screen.queryByText('My modal heading')).toBeInTheDocument()
-  expect(screen.queryByText('Paragraph1')).toBeInTheDocument()
-  expect(screen.queryByText('My amazing button')).toBeInTheDocument()
-})
+test("Renders", () => {
+  expect(screen.queryByText("My modal heading")).toBeInTheDocument();
+  expect(screen.queryByText("Paragraph1")).toBeInTheDocument();
+  expect(screen.queryByText("My amazing button")).toBeInTheDocument();
+});
 
-test('Clicking close button closes modal', () => {
-  const closeButton = screen.queryByTitle('modals.close')
-  fireEvent.click(closeButton)
-  expect(closeModal).toHaveBeenCalled()
-})
+test("Clicking close button closes modal", () => {
+  const closeButton = screen.queryByTitle("modals.close");
+  fireEvent.click(closeButton);
+  expect(closeModal).toHaveBeenCalled();
+});
 
-test('Pressing Enter calls the default callback', () => {
-  const modal = screen.getByRole('dialog')
-  fireEvent.keyDown(modal, {key: 'Enter'})
-})
+test("Pressing Enter calls the default callback", () => {
+  const modal = screen.getByRole("dialog");
+  fireEvent.keyDown(modal, { key: "Enter" });
+});
diff --git a/src/components/Modals/InputModal.js b/src/components/Modals/InputModal.js
index bd838c552..3a11aa81f 100644
--- a/src/components/Modals/InputModal.js
+++ b/src/components/Modals/InputModal.js
@@ -2,27 +2,37 @@ import React, { useCallback } from "react";
 import GeneralModal from "./GeneralModal";
 import NameErrorMessage from "../Editor/ErrorMessage/NameErrorMessage";
 
-const InputModal = ({inputLabel, inputDefaultValue, inputHelpText, ...otherProps}) => {
-
+const InputModal = ({
+  inputLabel,
+  inputDefaultValue,
+  inputHelpText,
+  ...otherProps
+}) => {
   const inputBox = useCallback((node) => {
     if (node) {
-      node.focus()
+      node.focus();
     }
-  }, [])
+  }, []);
 
   return (
     <GeneralModal {...otherProps}>
       <div>
-        <label htmlFor='name'>{inputLabel}</label>
-        <p className='modal-content__help-text'>{inputHelpText}</p>
+        <label htmlFor="name">{inputLabel}</label>
+        <p className="modal-content__help-text">{inputHelpText}</p>
       </div>
-      
-      <div className='modal-content__input'>
+
+      <div className="modal-content__input">
         <NameErrorMessage />
-        <input ref={inputBox} type='text' name='name' id='name' defaultValue={inputDefaultValue}></input>
+        <input
+          ref={inputBox}
+          type="text"
+          name="name"
+          id="name"
+          defaultValue={inputDefaultValue}
+        ></input>
       </div>
     </GeneralModal>
-  )
-}
+  );
+};
 
-export default InputModal
+export default InputModal;
diff --git a/src/components/Modals/InputModal.test.js b/src/components/Modals/InputModal.test.js
index e4a164784..64c9a7eb0 100644
--- a/src/components/Modals/InputModal.test.js
+++ b/src/components/Modals/InputModal.test.js
@@ -1,43 +1,43 @@
 import React from "react";
-import configureStore from 'redux-mock-store';
+import configureStore from "redux-mock-store";
 import { render, screen } from "@testing-library/react";
 import { Provider } from "react-redux";
 import InputModal from "./InputModal";
 
-let inputBox
+let inputBox;
 
 beforeEach(() => {
-  const middlewares = []
-  const mockStore = configureStore(middlewares)
+  const middlewares = [];
+  const mockStore = configureStore(middlewares);
   const initialState = {
     editor: {
-      nameError: ''
-    }
-  }
+      nameError: "",
+    },
+  };
   const store = mockStore(initialState);
   render(
     <Provider store={store}>
-      <div id='app'>
+      <div id="app">
         <InputModal
           isOpen={true}
-          inputDefaultValue='my amazing default'
-          inputLabel='input'
-          inputHelpText='help me'
+          inputDefaultValue="my amazing default"
+          inputLabel="input"
+          inputHelpText="help me"
         />
       </div>
-    </Provider>
-  )
-  inputBox = screen.getByLabelText('input')
-})
+    </Provider>,
+  );
+  inputBox = screen.getByLabelText("input");
+});
 
-test('Renders help text', () => {
-  expect(screen.queryByText('help me')).toBeInTheDocument()
-})
+test("Renders help text", () => {
+  expect(screen.queryByText("help me")).toBeInTheDocument();
+});
 
-test('Input renders with default value', () => {
-  expect(inputBox).toHaveValue('my amazing default')
-})
+test("Input renders with default value", () => {
+  expect(inputBox).toHaveValue("my amazing default");
+});
 
-test('Focusses input box on load', () => {
-  expect(inputBox).toHaveFocus()
-})
+test("Focusses input box on load", () => {
+  expect(inputBox).toHaveFocus();
+});
diff --git a/src/components/Modals/LoginToSaveModal.js b/src/components/Modals/LoginToSaveModal.js
index 66231a401..1e0bf0aea 100644
--- a/src/components/Modals/LoginToSaveModal.js
+++ b/src/components/Modals/LoginToSaveModal.js
@@ -5,42 +5,55 @@ import { useTranslation } from "react-i18next";
 import { closeLoginToSaveModal } from "../Editor/EditorSlice";
 import DownloadButton from "../Header/DownloadButton";
 import LoginButton from "../Login/LoginButton";
-import '../../Modal.scss';
+import "../../Modal.scss";
 import Button from "../Button/Button";
 import GeneralModal from "./GeneralModal";
 import { login } from "../../utils/login";
 import { useLocation } from "react-router-dom";
 
 const LoginToSaveModal = () => {
-  const dispatch = useDispatch()
-  const { t } = useTranslation()
-  const location = useLocation()
-  const project = useSelector((state) => state.editor.project)
-  const isModalOpen = useSelector((state) => state.editor.loginToSaveModalShowing)
+  const dispatch = useDispatch();
+  const { t } = useTranslation();
+  const location = useLocation();
+  const project = useSelector((state) => state.editor.project);
+  const isModalOpen = useSelector(
+    (state) => state.editor.loginToSaveModalShowing,
+  );
   const closeModal = () => dispatch(closeLoginToSaveModal());
 
   const defaultCallback = () => {
-    login({project, location, triggerSave: true})
-  }
+    login({ project, location, triggerSave: true });
+  };
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('loginToSaveModal.heading')}
+      heading={t("loginToSaveModal.heading")}
       text={[
-        {type: 'paragraph', content: t('loginToSaveModal.loginText')},
-        {type: 'paragraph', content: t('loginToSaveModal.downloadText')}
+        { type: "paragraph", content: t("loginToSaveModal.loginText") },
+        { type: "paragraph", content: t("loginToSaveModal.downloadText") },
       ]}
       buttons={[
-        <LoginButton className='btn--primary' buttonText={t('loginToSaveModal.loginButtonText')} triggerSave />,
-        <DownloadButton buttonText = {t('loginToSaveModal.downloadButtonText')} className = 'btn--secondary' />,
-        <Button buttonText = {t('loginToSaveModal.cancel')} className='btn--tertiary' onClickHandler={closeModal}/>
+        <LoginButton
+          className="btn--primary"
+          buttonText={t("loginToSaveModal.loginButtonText")}
+          triggerSave
+        />,
+        <DownloadButton
+          buttonText={t("loginToSaveModal.downloadButtonText")}
+          className="btn--secondary"
+        />,
+        <Button
+          buttonText={t("loginToSaveModal.cancel")}
+          className="btn--tertiary"
+          onClickHandler={closeModal}
+        />,
       ]}
       defaultCallback={defaultCallback}
     />
   );
-}
+};
 
 export default LoginToSaveModal;
diff --git a/src/components/Modals/LoginToSaveModal.test.js b/src/components/Modals/LoginToSaveModal.test.js
index b16acd390..c16fe133b 100644
--- a/src/components/Modals/LoginToSaveModal.test.js
+++ b/src/components/Modals/LoginToSaveModal.test.js
@@ -1,37 +1,45 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import LoginToSaveModal from "./LoginToSaveModal";
 
-jest.mock('react-router-dom', () => ({
-  useLocation: jest.fn()
-}))
+jest.mock("react-router-dom", () => ({
+  useLocation: jest.fn(),
+}));
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
-describe('When loginToSaveModalShowing is true', () => {
-  let store
+describe("When loginToSaveModalShowing is true", () => {
+  let store;
 
   beforeEach(() => {
     const initialState = {
       editor: {
         loginToSaveModalShowing: true,
-        modals: {}
-      }
-    }
+        modals: {},
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><LoginToSaveModal /></div></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <LoginToSaveModal />
+        </div>
+      </Provider>,
+    );
+  });
 
-  test('Modal rendered', () => {
-    expect(screen.queryByText('loginToSaveModal.heading')).toBeInTheDocument()
-  })
+  test("Modal rendered", () => {
+    expect(screen.queryByText("loginToSaveModal.heading")).toBeInTheDocument();
+  });
 
-  test('Clicking cancel dispatches close modal action', () => {
-    const cancelLink = screen.queryByText('loginToSaveModal.cancel')
-    fireEvent.click(cancelLink)
-    expect(store.getActions()).toEqual([{type: 'editor/closeLoginToSaveModal'}])
-  })
-})
+  test("Clicking cancel dispatches close modal action", () => {
+    const cancelLink = screen.queryByText("loginToSaveModal.cancel");
+    fireEvent.click(cancelLink);
+    expect(store.getActions()).toEqual([
+      { type: "editor/closeLoginToSaveModal" },
+    ]);
+  });
+});
diff --git a/src/components/Modals/NewFileModal.js b/src/components/Modals/NewFileModal.js
index 5edb09965..31e55c244 100644
--- a/src/components/Modals/NewFileModal.js
+++ b/src/components/Modals/NewFileModal.js
@@ -1,49 +1,66 @@
-import React from 'react'
+import React from "react";
 
-import Button from '../Button/Button'
-import { addProjectComponent, closeNewFileModal, openFile } from '../Editor/EditorSlice';
-import { useDispatch, useSelector } from 'react-redux';
-import { useTranslation } from 'react-i18next';
-import { validateFileName } from '../../utils/componentNameValidation';
-import InputModal from './InputModal';
+import Button from "../Button/Button";
+import {
+  addProjectComponent,
+  closeNewFileModal,
+  openFile,
+} from "../Editor/EditorSlice";
+import { useDispatch, useSelector } from "react-redux";
+import { useTranslation } from "react-i18next";
+import { validateFileName } from "../../utils/componentNameValidation";
+import InputModal from "./InputModal";
 
 const NewFileModal = () => {
-
-  const { t } = useTranslation()
+  const { t } = useTranslation();
   const dispatch = useDispatch();
-  const projectType = useSelector((state) => state.editor.project.project_type)
-  const projectComponents = useSelector((state) => state.editor.project.components);
-  const componentNames = projectComponents.map(component => `${component.name}.${component.extension}`)
+  const projectType = useSelector((state) => state.editor.project.project_type);
+  const projectComponents = useSelector(
+    (state) => state.editor.project.components,
+  );
+  const componentNames = projectComponents.map(
+    (component) => `${component.name}.${component.extension}`,
+  );
 
-  const isModalOpen = useSelector((state) => state.editor.newFileModalShowing)
-  const closeModal = () => dispatch(closeNewFileModal())
+  const isModalOpen = useSelector((state) => state.editor.newFileModalShowing);
+  const closeModal = () => dispatch(closeNewFileModal());
 
   const createComponent = () => {
-    const fileName = document.getElementById('name').value
-    const name = fileName.split('.')[0];
-    const extension = fileName.split('.').slice(1).join('.');
+    const fileName = document.getElementById("name").value;
+    const name = fileName.split(".")[0];
+    const extension = fileName.split(".").slice(1).join(".");
     validateFileName(fileName, projectType, componentNames, dispatch, t, () => {
-      dispatch(addProjectComponent({extension: extension, name: name}));
-      dispatch(openFile(fileName))
+      dispatch(addProjectComponent({ extension: extension, name: name }));
+      dispatch(openFile(fileName));
       closeModal();
-    })
-  }
+    });
+  };
 
   return (
     <InputModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('filePane.newFileModal.heading')}
-      inputLabel={t('filePane.newFileModal.inputLabel')}
-      inputHelpText={t('filePane.newFileModal.helpText', {examples: t(`filePane.newFileModal.helpTextExample.${projectType}`)})}
+      heading={t("filePane.newFileModal.heading")}
+      inputLabel={t("filePane.newFileModal.inputLabel")}
+      inputHelpText={t("filePane.newFileModal.helpText", {
+        examples: t(`filePane.newFileModal.helpTextExample.${projectType}`),
+      })}
       defaultCallback={createComponent}
       buttons={[
-        <Button className='btn--primary' buttonText={t('filePane.newFileModal.addFile')} onClickHandler={createComponent} />,
-        <Button className='btn--secondary' buttonText={t('filePane.newFileModal.cancel')} onClickHandler={closeModal} />
+        <Button
+          className="btn--primary"
+          buttonText={t("filePane.newFileModal.addFile")}
+          onClickHandler={createComponent}
+        />,
+        <Button
+          className="btn--secondary"
+          buttonText={t("filePane.newFileModal.cancel")}
+          onClickHandler={closeModal}
+        />,
       ]}
     />
-  )
-}
+  );
+};
 
-export default NewFileModal
+export default NewFileModal;
diff --git a/src/components/Modals/NewFileModal.test.js b/src/components/Modals/NewFileModal.test.js
index 90304944f..6f7fd1aac 100644
--- a/src/components/Modals/NewFileModal.test.js
+++ b/src/components/Modals/NewFileModal.test.js
@@ -1,10 +1,15 @@
 import React from "react";
-import { fireEvent, render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import NewFileModal from "./NewFileModal";
-import { addProjectComponent, closeNewFileModal, openFile, setNameError } from "../Editor/EditorSlice";
+import {
+  addProjectComponent,
+  closeNewFileModal,
+  openFile,
+  setNameError,
+} from "../Editor/EditorSlice";
 
 describe("Testing the new file modal", () => {
   let store;
@@ -12,68 +17,78 @@ describe("Testing the new file modal", () => {
   let inputBox;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
               name: "main",
-              extension: "py"
-            }
+              extension: "py",
+            },
           ],
-          project_type: "python"
+          project_type: "python",
         },
         nameError: "",
-        newFileModalShowing: true
-      }
-    }
+        newFileModalShowing: true,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><NewFileModal /></div></Provider>)
-    saveButton = screen.getByText('filePane.newFileModal.addFile')
-    inputBox = screen.getByRole('textbox')
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <NewFileModal />
+        </div>
+      </Provider>,
+    );
+    saveButton = screen.getByText("filePane.newFileModal.addFile");
+    inputBox = screen.getByRole("textbox");
+  });
 
-  test('Modal renders',() => {
-    expect(screen.queryByText('filePane.newFileModal.heading')).toBeInTheDocument()
-  })
+  test("Modal renders", () => {
+    expect(
+      screen.queryByText("filePane.newFileModal.heading"),
+    ).toBeInTheDocument();
+  });
 
   test("Pressing save adds new file with the given name", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.py"}})
+    fireEvent.change(inputBox, { target: { value: "file1.py" } });
     inputBox.innerHTML = "file1.py";
-    fireEvent.click(saveButton)
+    fireEvent.click(saveButton);
     const expectedActions = [
-      addProjectComponent({extension: "py", name: "file1"}),
-      openFile('file1.py'),
-      closeNewFileModal()
-    ]
+      addProjectComponent({ extension: "py", name: "file1" }),
+      openFile("file1.py"),
+      closeNewFileModal(),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Pressing Enter adds new file with the given name", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.py"}})
+    fireEvent.change(inputBox, { target: { value: "file1.py" } });
     inputBox.innerHTML = "file1.py";
-    fireEvent.keyDown(inputBox, { key: 'Enter'})
+    fireEvent.keyDown(inputBox, { key: "Enter" });
     const expectedActions = [
-      addProjectComponent({extension: "py", name: "file1"}),
-      openFile('file1.py'),
-      closeNewFileModal()
-    ]
+      addProjectComponent({ extension: "py", name: "file1" }),
+      openFile("file1.py"),
+      closeNewFileModal(),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Duplicate file names throws error", () => {
-    fireEvent.change(inputBox, {target: {value: "main.py"}})
-    fireEvent.click(saveButton)
-    const expectedActions = [setNameError("filePane.errors.notUnique")]
+    fireEvent.change(inputBox, { target: { value: "main.py" } });
+    fireEvent.click(saveButton);
+    const expectedActions = [setNameError("filePane.errors.notUnique")];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Unsupported extension throws error", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.js"}})
-    fireEvent.click(saveButton)
-    const expectedActions = [setNameError("filePane.errors.unsupportedExtension")]
+    fireEvent.change(inputBox, { target: { value: "file1.js" } });
+    fireEvent.click(saveButton);
+    const expectedActions = [
+      setNameError("filePane.errors.unsupportedExtension"),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
-})
+  });
+});
diff --git a/src/components/Modals/NotFoundModal.js b/src/components/Modals/NotFoundModal.js
index 3eda74818..e36c73e04 100644
--- a/src/components/Modals/NotFoundModal.js
+++ b/src/components/Modals/NotFoundModal.js
@@ -3,42 +3,55 @@ import { useDispatch, useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 
 import Button from "../Button/Button";
-import '../../Modal.scss';
+import "../../Modal.scss";
 import { closeNotFoundModal, syncProject } from "../Editor/EditorSlice";
 import { defaultPythonProject } from "../../utils/defaultProjects";
 import GeneralModal from "./GeneralModal";
 
 const NotFoundModal = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  const user = useSelector((state) => state.auth.user)
-  
-  const isModalOpen = useSelector((state) => state.editor.notFoundModalShowing)
-  const closeModal = () => dispatch(closeNotFoundModal())
+  const user = useSelector((state) => state.auth.user);
+
+  const isModalOpen = useSelector((state) => state.editor.notFoundModalShowing);
+  const closeModal = () => dispatch(closeNotFoundModal());
 
   const createNewProject = async () => {
     if (user) {
-      dispatch(syncProject('save')({ project: defaultPythonProject, accessToken: user.access_token, autosave: false }))
+      dispatch(
+        syncProject("save")({
+          project: defaultPythonProject,
+          accessToken: user.access_token,
+          autosave: false,
+        }),
+      );
     }
-    closeModal()
-  }
+    closeModal();
+  };
 
   return (
     <GeneralModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('project.notFoundModal.heading')}
-      text={[
-        {type: 'paragraph', content: t('project.notFoundModal.text')}
-      ]}
+      heading={t("project.notFoundModal.heading")}
+      text={[{ type: "paragraph", content: t("project.notFoundModal.text") }]}
       buttons={[
-        <Button className='btn--primary' buttonText={t('project.notFoundModal.newProject')} onClickHandler={createNewProject} />,
-        <a className='btn btn--secondary' href='https://projects.raspberrypi.org'>{t('project.notFoundModal.projectsSiteLinkText')}</a>
+        <Button
+          className="btn--primary"
+          buttonText={t("project.notFoundModal.newProject")}
+          onClickHandler={createNewProject}
+        />,
+        <a
+          className="btn btn--secondary"
+          href="https://projects.raspberrypi.org"
+        >
+          {t("project.notFoundModal.projectsSiteLinkText")}
+        </a>,
       ]}
       defaultCallback={createNewProject}
     />
   );
-}
+};
 
 export default NotFoundModal;
diff --git a/src/components/Modals/NotFoundModal.test.js b/src/components/Modals/NotFoundModal.test.js
index 0fa07d079..c53dfb8f5 100644
--- a/src/components/Modals/NotFoundModal.test.js
+++ b/src/components/Modals/NotFoundModal.test.js
@@ -1,28 +1,28 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import NotFoundModal from "./NotFoundModal";
 import { closeNotFoundModal, syncProject } from "../Editor/EditorSlice";
 import { defaultPythonProject } from "../../utils/defaultProjects";
 
-jest.mock('../Editor/EditorSlice', () => ({
-  ...jest.requireActual('../Editor/EditorSlice'),
-  syncProject: jest.fn((_) => jest.fn())
-}))
+jest.mock("../Editor/EditorSlice", () => ({
+  ...jest.requireActual("../Editor/EditorSlice"),
+  syncProject: jest.fn((_) => jest.fn()),
+}));
 
 const user = {
   access_token: "39a09671-be55-4847-baf5-8919a0c24a25",
   profile: {
-    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf"
-  }
-}
+    user: "b48e70e2-d9ed-4a59-aee5-fc7cf09dbfaf",
+  },
+};
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
-describe('When logged in and notFoundModalShowing is true', () => {
-  let store
+describe("When logged in and notFoundModalShowing is true", () => {
+  let store;
 
   beforeEach(() => {
     const initialState = {
@@ -30,48 +30,68 @@ describe('When logged in and notFoundModalShowing is true', () => {
         notFoundModalShowing: true,
       },
       auth: {
-        user: user
-      }
-    }
+        user: user,
+      },
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><NotFoundModal /></div></Provider>)
-  })
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <NotFoundModal />
+        </div>
+      </Provider>,
+    );
+  });
 
-  test('Modal rendered', () => {
-    expect(screen.queryByText('project.notFoundModal.heading')).toBeInTheDocument()
-  })
+  test("Modal rendered", () => {
+    expect(
+      screen.queryByText("project.notFoundModal.heading"),
+    ).toBeInTheDocument();
+  });
 
-  test('Clicking new project creates a new project', async () => {
-    const newProjectLink = screen.queryByText('project.notFoundModal.newProject')
-    const saveAction = {type: 'SAVE_PROJECT' }
-    const saveProject = jest.fn(() => saveAction)
-    syncProject.mockImplementationOnce(jest.fn((_) => (saveProject)))
-    fireEvent.click(newProjectLink)
-    await waitFor(() => expect(saveProject).toHaveBeenCalledWith({
-      project: defaultPythonProject,
-      accessToken: user.access_token,
-      autosave: false
-    }))
-    expect(store.getActions()[0]).toEqual(saveAction)
-  })
-})
+  test("Clicking new project creates a new project", async () => {
+    const newProjectLink = screen.queryByText(
+      "project.notFoundModal.newProject",
+    );
+    const saveAction = { type: "SAVE_PROJECT" };
+    const saveProject = jest.fn(() => saveAction);
+    syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+    fireEvent.click(newProjectLink);
+    await waitFor(() =>
+      expect(saveProject).toHaveBeenCalledWith({
+        project: defaultPythonProject,
+        accessToken: user.access_token,
+        autosave: false,
+      }),
+    );
+    expect(store.getActions()[0]).toEqual(saveAction);
+  });
+});
 
-describe('When not logged in', () => {
-  let store
+describe("When not logged in", () => {
+  let store;
 
   beforeEach(() => {
     const initialState = {
       editor: {
         notFoundModalShowing: true,
       },
-      auth: {}
-    }
+      auth: {},
+    };
     store = mockStore(initialState);
-    render(<Provider store={store}><div id='app'><NotFoundModal /></div></Provider>)
-  })
-  test('Clicking new project closes the modal', () => {
-    const newProjectLink = screen.queryByText('project.notFoundModal.newProject')
-    fireEvent.click(newProjectLink)
-    expect(store.getActions()).toEqual([closeNotFoundModal()])
-  })
-})
+    render(
+      <Provider store={store}>
+        <div id="app">
+          <NotFoundModal />
+        </div>
+      </Provider>,
+    );
+  });
+  test("Clicking new project closes the modal", () => {
+    const newProjectLink = screen.queryByText(
+      "project.notFoundModal.newProject",
+    );
+    fireEvent.click(newProjectLink);
+    expect(store.getActions()).toEqual([closeNotFoundModal()]);
+  });
+});
diff --git a/src/components/Modals/RenameFile.js b/src/components/Modals/RenameFile.js
index 55897541a..e4d7fa64d 100644
--- a/src/components/Modals/RenameFile.js
+++ b/src/components/Modals/RenameFile.js
@@ -3,47 +3,82 @@ import { useDispatch, useSelector } from "react-redux";
 import { useTranslation } from "react-i18next";
 import { validateFileName } from "../../utils/componentNameValidation";
 import Button from "../Button/Button";
-import { closeRenameFileModal, updateComponentName } from "../Editor/EditorSlice";
-import '../../Modal.scss';
+import {
+  closeRenameFileModal,
+  updateComponentName,
+} from "../Editor/EditorSlice";
+import "../../Modal.scss";
 import InputModal from "./InputModal";
 
 const RenameFile = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  const projectType = useSelector((state) => state.editor.project.project_type)
-  const projectComponents = useSelector((state) => state.editor.project.components)
-  const isModalOpen = useSelector((state) => state.editor.renameFileModalShowing)
-  const {name: currentName, ext: currentExtension, fileKey} = useSelector((state) => state.editor.modals.renameFile);
-  const componentNames = projectComponents.map(component => `${component.name}.${component.extension}`)
+  const projectType = useSelector((state) => state.editor.project.project_type);
+  const projectComponents = useSelector(
+    (state) => state.editor.project.components,
+  );
+  const isModalOpen = useSelector(
+    (state) => state.editor.renameFileModalShowing,
+  );
+  const {
+    name: currentName,
+    ext: currentExtension,
+    fileKey,
+  } = useSelector((state) => state.editor.modals.renameFile);
+  const componentNames = projectComponents.map(
+    (component) => `${component.name}.${component.extension}`,
+  );
 
   const closeModal = () => dispatch(closeRenameFileModal());
 
   const renameComponent = () => {
-    const fileName = document.getElementById('name').value
-    const name = fileName.split('.')[0];
-    const extension = fileName.split('.').slice(1).join('.');
+    const fileName = document.getElementById("name").value;
+    const name = fileName.split(".")[0];
+    const extension = fileName.split(".").slice(1).join(".");
 
-    validateFileName(fileName, projectType, componentNames, dispatch, t, () => {
-      dispatch(updateComponentName({key: fileKey, extension: extension, name: name}));
-      closeModal();
-    }, `${currentName}.${currentExtension}`)
-  }
+    validateFileName(
+      fileName,
+      projectType,
+      componentNames,
+      dispatch,
+      t,
+      () => {
+        dispatch(
+          updateComponentName({
+            key: fileKey,
+            extension: extension,
+            name: name,
+          }),
+        );
+        closeModal();
+      },
+      `${currentName}.${currentExtension}`,
+    );
+  };
 
   return (
     <InputModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('filePane.renameFileModal.heading')}
-      inputLabel={t('filePane.renameFileModal.inputLabel')}
+      heading={t("filePane.renameFileModal.heading")}
+      inputLabel={t("filePane.renameFileModal.inputLabel")}
       inputDefaultValue={`${currentName}.${currentExtension}`}
       defaultCallback={renameComponent}
       buttons={[
-        <Button className='btn--primary' buttonText={t('filePane.renameFileModal.save')} onClickHandler={renameComponent} />,
-        <Button className='btn--secondary' buttonText={t('filePane.renameFileModal.cancel')} onClickHandler={closeModal} />
+        <Button
+          className="btn--primary"
+          buttonText={t("filePane.renameFileModal.save")}
+          onClickHandler={renameComponent}
+        />,
+        <Button
+          className="btn--secondary"
+          buttonText={t("filePane.renameFileModal.cancel")}
+          onClickHandler={closeModal}
+        />,
       ]}
     />
   );
-}
+};
 
 export default RenameFile;
diff --git a/src/components/Modals/RenameFile.test.js b/src/components/Modals/RenameFile.test.js
index 249e70a11..0a1be1d11 100644
--- a/src/components/Modals/RenameFile.test.js
+++ b/src/components/Modals/RenameFile.test.js
@@ -1,10 +1,14 @@
 import React from "react";
-import { fireEvent, render } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 
 import RenameFile from "./RenameFile";
-import { setNameError, updateComponentName, closeRenameFileModal } from "../Editor/EditorSlice";
+import {
+  setNameError,
+  updateComponentName,
+  closeRenameFileModal,
+} from "../Editor/EditorSlice";
 
 describe("Testing the rename file modal", () => {
   let store;
@@ -13,86 +17,94 @@ describe("Testing the rename file modal", () => {
   let getByText;
 
   beforeEach(() => {
-    const middlewares = []
-    const mockStore = configureStore(middlewares)
+    const middlewares = [];
+    const mockStore = configureStore(middlewares);
     const initialState = {
       editor: {
         project: {
           components: [
             {
               name: "main",
-              extension: "py"
+              extension: "py",
             },
             {
               name: "my_file",
-              extension: "py"
-            }
+              extension: "py",
+            },
           ],
-          project_type: "python"
+          project_type: "python",
         },
         nameError: "",
         modals: {
           renameFile: {
-            name: 'main',
-            ext: 'py',
-            fileKey: 0
-          }
+            name: "main",
+            ext: "py",
+            fileKey: 0,
+          },
         },
-        renameFileModalShowing: true
-      }
-    }
+        renameFileModalShowing: true,
+      },
+    };
     store = mockStore(initialState);
-    ({getByText} = render(<Provider store={store}><div id='app'><RenameFile currentName='main' currentExtension='py' fileKey={0} /></div></Provider>))
-    inputBox = document.getElementById('name')
-    saveButton = getByText('filePane.renameFileModal.save');
-  })
+    ({ getByText } = render(
+      <Provider store={store}>
+        <div id="app">
+          <RenameFile currentName="main" currentExtension="py" fileKey={0} />
+        </div>
+      </Provider>,
+    ));
+    inputBox = document.getElementById("name");
+    saveButton = getByText("filePane.renameFileModal.save");
+  });
 
-  test('State being set displays the modal', () => {
-    expect(getByText('filePane.renameFileModal.heading')).toBeInTheDocument()
-  })
+  test("State being set displays the modal", () => {
+    expect(getByText("filePane.renameFileModal.heading")).toBeInTheDocument();
+  });
 
   test("Pressing save renames the file to the given name", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.py"}})
+    fireEvent.change(inputBox, { target: { value: "file1.py" } });
     inputBox.innerHTML = "file1.py";
-    fireEvent.click(saveButton)
+    fireEvent.click(saveButton);
     const expectedActions = [
-      updateComponentName({key: 0, extension: "py", name: "file1"}),
-      closeRenameFileModal()
-    ]
+      updateComponentName({ key: 0, extension: "py", name: "file1" }),
+      closeRenameFileModal(),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Pressing Enter renames the file to the given name", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.py"}})
+    fireEvent.change(inputBox, { target: { value: "file1.py" } });
     inputBox.innerHTML = "file1.py";
-    fireEvent.keyDown(inputBox, { key: 'Enter'})
+    fireEvent.keyDown(inputBox, { key: "Enter" });
     const expectedActions = [
-      updateComponentName({key: 0, extension: "py", name: "file1"}),
-      closeRenameFileModal()
-    ]
+      updateComponentName({ key: 0, extension: "py", name: "file1" }),
+      closeRenameFileModal(),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Duplicate file names throws error", () => {
-    fireEvent.change(inputBox, {target: {value: "my_file.py"}})
-    fireEvent.click(saveButton)
-    const expectedActions = [setNameError('filePane.errors.notUnique')]
+    fireEvent.change(inputBox, { target: { value: "my_file.py" } });
+    fireEvent.click(saveButton);
+    const expectedActions = [setNameError("filePane.errors.notUnique")];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Unchanged file name does not throw error", () => {
-    fireEvent.click(saveButton)
+    fireEvent.click(saveButton);
     const expectedActions = [
-      updateComponentName({key: 0, extension: "py", name: "main"}),
-      closeRenameFileModal()
-  ]
+      updateComponentName({ key: 0, extension: "py", name: "main" }),
+      closeRenameFileModal(),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
+  });
 
   test("Unsupported extension throws error", () => {
-    fireEvent.change(inputBox, {target: {value: "file1.js"}})
-    fireEvent.click(saveButton)
-    const expectedActions = [setNameError("filePane.errors.unsupportedExtension")]
+    fireEvent.change(inputBox, { target: { value: "file1.js" } });
+    fireEvent.click(saveButton);
+    const expectedActions = [
+      setNameError("filePane.errors.unsupportedExtension"),
+    ];
     expect(store.getActions()).toEqual(expectedActions);
-  })
-})
+  });
+});
diff --git a/src/components/Modals/RenameProjectModal.js b/src/components/Modals/RenameProjectModal.js
index 2cf86d614..99f87e648 100644
--- a/src/components/Modals/RenameProjectModal.js
+++ b/src/components/Modals/RenameProjectModal.js
@@ -1,15 +1,15 @@
 import React from "react";
-import { gql, useMutation } from '@apollo/client';
+import { gql, useMutation } from "@apollo/client";
 import { useTranslation } from "react-i18next";
 import { useDispatch, useSelector } from "react-redux";
 import { closeRenameProjectModal } from "../Editor/EditorSlice";
-import { showRenamedMessage } from '../../utils/Notifications';
+import { showRenamedMessage } from "../../utils/Notifications";
 import Button from "../Button/Button";
 import InputModal from "./InputModal";
 
 export const RENAME_PROJECT_MUTATION = gql`
   mutation RenameProject($id: String!, $name: String!) {
-    updateProject(input: {id: $id, name: $name}) {
+    updateProject(input: { id: $id, name: $name }) {
       project {
         id
         name
@@ -20,41 +20,54 @@ export const RENAME_PROJECT_MUTATION = gql`
 `;
 
 export const RenameProjectModal = () => {
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
   const { t } = useTranslation();
-  const isModalOpen = useSelector((state) => state.editor.renameProjectModalShowing)
-  const project = useSelector((state) => state.editor.modals.renameProject)
-  const closeModal = () => dispatch(closeRenameProjectModal())
+  const isModalOpen = useSelector(
+    (state) => state.editor.renameProjectModalShowing,
+  );
+  const project = useSelector((state) => state.editor.modals.renameProject);
+  const closeModal = () => dispatch(closeRenameProjectModal());
 
   const onCompleted = () => {
-    closeModal()
-    showRenamedMessage()
-  }
+    closeModal();
+    showRenamedMessage();
+  };
 
   // This can capture data, error, loading as per normal queries, but we're not
   // using them yet.
   const [renameProjectMutation] = useMutation(RENAME_PROJECT_MUTATION);
 
   const renameProject = () => {
-    const newName = document.getElementById('name').value
-    renameProjectMutation({variables: {id: project.id, name: newName}, onCompleted: onCompleted})
-  }
+    const newName = document.getElementById("name").value;
+    renameProjectMutation({
+      variables: { id: project.id, name: newName },
+      onCompleted: onCompleted,
+    });
+  };
 
   return (
     <InputModal
       isOpen={isModalOpen}
       closeModal={closeModal}
       withCloseButton
-      heading={t('projectList.renameProjectModal.heading')}
-      inputLabel={t('projectList.renameProjectModal.inputLabel')}
+      heading={t("projectList.renameProjectModal.heading")}
+      inputLabel={t("projectList.renameProjectModal.inputLabel")}
       inputDefaultValue={project.name}
       defaultCallback={renameProject}
       buttons={[
-        <Button className='btn--primary' buttonText={t('projectList.renameProjectModal.save')} onClickHandler={renameProject} />,
-        <Button className='btn--secondary' buttonText={t('projectList.renameProjectModal.cancel')} onClickHandler={closeModal} />
+        <Button
+          className="btn--primary"
+          buttonText={t("projectList.renameProjectModal.save")}
+          onClickHandler={renameProject}
+        />,
+        <Button
+          className="btn--secondary"
+          buttonText={t("projectList.renameProjectModal.cancel")}
+          onClickHandler={closeModal}
+        />,
       ]}
     />
   );
-}
+};
 
-export default RenameProjectModal
+export default RenameProjectModal;
diff --git a/src/components/Modals/RenameProjectModal.test.js b/src/components/Modals/RenameProjectModal.test.js
index 89357b8a0..86bc364c3 100644
--- a/src/components/Modals/RenameProjectModal.test.js
+++ b/src/components/Modals/RenameProjectModal.test.js
@@ -1,116 +1,135 @@
 import React from "react";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import { MockedProvider } from "@apollo/client/testing";
 
-import { RenameProjectModal, RENAME_PROJECT_MUTATION } from "./RenameProjectModal";
-import { showRenamedMessage } from '../../utils/Notifications';
+import {
+  RenameProjectModal,
+  RENAME_PROJECT_MUTATION,
+} from "./RenameProjectModal";
+import { showRenamedMessage } from "../../utils/Notifications";
 
-jest.mock('../../utils/Notifications')
+jest.mock("../../utils/Notifications");
 
 describe("RenameProjectModal", () => {
-  let store
-  let inputBox
-  let saveButton
+  let store;
+  let inputBox;
+  let saveButton;
   let project = {
-    name: 'my first project',
-    id: 'XYZ'
-  }
-  let newName = 'renamed project'
-  let mocks
+    name: "my first project",
+    id: "XYZ",
+  };
+  let newName = "renamed project";
+  let mocks;
 
   beforeEach(() => {
     mocks = [
       {
         request: {
           query: RENAME_PROJECT_MUTATION,
-          variables: { id: project.id, name: newName }
+          variables: { id: project.id, name: newName },
         },
         result: jest.fn(() => ({
           data: {
             id: project.id,
             name: newName,
-            updatedAt: '2023-02-257T14:48:00Z'
-          }
-        }))
-      }
-    ]
+            updatedAt: "2023-02-257T14:48:00Z",
+          },
+        })),
+      },
+    ];
 
-    const mockStore = configureStore([])
+    const mockStore = configureStore([]);
     const initialState = {
       editor: {
         modals: {
-          renameProject: project
+          renameProject: project,
         },
-        renameProjectModalShowing: true
-      }
-    }
+        renameProjectModalShowing: true,
+      },
+    };
     store = mockStore(initialState);
 
     render(
       <MockedProvider mocks={mocks}>
         <Provider store={store}>
-          <div id='app'><RenameProjectModal /></div>
+          <div id="app">
+            <RenameProjectModal />
+          </div>
         </Provider>
-      </MockedProvider>
-    )
+      </MockedProvider>,
+    );
 
-    inputBox = screen.getByRole('textbox')
-    saveButton = screen.getByText('projectList.renameProjectModal.save')
-  })
+    inputBox = screen.getByRole("textbox");
+    saveButton = screen.getByText("projectList.renameProjectModal.save");
+  });
 
-  test('Modal renders', () => {
-    expect(screen.getByText('projectList.renameProjectModal.heading')).not.toBeNull()
-  })
+  test("Modal renders", () => {
+    expect(
+      screen.getByText("projectList.renameProjectModal.heading"),
+    ).not.toBeNull();
+  });
 
-  test('Clicking cancel button closes modal and does not save', () => {
-    const cancelButton = screen.queryByText('projectList.renameProjectModal.cancel')
-    fireEvent.click(cancelButton)
-    expect(store.getActions()).toEqual([{type: 'editor/closeRenameProjectModal'}])
-  })
+  test("Clicking cancel button closes modal and does not save", () => {
+    const cancelButton = screen.queryByText(
+      "projectList.renameProjectModal.cancel",
+    );
+    fireEvent.click(cancelButton);
+    expect(store.getActions()).toEqual([
+      { type: "editor/closeRenameProjectModal" },
+    ]);
+  });
 
-  describe('Clicking save', () => {
+  describe("Clicking save", () => {
     let renameProjectMutationMock;
 
     beforeEach(() => {
-      renameProjectMutationMock = mocks[0].result
-      fireEvent.change(inputBox, {target: {value: "renamed project"}})
-      fireEvent.click(saveButton)
-    })
+      renameProjectMutationMock = mocks[0].result;
+      fireEvent.change(inputBox, { target: { value: "renamed project" } });
+      fireEvent.click(saveButton);
+    });
 
     test("Calls the mutation", async () => {
-      await waitFor(() => expect(renameProjectMutationMock).toHaveBeenCalled())
-    })
-  
+      await waitFor(() => expect(renameProjectMutationMock).toHaveBeenCalled());
+    });
+
     test("Eventually closes the modal", async () => {
-      await waitFor(() => expect(store.getActions()).toEqual([{type: 'editor/closeRenameProjectModal'}]))
-    })
-  
+      await waitFor(() =>
+        expect(store.getActions()).toEqual([
+          { type: "editor/closeRenameProjectModal" },
+        ]),
+      );
+    });
+
     test("Eventually pops up the toast notification", async () => {
-      await waitFor(() => expect(showRenamedMessage).toHaveBeenCalled())
-    })
-  })
+      await waitFor(() => expect(showRenamedMessage).toHaveBeenCalled());
+    });
+  });
 
-  describe('Pressing Enter', () => {
+  describe("Pressing Enter", () => {
     let renameProjectMutationMock;
 
     beforeEach(() => {
-      renameProjectMutationMock = mocks[0].result
-      fireEvent.change(inputBox, {target: {value: "renamed project"}})
-      fireEvent.keyDown(inputBox, { key: 'Enter'})
-    })
+      renameProjectMutationMock = mocks[0].result;
+      fireEvent.change(inputBox, { target: { value: "renamed project" } });
+      fireEvent.keyDown(inputBox, { key: "Enter" });
+    });
 
     test("Calls the mutation", async () => {
-      await waitFor(() => expect(renameProjectMutationMock).toHaveBeenCalled())
-    })
-  
+      await waitFor(() => expect(renameProjectMutationMock).toHaveBeenCalled());
+    });
+
     test("Eventually closes the modal", async () => {
-      await waitFor(() => expect(store.getActions()).toEqual([{type: 'editor/closeRenameProjectModal'}]))
-    })
-  
+      await waitFor(() =>
+        expect(store.getActions()).toEqual([
+          { type: "editor/closeRenameProjectModal" },
+        ]),
+      );
+    });
+
     test("Eventually pops up the toast notification", async () => {
-      await waitFor(() => expect(showRenamedMessage).toHaveBeenCalled())
-    })
-  })
-})
+      await waitFor(() => expect(showRenamedMessage).toHaveBeenCalled());
+    });
+  });
+});
diff --git a/src/components/ProjectIndex/ProjectIndex.js b/src/components/ProjectIndex/ProjectIndex.js
index a460beaf2..a6568e3f2 100644
--- a/src/components/ProjectIndex/ProjectIndex.js
+++ b/src/components/ProjectIndex/ProjectIndex.js
@@ -51,16 +51,16 @@ const ProjectIndex = (props) => {
   useRequiresUser(isLoading, user);
 
   const renameProjectModalShowing = useSelector(
-    (state) => state.editor.renameProjectModalShowing
+    (state) => state.editor.renameProjectModalShowing,
   );
   const deleteProjectModalShowing = useSelector(
-    (state) => state.editor.deleteProjectModalShowing
+    (state) => state.editor.deleteProjectModalShowing,
   );
 
   const onCreateProject = async () => {
     const response = await createOrUpdateProject(
       defaultPythonProject,
-      user.access_token
+      user.access_token,
     );
     const identifier = response.data.identifier;
     const locale = i18n.language;
diff --git a/src/components/ProjectIndex/ProjectIndex.test.js b/src/components/ProjectIndex/ProjectIndex.test.js
index 1c27f6038..339a1996e 100644
--- a/src/components/ProjectIndex/ProjectIndex.test.js
+++ b/src/components/ProjectIndex/ProjectIndex.test.js
@@ -94,7 +94,7 @@ describe("When authenticated", () => {
               <ProjectIndex user={user} isLoading={false} />
             </MockedProvider>
           </MemoryRouter>
-        </Provider>
+        </Provider>,
       );
     });
 
@@ -120,7 +120,7 @@ describe("When unauthenticated", () => {
         <Provider store={store}>
           <ProjectIndex />
         </Provider>
-      </MockedProvider>
+      </MockedProvider>,
     );
   });
 
diff --git a/src/components/ProjectIndex/ProjectIndexPagination.test.js b/src/components/ProjectIndex/ProjectIndexPagination.test.js
index 2f7a6cb49..e37ad480c 100644
--- a/src/components/ProjectIndex/ProjectIndexPagination.test.js
+++ b/src/components/ProjectIndex/ProjectIndexPagination.test.js
@@ -17,13 +17,13 @@ describe("When pageInfo is missing", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("It doesn't show the navigation", () => {
     expect(
-      screen.queryByTestId("projectIndexPagination")
+      screen.queryByTestId("projectIndexPagination"),
     ).not.toBeInTheDocument();
   });
 });
@@ -39,13 +39,13 @@ describe("When totalCount is missing", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("It doesn't show the navigation", () => {
     expect(
-      screen.queryByTestId("projectIndexPagination")
+      screen.queryByTestId("projectIndexPagination"),
     ).not.toBeInTheDocument();
   });
 });
@@ -66,13 +66,13 @@ describe("When on the first page of projects", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("More buttons shown", () => {
     expect(
-      screen.queryByTitle("projectList.pagination.more")
+      screen.queryByTitle("projectList.pagination.more"),
     ).toBeInTheDocument();
   });
 });
@@ -91,13 +91,13 @@ describe("When the endCursor is missing", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("Assume there is more to load", () => {
     expect(
-      screen.queryByTitle("projectList.pagination.more")
+      screen.queryByTitle("projectList.pagination.more"),
     ).toBeInTheDocument();
   });
 });
@@ -119,13 +119,13 @@ describe("When on a middle page of projects", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("More buttons shown", () => {
     expect(
-      screen.queryByTitle("projectList.pagination.more")
+      screen.queryByTitle("projectList.pagination.more"),
     ).toBeInTheDocument();
   });
 
@@ -154,13 +154,13 @@ describe("When on the last page of projects", () => {
         pageSize={pageSize}
         paginationData={paginationData}
         fetchMore={fetchMore}
-      />
+      />,
     );
   });
 
   test("More button not shown", () => {
     expect(
-      screen.queryByTitle("projectList.pagination.more")
+      screen.queryByTitle("projectList.pagination.more"),
     ).not.toBeInTheDocument();
   });
 });
diff --git a/src/components/ProjectIndexHeader/ProjectIndexHeader.js b/src/components/ProjectIndexHeader/ProjectIndexHeader.js
index 9f8558935..b4408c803 100644
--- a/src/components/ProjectIndexHeader/ProjectIndexHeader.js
+++ b/src/components/ProjectIndexHeader/ProjectIndexHeader.js
@@ -1,21 +1,20 @@
-import { useTranslation } from 'react-i18next';
-import './ProjectIndexHeader.scss'
-
+import { useTranslation } from "react-i18next";
+import "./ProjectIndexHeader.scss";
 
 const ProjectIndexHeader = (props) => {
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
   return (
-    <header className='editor-project-header'>
-      <div className='editor-project-header__inner'>
-        <div className='editor-project-header__content'>
-          <h2>{t('projectHeader.subTitle')}</h2>
-          <h1 className='editor-project-header__title'>{t('projectHeader.title')}</h1>
-          <h3>{t('projectHeader.text')}</h3>
-        </div>
-        <div className='editor-project-header__action'>
-          {props.children}
+    <header className="editor-project-header">
+      <div className="editor-project-header__inner">
+        <div className="editor-project-header__content">
+          <h2>{t("projectHeader.subTitle")}</h2>
+          <h1 className="editor-project-header__title">
+            {t("projectHeader.title")}
+          </h1>
+          <h3>{t("projectHeader.text")}</h3>
         </div>
+        <div className="editor-project-header__action">{props.children}</div>
       </div>
     </header>
   );
diff --git a/src/components/ProjectListItem/ProjectListItem.js b/src/components/ProjectListItem/ProjectListItem.js
index f16682955..948da4f31 100644
--- a/src/components/ProjectListItem/ProjectListItem.js
+++ b/src/components/ProjectListItem/ProjectListItem.js
@@ -32,7 +32,7 @@ export const ProjectListItem = (props) => {
   const lastSaved = intlFormatDistance(
     new Date(project.updatedAt),
     Date.now(),
-    { style: "short" }
+    { style: "short" },
   );
   const projectType = props.project.projectType;
 
diff --git a/src/components/ProjectListItem/ProjectListItem.test.js b/src/components/ProjectListItem/ProjectListItem.test.js
index 2cd2e621d..710ac5276 100644
--- a/src/components/ProjectListItem/ProjectListItem.test.js
+++ b/src/components/ProjectListItem/ProjectListItem.test.js
@@ -2,34 +2,48 @@ import { fireEvent, render, screen } from "@testing-library/react";
 import React from "react";
 import { Provider } from "react-redux";
 import { MemoryRouter } from "react-router-dom";
-import configureStore from 'redux-mock-store';
+import configureStore from "redux-mock-store";
 import { ProjectListItem } from "./ProjectListItem";
 
-jest.mock('date-fns')
+jest.mock("date-fns");
 
-let store
-let project = { identifier: 'hello-world-project', name: 'my amazing project', updatedAt: Date.now() }
+let store;
+let project = {
+  identifier: "hello-world-project",
+  name: "my amazing project",
+  updatedAt: Date.now(),
+};
 
 beforeEach(() => {
-  const mockStore = configureStore([])
-  const initialState = {}
+  const mockStore = configureStore([]);
+  const initialState = {};
   store = mockStore(initialState);
 
-  render(<Provider store={store}><MemoryRouter><ProjectListItem project = {project}/></MemoryRouter></Provider>)
-})
+  render(
+    <Provider store={store}>
+      <MemoryRouter>
+        <ProjectListItem project={project} />
+      </MemoryRouter>
+    </Provider>,
+  );
+});
 
-test('Renders project name', () => {
-  expect(screen.queryByText(project.name)).toBeInTheDocument()
-})
+test("Renders project name", () => {
+  expect(screen.queryByText(project.name)).toBeInTheDocument();
+});
 
-test('Clicking rename button opens rename project modal', () => {
-  const renameButtons = screen.queryAllByText('projectList.rename')
-  fireEvent.click(renameButtons[0])
-  expect(store.getActions()).toEqual([{type: "editor/showRenameProjectModal", payload: project}])
-})
+test("Clicking rename button opens rename project modal", () => {
+  const renameButtons = screen.queryAllByText("projectList.rename");
+  fireEvent.click(renameButtons[0]);
+  expect(store.getActions()).toEqual([
+    { type: "editor/showRenameProjectModal", payload: project },
+  ]);
+});
 
-test('Clicking delete button opens delete project modal', () => {
-  const deleteButtons = screen.queryAllByText('projectList.delete')
-  fireEvent.click(deleteButtons[0])
-  expect(store.getActions()).toEqual([{type: "editor/showDeleteProjectModal", payload: project}])
-})
+test("Clicking delete button opens delete project modal", () => {
+  const deleteButtons = screen.queryAllByText("projectList.delete");
+  fireEvent.click(deleteButtons[0]);
+  expect(store.getActions()).toEqual([
+    { type: "editor/showDeleteProjectModal", payload: project },
+  ]);
+});
diff --git a/src/components/ProjectListTable/ProjectListTable.js b/src/components/ProjectListTable/ProjectListTable.js
index 910dff231..03cc16c08 100644
--- a/src/components/ProjectListTable/ProjectListTable.js
+++ b/src/components/ProjectListTable/ProjectListTable.js
@@ -1,7 +1,10 @@
-import { useTranslation } from 'react-i18next';
-import { ProjectListItem, PROJECT_LIST_ITEM_FRAGMENT } from '../ProjectListItem/ProjectListItem'
-import './ProjectListTable.scss'
-import { gql } from '@apollo/client';
+import { useTranslation } from "react-i18next";
+import {
+  ProjectListItem,
+  PROJECT_LIST_ITEM_FRAGMENT,
+} from "../ProjectListItem/ProjectListItem";
+import "./ProjectListTable.scss";
+import { gql } from "@apollo/client";
 
 export const PROJECT_LIST_TABLE_FRAGMENT = gql`
   fragment ProjectListTableFragment on ProjectConnection {
@@ -16,7 +19,6 @@ export const PROJECT_LIST_TABLE_FRAGMENT = gql`
   ${PROJECT_LIST_ITEM_FRAGMENT}
 `;
 
-
 export const ProjectListTable = (props) => {
   const { t } = useTranslation();
   const { projectData } = props;
@@ -24,22 +26,20 @@ export const ProjectListTable = (props) => {
   const projectList = projectData?.edges?.map((edge) => edge.node);
 
   return (
-    <div className='editor-project-list'>
-      <div className='editor-project-list__container'>
-        { projectList && projectList.length > 0 ?
+    <div className="editor-project-list">
+      <div className="editor-project-list__container">
+        {projectList && projectList.length > 0 ? (
           <>
-            { projectList.map((project, i) => (
-                <ProjectListItem project={project} key={i}/>
-              )
-            )}
+            {projectList.map((project, i) => (
+              <ProjectListItem project={project} key={i} />
+            ))}
           </>
-          :
-          <div className='editor-project-list__empty'>
-            <p>{t('projectList.empty')}</p>
+        ) : (
+          <div className="editor-project-list__empty">
+            <p>{t("projectList.empty")}</p>
           </div>
-        }
+        )}
       </div>
     </div>
-  )
+  );
 };
-
diff --git a/src/components/ProjectListTable/ProjectListTable.test.js b/src/components/ProjectListTable/ProjectListTable.test.js
index 212b01314..811828a22 100644
--- a/src/components/ProjectListTable/ProjectListTable.test.js
+++ b/src/components/ProjectListTable/ProjectListTable.test.js
@@ -1,50 +1,64 @@
-import { render, screen } from '@testing-library/react';
-import { Provider } from 'react-redux';
-import { MemoryRouter } from 'react-router-dom';
-import configureStore from 'redux-mock-store';
-import { ProjectListTable } from './ProjectListTable';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import { MemoryRouter } from "react-router-dom";
+import configureStore from "redux-mock-store";
+import { ProjectListTable } from "./ProjectListTable";
 
-describe('When the logged in user has projects', () => {
+describe("When the logged in user has projects", () => {
   const project = {
-    name: 'hello world',
-    project_type: 'python',
-    identifier: 'hello-world-project',
-    updatedAt: Date.now()
-  }
+    name: "hello world",
+    project_type: "python",
+    identifier: "hello-world-project",
+    updatedAt: Date.now(),
+  };
 
   const projectData = {
-    edges: [{
-      cursor: "Mq",
-      node: { ...project }
-    }]
-  }
+    edges: [
+      {
+        cursor: "Mq",
+        node: { ...project },
+      },
+    ],
+  };
 
   beforeEach(() => {
     const mockStore = configureStore([]);
-    const initialState = {}
-    const store = mockStore(initialState)
+    const initialState = {};
+    const store = mockStore(initialState);
 
-    render(<Provider store={store}><MemoryRouter><ProjectListTable projectData = { projectData } /></MemoryRouter></Provider>);
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <ProjectListTable projectData={projectData} />
+        </MemoryRouter>
+      </Provider>,
+    );
   });
 
-  test('The projects page show a list of projects', () => {
+  test("The projects page show a list of projects", () => {
     expect(screen.queryByText(project.name)).toBeInTheDocument();
   });
 });
 
-describe('When the logged in user has no projects', () => {
+describe("When the logged in user has no projects", () => {
   const projectData = {
-    edges: []
-  }
+    edges: [],
+  };
 
   beforeEach(() => {
     const mockStore = configureStore([]);
-    const initialState = { }
+    const initialState = {};
     const store = mockStore(initialState);
-    render(<Provider store={store}><MemoryRouter><ProjectListTable projectData = { projectData } /></MemoryRouter></Provider>);
+    render(
+      <Provider store={store}>
+        <MemoryRouter>
+          <ProjectListTable projectData={projectData} />
+        </MemoryRouter>
+      </Provider>,
+    );
   });
 
-  test('The projects page show an empty state message', () => {
-    expect(screen.queryByText('projectList.empty')).toBeInTheDocument();
+  test("The projects page show an empty state message", () => {
+    expect(screen.queryByText("projectList.empty")).toBeInTheDocument();
   });
 });
diff --git a/src/components/ProjectViewer/ProjectViewer.js b/src/components/ProjectViewer/ProjectViewer.js
index 194891e05..e34b44d2a 100644
--- a/src/components/ProjectViewer/ProjectViewer.js
+++ b/src/components/ProjectViewer/ProjectViewer.js
@@ -1,15 +1,15 @@
 /* eslint-disable react-hooks/exhaustive-deps */
-import React, { useEffect } from 'react';
-import { useSelector, useDispatch } from 'react-redux'
-import { useProject } from '../Editor/Hooks/useProject'
-import PythonRunner from '../Editor/Runners/PythonRunner/PythonRunner'
-import { triggerCodeRun } from '../Editor/EditorSlice'
-import RunnerControls from '../RunButton/RunnerControls';
-import { useParams } from 'react-router-dom';
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { useProject } from "../Editor/Hooks/useProject";
+import PythonRunner from "../Editor/Runners/PythonRunner/PythonRunner";
+import { triggerCodeRun } from "../Editor/EditorSlice";
+import RunnerControls from "../RunButton/RunnerControls";
+import { useParams } from "react-router-dom";
 
 const ProjectViewer = () => {
   const loading = useSelector((state) => state.editor.loading);
-  const { identifier } = useParams()
+  const { identifier } = useParams();
   const dispatch = useDispatch();
   useProject(identifier);
 
@@ -17,10 +17,9 @@ const ProjectViewer = () => {
     dispatch(triggerCodeRun());
   }, []);
 
-
-  return loading === 'success' ? (
+  return loading === "success" ? (
     <>
-      <div className='main-container'>
+      <div className="main-container">
         <h1>Shared project</h1>
         <RunnerControls />
         <div>
@@ -28,7 +27,9 @@ const ProjectViewer = () => {
         </div>
       </div>
     </>
-  ) : <p>Loading</p>;
+  ) : (
+    <p>Loading</p>
+  );
 };
 
 export default ProjectViewer;
diff --git a/src/components/RunButton/RunBar.js b/src/components/RunButton/RunBar.js
index 84e4d2923..85ec8d830 100644
--- a/src/components/RunButton/RunBar.js
+++ b/src/components/RunButton/RunBar.js
@@ -1,14 +1,14 @@
 import React from "react";
 import RunnerControls from "./RunnerControls";
 
-import './RunBar.scss';
+import "./RunBar.scss";
 
 const RunBar = () => {
   return (
-    <div className='run-bar'>
+    <div className="run-bar">
       <RunnerControls />
     </div>
-  )
-}
+  );
+};
 
-export default RunBar
+export default RunBar;
diff --git a/src/components/RunButton/RunBar.test.js b/src/components/RunButton/RunBar.test.js
index 783ee492e..9fc053717 100644
--- a/src/components/RunButton/RunBar.test.js
+++ b/src/components/RunButton/RunBar.test.js
@@ -1,19 +1,23 @@
 import React from "react";
-import { render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import RunBar from "./RunBar";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 const initialState = {
   editor: {
-    codeRunTriggered: false
-  }
-}
-const store = mockStore(initialState)
+    codeRunTriggered: false,
+  },
+};
+const store = mockStore(initialState);
 
 test("Renders", () => {
-    render(<Provider store={store}><RunBar/></Provider>)
-    expect(screen.queryByRole('button')).toHaveTextContent('runButton.run')
-})
+  render(
+    <Provider store={store}>
+      <RunBar />
+    </Provider>,
+  );
+  expect(screen.queryByRole("button")).toHaveTextContent("runButton.run");
+});
diff --git a/src/components/RunButton/RunButton.js b/src/components/RunButton/RunButton.js
index bdacec73c..06dd975b8 100644
--- a/src/components/RunButton/RunButton.js
+++ b/src/components/RunButton/RunButton.js
@@ -1,23 +1,26 @@
-import Button from '../Button/Button'
+import Button from "../Button/Button";
 
-import React from 'react';
-import { useDispatch } from 'react-redux'
-import { triggerCodeRun } from '../Editor/EditorSlice'
+import React from "react";
+import { useDispatch } from "react-redux";
+import { triggerCodeRun } from "../Editor/EditorSlice";
 
 const RunButton = (props) => {
   const dispatch = useDispatch();
 
   const onClickRun = () => {
     if (window.plausible) {
-      window.plausible('Run button')
+      window.plausible("Run button");
     }
     dispatch(triggerCodeRun());
-  }
+  };
 
   return (
-    <Button className={"btn--primary btn--run"} onClickHandler={onClickRun} {...props} />
-  )
+    <Button
+      className={"btn--primary btn--run"}
+      onClickHandler={onClickRun}
+      {...props}
+    />
+  );
 };
 
 export default RunButton;
-
diff --git a/src/components/RunButton/RunButton.test.js b/src/components/RunButton/RunButton.test.js
index f37e8730a..02c7aecec 100644
--- a/src/components/RunButton/RunButton.test.js
+++ b/src/components/RunButton/RunButton.test.js
@@ -1,14 +1,18 @@
 import React from "react";
-import { render, screen } from "@testing-library/react"
-import { Provider } from 'react-redux';
-import configureStore from 'redux-mock-store';
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
 import RunButton from "./RunButton";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
-const store = mockStore({})
+const middlewares = [];
+const mockStore = configureStore(middlewares);
+const store = mockStore({});
 
 test("Run button renders with expected button text", () => {
-    render(<Provider store={store}><RunButton buttonText="Run Code" /></Provider>)
-    expect(screen.queryByRole('button')).toHaveTextContent('Run Code')
-})
+  render(
+    <Provider store={store}>
+      <RunButton buttonText="Run Code" />
+    </Provider>,
+  );
+  expect(screen.queryByRole("button")).toHaveTextContent("Run Code");
+});
diff --git a/src/components/RunButton/RunnerControls.js b/src/components/RunButton/RunnerControls.js
index b2493096a..a20efde69 100644
--- a/src/components/RunButton/RunnerControls.js
+++ b/src/components/RunButton/RunnerControls.js
@@ -1,21 +1,30 @@
-import React from 'react';
+import React from "react";
 import RunButton from "./RunButton";
 import StopButton from "./StopButton";
-import { useSelector } from 'react-redux';
-import { RunIcon, StopIcon } from '../../Icons';
-import { useTranslation } from 'react-i18next';
+import { useSelector } from "react-redux";
+import { RunIcon, StopIcon } from "../../Icons";
+import { useTranslation } from "react-i18next";
 
 const RunnerControls = () => {
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered);
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
   const drawTriggered = useSelector((state) => state.editor.drawTriggered);
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
-  return (
-    (codeRunTriggered || drawTriggered) ?
-      <StopButton buttonText={t('runButton.stop')} ButtonIcon={StopIcon} buttonIconPosition = 'right' />
-    :
-      <RunButton buttonText={t('runButton.run')} ButtonIcon={RunIcon} buttonIconPosition = 'right' />
-  )
-}
+  return codeRunTriggered || drawTriggered ? (
+    <StopButton
+      buttonText={t("runButton.stop")}
+      ButtonIcon={StopIcon}
+      buttonIconPosition="right"
+    />
+  ) : (
+    <RunButton
+      buttonText={t("runButton.run")}
+      ButtonIcon={RunIcon}
+      buttonIconPosition="right"
+    />
+  );
+};
 
 export default RunnerControls;
diff --git a/src/components/RunButton/RunnerControls.test.js b/src/components/RunButton/RunnerControls.test.js
index 3715bf46b..8575b862d 100644
--- a/src/components/RunButton/RunnerControls.test.js
+++ b/src/components/RunButton/RunnerControls.test.js
@@ -1,34 +1,42 @@
 import React from "react";
 import { render, screen } from "@testing-library/react";
-import { Provider } from 'react-redux';
+import { Provider } from "react-redux";
 import RunnerControls from "./RunnerControls";
 import configureStore from "redux-mock-store";
 
-const middlewares = []
-const mockStore = configureStore(middlewares)
+const middlewares = [];
+const mockStore = configureStore(middlewares);
 
 test("Run button shows when code is not running", () => {
-    const initialState = {
-        editor: {
-            codeRunTriggered: false,
-            codeRunStopped: false
-        }
-    }
-    const store = mockStore(initialState)
-    render(<Provider store={store}><RunnerControls /></Provider>);
-    const runButton = screen.queryByText('runButton.run');
-    expect(runButton).toBeInTheDocument()
-})
+  const initialState = {
+    editor: {
+      codeRunTriggered: false,
+      codeRunStopped: false,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <RunnerControls />
+    </Provider>,
+  );
+  const runButton = screen.queryByText("runButton.run");
+  expect(runButton).toBeInTheDocument();
+});
 
 test("Stop button shows when code is running", () => {
-    const initialState = {
-        editor: {
-            codeRunTriggered: true,
-            codeRunStopped: false
-        }
-    }
-    const store = mockStore(initialState)
-    render(<Provider store={store}><RunnerControls /></Provider>);
-    const stopButton = screen.queryByText('runButton.stop');
-    expect(stopButton).toBeInTheDocument()
-})
+  const initialState = {
+    editor: {
+      codeRunTriggered: true,
+      codeRunStopped: false,
+    },
+  };
+  const store = mockStore(initialState);
+  render(
+    <Provider store={store}>
+      <RunnerControls />
+    </Provider>,
+  );
+  const stopButton = screen.queryByText("runButton.stop");
+  expect(stopButton).toBeInTheDocument();
+});
diff --git a/src/components/RunButton/StopButton.js b/src/components/RunButton/StopButton.js
index e3be6a05b..fbd55b157 100644
--- a/src/components/RunButton/StopButton.js
+++ b/src/components/RunButton/StopButton.js
@@ -1,36 +1,43 @@
-import Button from '../Button/Button'
-import React, { useEffect, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux'
-import { stopCodeRun, stopDraw } from '../Editor/EditorSlice'
-import { useTranslation } from 'react-i18next'
+import Button from "../Button/Button";
+import React, { useEffect, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { stopCodeRun, stopDraw } from "../Editor/EditorSlice";
+import { useTranslation } from "react-i18next";
 
 const StopButton = (props) => {
-
   const codeRunStopped = useSelector((state) => state.editor.codeRunStopped);
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered);
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
   const dispatch = useDispatch();
-  const { t } = useTranslation()
+  const { t } = useTranslation();
 
   const onClickStop = () => {
     if (codeRunTriggered) {
       dispatch(stopCodeRun());
     }
     dispatch(stopDraw());
-  }
+  };
 
-  const stop = <Button className='btn--primary btn--stop' onClickHandler={onClickStop} {...props} />
-  const [button, setButton] = useState(stop)
+  const stop = (
+    <Button
+      className="btn--primary btn--stop"
+      onClickHandler={onClickStop}
+      {...props}
+    />
+  );
+  const [button, setButton] = useState(stop);
 
   useEffect(() => {
     if (codeRunStopped) {
-      const stopping = <Button buttonText={t('runButton.stopping')} disabled />
-      setTimeout(() => { setButton(stopping) }, 100);
+      const stopping = <Button buttonText={t("runButton.stopping")} disabled />;
+      setTimeout(() => {
+        setButton(stopping);
+      }, 100);
     }
   }, [codeRunStopped, t]);
 
-  return (
-    button
-  )
+  return button;
 };
 
 export default StopButton;
diff --git a/src/components/RunButton/StopButton.test.js b/src/components/RunButton/StopButton.test.js
index c2c4e2630..32dc00128 100644
--- a/src/components/RunButton/StopButton.test.js
+++ b/src/components/RunButton/StopButton.test.js
@@ -1,49 +1,51 @@
-import React from "react"
-import { act, render, fireEvent } from "@testing-library/react"
-import { Provider } from 'react-redux'
-import StopButton from "./StopButton"
-import store from '../../app/store'
-import { codeRunHandled, triggerCodeRun } from '../Editor/EditorSlice'
+import React from "react";
+import { act, render, fireEvent } from "@testing-library/react";
+import { Provider } from "react-redux";
+import StopButton from "./StopButton";
+import store from "../../app/store";
+import { codeRunHandled, triggerCodeRun } from "../Editor/EditorSlice";
 
 beforeEach(() => {
-  jest.useFakeTimers()
-})
+  jest.useFakeTimers();
+});
 
 afterEach(() => {
-  jest.useRealTimers()
-})
+  jest.useRealTimers();
+});
 
 test("Clicking stop button sets codeRunStopped to true", () => {
-  store.dispatch(codeRunHandled())
-  store.dispatch(triggerCodeRun())
+  store.dispatch(codeRunHandled());
+  store.dispatch(triggerCodeRun());
 
   const component = render(
     <Provider store={store}>
-        <StopButton buttonText="Stop Code" />
-    </Provider>
-  )
+      <StopButton buttonText="Stop Code" />
+    </Provider>,
+  );
 
-  const stopButton = component.getByRole('button')
-  fireEvent.click(stopButton)
+  const stopButton = component.getByRole("button");
+  fireEvent.click(stopButton);
 
-  expect(store.getState().editor.codeRunStopped).toEqual(true)
-})
+  expect(store.getState().editor.codeRunStopped).toEqual(true);
+});
 
 test("Clicking stop button changes it to 'Stopping...' after a time out", () => {
-  store.dispatch(codeRunHandled())
-  store.dispatch(triggerCodeRun())
+  store.dispatch(codeRunHandled());
+  store.dispatch(triggerCodeRun());
 
   const component = render(
     <Provider store={store}>
       <StopButton buttonText="Stop Code" />
-    </Provider>
-  )
-  const stopButton = component.getByRole('button')
-  expect(stopButton.textContent).toEqual("Stop Code")
-
-  fireEvent.click(stopButton)
-  expect(stopButton.textContent).toEqual("Stop Code")
-
-  act(() => { jest.runAllTimers(); } )
-  expect(stopButton.textContent).toEqual("runButton.stopping")
-})
+    </Provider>,
+  );
+  const stopButton = component.getByRole("button");
+  expect(stopButton.textContent).toEqual("Stop Code");
+
+  fireEvent.click(stopButton);
+  expect(stopButton.textContent).toEqual("Stop Code");
+
+  act(() => {
+    jest.runAllTimers();
+  });
+  expect(stopButton.textContent).toEqual("runButton.stopping");
+});
diff --git a/src/components/SilentRenew.js b/src/components/SilentRenew.js
index a9d2ef5a8..3f3c14de2 100644
--- a/src/components/SilentRenew.js
+++ b/src/components/SilentRenew.js
@@ -1,15 +1,15 @@
-import { useEffect } from 'react';
+import { useEffect } from "react";
 import { connect } from "react-redux";
 import { processSilentRenew } from "redux-oidc";
 
 const SilentRenew = () => {
   useEffect(() => {
-    console.log('*************************************');
-    console.log('silently renewing');
-    processSilentRenew()
+    console.log("*************************************");
+    console.log("silently renewing");
+    processSilentRenew();
   }, []);
 
-  return (null);
-}
+  return null;
+};
 
 export default connect()(SilentRenew);
diff --git a/src/components/ThemeToggle/ThemeToggle.js b/src/components/ThemeToggle/ThemeToggle.js
index 4f80b608f..ab1b0820e 100644
--- a/src/components/ThemeToggle/ThemeToggle.js
+++ b/src/components/ThemeToggle/ThemeToggle.js
@@ -1,42 +1,59 @@
-import React from 'react';
-import { useCookies } from 'react-cookie';
-import { useTranslation } from 'react-i18next';
+import React from "react";
+import { useCookies } from "react-cookie";
+import { useTranslation } from "react-i18next";
 
-import './ThemeToggle.scss'
-import { MoonIcon, SunIcon } from '../../Icons';
+import "./ThemeToggle.scss";
+import { MoonIcon, SunIcon } from "../../Icons";
 
-const COOKIE_PATHS = ['/', '/projects', '/python']
+const COOKIE_PATHS = ["/", "/projects", "/python"];
 
 const ThemeToggle = () => {
-  const [ cookies, setCookie, removeCookie ] = useCookies(['theme'])
-  const isDarkMode = cookies.theme==="dark" || (!cookies.theme && window.matchMedia("(prefers-color-scheme:dark)").matches)
-  const { t } = useTranslation()
+  const [cookies, setCookie, removeCookie] = useCookies(["theme"]);
+  const isDarkMode =
+    cookies.theme === "dark" ||
+    (!cookies.theme &&
+      window.matchMedia("(prefers-color-scheme:dark)").matches);
+  const { t } = useTranslation();
 
   const setTheme = (theme) => {
     if (cookies.theme) {
       COOKIE_PATHS.forEach((path) => {
-        removeCookie('theme', {path})
-      })
+        removeCookie("theme", { path });
+      });
     }
-    setCookie('theme', theme, { path: '/' })
-  }
+    setCookie("theme", theme, { path: "/" });
+  };
 
   return (
-    <div className='theme-toggle'>
-      <div className='theme-btn theme-btn--light' onClick={() => setTheme('light')}>
-        <button className={`theme-btn__icon theme-btn__icon--light ${!isDarkMode ? 'theme-btn__icon--active' : null}`}>
+    <div className="theme-toggle">
+      <div
+        className="theme-btn theme-btn--light"
+        onClick={() => setTheme("light")}
+      >
+        <button
+          className={`theme-btn__icon theme-btn__icon--light ${
+            !isDarkMode ? "theme-btn__icon--active" : null
+          }`}
+        >
           <SunIcon />
         </button>
-        <p>{t('header.settingsMenu.themeOptions.light')}</p>
+        <p>{t("header.settingsMenu.themeOptions.light")}</p>
       </div>
-      <div className='theme-btn theme-btn--dark' onClick={() => setTheme('dark')}>
-        <button className={`theme-btn__icon theme-btn__icon--dark ${isDarkMode ? 'theme-btn__icon--active' : null}`}>
+      <div
+        className="theme-btn theme-btn--dark"
+        onClick={() => setTheme("dark")}
+      >
+        <button
+          className={`theme-btn__icon theme-btn__icon--dark ${
+            isDarkMode ? "theme-btn__icon--active" : null
+          }`}
+        >
           <MoonIcon />
         </button>
-        <p>{t('header.settingsMenu.themeOptions.dark')}</p>
+        <p>{t("header.settingsMenu.themeOptions.dark")}</p>
       </div>
     </div>
-  )
-}
+  );
+};
 
-export default ThemeToggle
+export default ThemeToggle;
diff --git a/src/components/ThemeToggle/ThemeToggle.test.js b/src/components/ThemeToggle/ThemeToggle.test.js
index 231b07264..7500624dc 100644
--- a/src/components/ThemeToggle/ThemeToggle.test.js
+++ b/src/components/ThemeToggle/ThemeToggle.test.js
@@ -1,7 +1,7 @@
 import React from "react";
-import { act, render, fireEvent } from "@testing-library/react"
+import { act, render, fireEvent } from "@testing-library/react";
 import ThemeToggle from "./ThemeToggle";
-import { Cookies, CookiesProvider } from 'react-cookie';
+import { Cookies, CookiesProvider } from "react-cookie";
 
 describe("When default theme is light mode and cookie unset", () => {
   let cookies;
@@ -17,29 +17,31 @@ describe("When default theme is light mode and cookie unset", () => {
       addEventListener: jest.fn(),
       removeEventListener: jest.fn(),
       dispatchEvent: jest.fn(),
-    })
+    });
     cookies = new Cookies();
     toggleContainer = render(
       <CookiesProvider cookies={cookies}>
         <ThemeToggle />
-      </CookiesProvider>
-    )
-  })
+      </CookiesProvider>,
+    );
+  });
 
-  test('Cookie remains unset after render', () => {
-    expect(cookies.cookies.theme).toBeUndefined()
-  })
+  test("Cookie remains unset after render", () => {
+    expect(cookies.cookies.theme).toBeUndefined();
+  });
 
-  test('Sets cookie to dark when button clicked', async () => {
-    const button = toggleContainer.getByText("header.settingsMenu.themeOptions.dark").parentElement
-    fireEvent.click(button)
-    expect(cookies.cookies.theme).toBe("dark")
-  })
+  test("Sets cookie to dark when button clicked", async () => {
+    const button = toggleContainer.getByText(
+      "header.settingsMenu.themeOptions.dark",
+    ).parentElement;
+    fireEvent.click(button);
+    expect(cookies.cookies.theme).toBe("dark");
+  });
 
   afterEach(() => {
-    cookies.remove("theme")
-  })
-})
+    cookies.remove("theme");
+  });
+});
 
 describe("When default theme is dark mode and cookie unset", () => {
   let cookies;
@@ -55,56 +57,62 @@ describe("When default theme is dark mode and cookie unset", () => {
       addEventListener: jest.fn(),
       removeEventListener: jest.fn(),
       dispatchEvent: jest.fn(),
-    })
+    });
     cookies = new Cookies();
     toggleContainer = render(
       <CookiesProvider cookies={cookies}>
         <ThemeToggle />
-      </CookiesProvider>
-    )
-  })
+      </CookiesProvider>,
+    );
+  });
 
-  test('Cookie remains unset after render', () => {
-    expect(cookies.cookies.theme).toBeUndefined()
-  })
+  test("Cookie remains unset after render", () => {
+    expect(cookies.cookies.theme).toBeUndefined();
+  });
 
-  test('Sets cookie to light when button clicked', async () => {
-    const button = toggleContainer.getByText("header.settingsMenu.themeOptions.light").parentElement
-    fireEvent.click(button)
-    expect(cookies.cookies.theme).toBe("light")
-  })
+  test("Sets cookie to light when button clicked", async () => {
+    const button = toggleContainer.getByText(
+      "header.settingsMenu.themeOptions.light",
+    ).parentElement;
+    fireEvent.click(button);
+    expect(cookies.cookies.theme).toBe("light");
+  });
 
   afterEach(() => {
-    cookies.remove("theme")
-  })
-})
+    cookies.remove("theme");
+  });
+});
 
-test('Cookie set to dark intially changes to light when button clicked', () => {
+test("Cookie set to dark intially changes to light when button clicked", () => {
   var cookies = new Cookies();
-  cookies.set("theme", "dark")
+  cookies.set("theme", "dark");
   const toggleContainer = render(
     <CookiesProvider cookies={cookies}>
       <ThemeToggle />
-    </CookiesProvider>
-  )
-  const button = toggleContainer.getByText("header.settingsMenu.themeOptions.light").parentElement
+    </CookiesProvider>,
+  );
+  const button = toggleContainer.getByText(
+    "header.settingsMenu.themeOptions.light",
+  ).parentElement;
   act(() => {
-    fireEvent.click(button)
-  })
-  expect(cookies.cookies.theme).toBe("light")
-})
+    fireEvent.click(button);
+  });
+  expect(cookies.cookies.theme).toBe("light");
+});
 
-test('Cookie set to light intially changes to dark when button clicked', () => {
+test("Cookie set to light intially changes to dark when button clicked", () => {
   var cookies = new Cookies();
-  cookies.set("theme", "light")
+  cookies.set("theme", "light");
   var toggleContainer = render(
     <CookiesProvider cookies={cookies}>
       <ThemeToggle />
-    </CookiesProvider>
-  )
-  const button = toggleContainer.getByText("header.settingsMenu.themeOptions.dark").parentElement
+    </CookiesProvider>,
+  );
+  const button = toggleContainer.getByText(
+    "header.settingsMenu.themeOptions.dark",
+  ).parentElement;
   act(() => {
-    fireEvent.click(button)
-  })
-  expect(cookies.cookies.theme).toBe("dark")
-})
+    fireEvent.click(button);
+  });
+  expect(cookies.cookies.theme).toBe("dark");
+});
diff --git a/src/components/WebComponent/Project/WebComponentProject.js b/src/components/WebComponent/Project/WebComponentProject.js
index d397e0500..eb421e1c2 100644
--- a/src/components/WebComponent/Project/WebComponentProject.js
+++ b/src/components/WebComponent/Project/WebComponentProject.js
@@ -1,39 +1,42 @@
-import React, { useEffect } from 'react';
-import { useDispatch, useSelector } from 'react-redux'
-import { useCookies } from 'react-cookie';
-import Style from 'style-it';
-import internalStyles from '../InternalStyles.scss';
-import externalStyles from '../ExternalStyles.scss';
+import React, { useEffect } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { useCookies } from "react-cookie";
+import Style from "style-it";
+import internalStyles from "../InternalStyles.scss";
+import externalStyles from "../ExternalStyles.scss";
 
-import Project from '../../Editor/Project/Project';
-import { defaultMZCriteria } from '../../AstroPiModel/DefaultMZCriteria'
-import Sk from 'skulpt';
-import store from '../../../app/store';
-import { setIsSplitView } from '../../Editor/EditorSlice';
+import Project from "../../Editor/Project/Project";
+import { defaultMZCriteria } from "../../AstroPiModel/DefaultMZCriteria";
+import Sk from "skulpt";
+import store from "../../../app/store";
+import { setIsSplitView } from "../../Editor/EditorSlice";
 
 const WebComponentProject = () => {
   const project = useSelector((state) => state.editor.project);
-  const codeRunTriggered = useSelector((state) => state.editor.codeRunTriggered)
-  const [cookies] = useCookies(['theme', 'fontSize'])
-  const defaultTheme = window.matchMedia("(prefers-color-scheme:dark)").matches ? "dark" : "light"
+  const codeRunTriggered = useSelector(
+    (state) => state.editor.codeRunTriggered,
+  );
+  const [cookies] = useCookies(["theme", "fontSize"]);
+  const defaultTheme = window.matchMedia("(prefers-color-scheme:dark)").matches
+    ? "dark"
+    : "light";
   const [timeoutId, setTimeoutId] = React.useState(null);
-  const webComponent = document.querySelector('editor-wc')
+  const webComponent = document.querySelector("editor-wc");
   const [codeHasRun, setCodeHasRun] = React.useState(false);
-  const dispatch = useDispatch()
-  dispatch(setIsSplitView(false))
+  const dispatch = useDispatch();
+  dispatch(setIsSplitView(false));
 
   useEffect(() => {
-    setCodeHasRun(false)
-    if(timeoutId) clearTimeout(timeoutId);
-    const id = setTimeout(
-      function() {
-        const customEvent = new CustomEvent("codeChanged", {
-          bubbles: true,
-          cancelable: false,
-          composed: true
-        });
-        webComponent.dispatchEvent(customEvent)
-      }, 2000);
+    setCodeHasRun(false);
+    if (timeoutId) clearTimeout(timeoutId);
+    const id = setTimeout(function () {
+      const customEvent = new CustomEvent("codeChanged", {
+        bubbles: true,
+        cancelable: false,
+        composed: true,
+      });
+      webComponent.dispatchEvent(customEvent);
+    }, 2000);
     setTimeoutId(id);
   }, [project]);
 
@@ -42,38 +45,44 @@ const WebComponentProject = () => {
       const runStartedEvent = new CustomEvent("runStarted", {
         bubbles: true,
         cancelable: false,
-        composed: true
+        composed: true,
       });
-      webComponent.dispatchEvent(runStartedEvent)
-      setCodeHasRun(true)
+      webComponent.dispatchEvent(runStartedEvent);
+      setCodeHasRun(true);
     } else if (codeHasRun) {
       const state = store.getState();
-      const mz_criteria = Sk.sense_hat ? Sk.sense_hat.mz_criteria : {...defaultMZCriteria}
+      const mz_criteria = Sk.sense_hat
+        ? Sk.sense_hat.mz_criteria
+        : { ...defaultMZCriteria };
       const runCompletedEvent = new CustomEvent("runCompleted", {
         bubbles: true,
         cancelable: false,
         composed: true,
         detail: {
           isErrorFree: state.editor.error === "",
-          ...mz_criteria
-        }
+          ...mz_criteria,
+        },
       });
-      webComponent.dispatchEvent(runCompletedEvent)
+      webComponent.dispatchEvent(runCompletedEvent);
     }
-
-  }, [codeRunTriggered] )
+  }, [codeRunTriggered]);
 
   return (
     <>
       <style>{externalStyles.toString()}</style>
       <Style>
         {internalStyles}
-        <div id='wc' className = {`--${cookies.theme || defaultTheme} font-size-${cookies.fontSize || 'small'}`}>
-          <Project forWebComponent={true}/>
+        <div
+          id="wc"
+          className={`--${cookies.theme || defaultTheme} font-size-${
+            cookies.fontSize || "small"
+          }`}
+        >
+          <Project forWebComponent={true} />
         </div>
       </Style>
     </>
   );
-}
+};
 
-export default WebComponentProject
+export default WebComponentProject;
diff --git a/src/components/WebComponent/WebComponentLoader/WebComponentLoader.js b/src/components/WebComponent/WebComponentLoader/WebComponentLoader.js
index a35efdc71..14a17ec27 100644
--- a/src/components/WebComponent/WebComponentLoader/WebComponentLoader.js
+++ b/src/components/WebComponent/WebComponentLoader/WebComponentLoader.js
@@ -1,31 +1,31 @@
-import React, { useEffect } from 'react';
-import { useSelector, useDispatch } from 'react-redux'
-import { setProject, setSenseHatAlwaysEnabled } from '../../Editor/EditorSlice';
-import WebComponentProject from '../Project/WebComponentProject';
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { setProject, setSenseHatAlwaysEnabled } from "../../Editor/EditorSlice";
+import WebComponentProject from "../Project/WebComponentProject";
 
 const ProjectComponentLoader = (props) => {
   const loading = useSelector((state) => state.editor.loading);
   const { code, sense_hat_always_enabled } = props;
-  const dispatch = useDispatch()
+  const dispatch = useDispatch();
 
   useEffect(() => {
     const proj = {
-      type: 'python',
-      components: [{ name: 'main', extension: 'py', content: code }]
-    }
-    dispatch(setSenseHatAlwaysEnabled(typeof sense_hat_always_enabled !== 'undefined'))
-    dispatch(setProject(proj))
+      type: "python",
+      components: [{ name: "main", extension: "py", content: code }],
+    };
+    dispatch(
+      setSenseHatAlwaysEnabled(typeof sense_hat_always_enabled !== "undefined"),
+    );
+    dispatch(setProject(proj));
   }, [code, sense_hat_always_enabled, dispatch]);
 
-
-
-  return loading === 'success' ? (
+  return loading === "success" ? (
     <>
       <WebComponentProject />
     </>
   ) : (
     <>
-    <p>Loading</p>
+      <p>Loading</p>
     </>
   );
 };
diff --git a/src/components/WebComponent/WebComponentSlice.js b/src/components/WebComponent/WebComponentSlice.js
index e33fb1190..ef8934aad 100644
--- a/src/components/WebComponent/WebComponentSlice.js
+++ b/src/components/WebComponent/WebComponentSlice.js
@@ -1,20 +1,18 @@
-import { createSlice } from '@reduxjs/toolkit'
+import { createSlice } from "@reduxjs/toolkit";
 
 export const WebComponentSlice = createSlice({
-  name: 'component',
+  name: "component",
   initialState: {
-    project: {}
+    project: {},
   },
 
   reducers: {
     setProject: (state, action) => {
       state.project = action.payload;
-    }
-  }
-})
+    },
+  },
+});
 
-export const {
-  setProject,
-} = WebComponentSlice.actions
+export const { setProject } = WebComponentSlice.actions;
 
-export default WebComponentSlice.reducer
+export default WebComponentSlice.reducer;
diff --git a/src/hooks/useUserFont.js b/src/hooks/useUserFont.js
index 2ef35917f..30fcadd81 100644
--- a/src/hooks/useUserFont.js
+++ b/src/hooks/useUserFont.js
@@ -1,10 +1,10 @@
-import { useCookies } from 'react-cookie';
+import { useCookies } from "react-cookie";
 
-const fontScaleFactors = {'small': 1, 'medium': 1.44, 'large': 2.074}
+const fontScaleFactors = { small: 1, medium: 1.44, large: 2.074 };
 
 export const useUserFont = (defaultScale = 1) => {
-  const [cookies] = useCookies(['fontSize'])
-  const scale = fontScaleFactors[cookies.fontSize] || defaultScale
+  const [cookies] = useCookies(["fontSize"]);
+  const scale = fontScaleFactors[cookies.fontSize] || defaultScale;
 
-  return scale
-}
\ No newline at end of file
+  return scale;
+};
diff --git a/src/i18n.js b/src/i18n.js
index 1fcd4fe68..ed52f6867 100644
--- a/src/i18n.js
+++ b/src/i18n.js
@@ -155,10 +155,11 @@ i18n
             newFileModal: {
               cancel: "Cancel",
               heading: "Add a new file to your project",
-              helpText: "Remember to add the file extension at the end of your file name, for example, {{examples}}",
-              helpTextExample:{
+              helpText:
+                "Remember to add the file extension at the end of your file name, for example, {{examples}}",
+              helpTextExample: {
                 html: "'file.html' or 'file.css'",
-                python: "'file.py'"
+                python: "'file.py'",
               },
               inputLabel: "Name your file",
               addFile: "Add file",
@@ -236,7 +237,7 @@ i18n
               "Log in to your Raspberry Pi account to save your work, and you'll be able to access and edit your project whenever you need to.",
           },
           modals: {
-            close: 'Close'
+            close: "Close",
           },
           notifications: {
             close: "close",
@@ -339,7 +340,7 @@ i18n
             },
             updated: "Edited",
             python_type: "Python",
-            html_type: "HTML"
+            html_type: "HTML",
           },
           runButton: {
             run: "Run",
@@ -347,7 +348,7 @@ i18n
             stopping: "Stopping...",
           },
           runners: {
-            HtmlOutput: 'HTML Output Preview'
+            HtmlOutput: "HTML Output Preview",
           },
           sideMenu: {
             collapse: "Collapse file pane",
diff --git a/src/index.js b/src/index.js
index e7075b02b..080c13c23 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,22 +1,29 @@
-import React from 'react';
-import { createRoot } from 'react-dom/client';
+import React from "react";
+import { createRoot } from "react-dom/client";
 
-import { SentryLink } from 'apollo-link-sentry';
+import { SentryLink } from "apollo-link-sentry";
 
-import './index.css';
-import './sentry';
-import App from './App';
-import './i18n';
-import { ApolloLink, ApolloProvider, ApolloClient, createHttpLink } from '@apollo/client';
-import { setContext } from '@apollo/client/link/context';
-import { OidcProvider } from 'redux-oidc';
-import { Provider } from 'react-redux';
-import store from './app/store';
-import userManager from './utils/userManager';
-import apolloCache from './utils/apolloCache';
-import { CookiesProvider } from 'react-cookie';
+import "./index.css";
+import "./sentry";
+import App from "./App";
+import "./i18n";
+import {
+  ApolloLink,
+  ApolloProvider,
+  ApolloClient,
+  createHttpLink,
+} from "@apollo/client";
+import { setContext } from "@apollo/client/link/context";
+import { OidcProvider } from "redux-oidc";
+import { Provider } from "react-redux";
+import store from "./app/store";
+import userManager from "./utils/userManager";
+import apolloCache from "./utils/apolloCache";
+import { CookiesProvider } from "react-cookie";
 
-const apiEndpointLink = createHttpLink({ uri: process.env.REACT_APP_API_ENDPOINT + '/graphql' });
+const apiEndpointLink = createHttpLink({
+  uri: process.env.REACT_APP_API_ENDPOINT + "/graphql",
+});
 const apiAuthLink = setContext((_, { headers }) => {
   // TODO: ... better way to handle state in Apollo
   const user = store.getState().auth.user;
@@ -26,27 +33,23 @@ const apiAuthLink = setContext((_, { headers }) => {
     headers: {
       ...headers,
       Authorization: user ? user.access_token : "",
-    }
-  }
+    },
+  };
 });
 
 const client = new ApolloClient({
-  link: ApolloLink.from([
-    new SentryLink(),
-    apiAuthLink,
-    apiEndpointLink
-  ]),
-  cache: apolloCache
+  link: ApolloLink.from([new SentryLink(), apiAuthLink, apiEndpointLink]),
+  cache: apolloCache,
 });
 
-const supportsContainerQueries = 'container' in document.documentElement.style
+const supportsContainerQueries = "container" in document.documentElement.style;
 if (!supportsContainerQueries) {
   // eslint-disable-next-line no-unused-expressions
-  import('container-query-polyfill')
+  import("container-query-polyfill");
 }
 
-const div = document.getElementById('root')
-const root = createRoot(div)
+const div = document.getElementById("root");
+const root = createRoot(div);
 root.render(
   <React.StrictMode>
     <CookiesProvider>
@@ -58,7 +61,7 @@ root.render(
         </Provider>
       </ApolloProvider>
     </CookiesProvider>
-  </React.StrictMode>
+  </React.StrictMode>,
 );
 
 // If you want to start measuring performance in your app, pass a function
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
index 5253d3ad9..9ecd33f9c 100644
--- a/src/reportWebVitals.js
+++ b/src/reportWebVitals.js
@@ -1,6 +1,6 @@
-const reportWebVitals = onPerfEntry => {
+const reportWebVitals = (onPerfEntry) => {
   if (onPerfEntry && onPerfEntry instanceof Function) {
-    import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+    import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
       getCLS(onPerfEntry);
       getFID(onPerfEntry);
       getFCP(onPerfEntry);
diff --git a/src/sentry.js b/src/sentry.js
index 1e92e24dc..04c51570c 100644
--- a/src/sentry.js
+++ b/src/sentry.js
@@ -1,9 +1,14 @@
-import React from 'react';
-import { useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from "react-router-dom";
+import React from "react";
+import {
+  useLocation,
+  useNavigationType,
+  createRoutesFromChildren,
+  matchRoutes,
+} from "react-router-dom";
 
-import * as Sentry from '@sentry/react'
-import { BrowserTracing } from '@sentry/tracing';
-import { excludeGraphQLFetch } from 'apollo-link-sentry';
+import * as Sentry from "@sentry/react";
+import { BrowserTracing } from "@sentry/tracing";
+import { excludeGraphQLFetch } from "apollo-link-sentry";
 
 Sentry.init({
   dsn: process.env.REACT_APP_SENTRY_DSN,
@@ -22,4 +27,4 @@ Sentry.init({
   environment: process.env.REACT_APP_SENTRY_ENV,
   beforeBreadcrumb: excludeGraphQLFetch,
   tracesSampleRate: 0.8,
-})
+});
diff --git a/src/settings.js b/src/settings.js
index 41fb3d20d..e20dedc90 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -1,8 +1,10 @@
-import { createContext } from "react"
+import { createContext } from "react";
 
 const SettingsContext = createContext({
-    theme: window.matchMedia("(prefers-color-scheme:dark)").matches ? "dark" : "light",
-    fontSize: 'small'
-})
+  theme: window.matchMedia("(prefers-color-scheme:dark)").matches
+    ? "dark"
+    : "light",
+  fontSize: "small",
+});
 
-export { SettingsContext }
\ No newline at end of file
+export { SettingsContext };
diff --git a/src/utils/Geometry.js b/src/utils/Geometry.js
index 5529337d8..e5ac51afa 100644
--- a/src/utils/Geometry.js
+++ b/src/utils/Geometry.js
@@ -1,28 +1,26 @@
 var Geometry = {
-  _Eps: 1e-5
+  _Eps: 1e-5,
 };
 
-
-Geometry.Vector = function(x, y, z) {
+Geometry.Vector = function (x, y, z) {
   this.x = x;
   this.y = y;
   this.z = z;
-}
+};
 
 Geometry.Vector.prototype = {
-  length: function() {
+  length: function () {
     return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
   },
-  normalize: function() {
+  normalize: function () {
     var length = this.length();
-    if (length <= Geometry._Eps)
-      return;
+    if (length <= Geometry._Eps) return;
 
     this.x /= length;
     this.y /= length;
     this.z /= length;
-  }
-}
+  },
+};
 
 /**
  * Transposes a 2-dim Array
@@ -31,38 +29,42 @@ Geometry.Vector.prototype = {
  *
  * @returns {Array} transposed a
  */
-Geometry.transpose3x3Matrix = function(a) {
-    var t = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
-
-    t[0][0] = a[0][0];
-    t[0][1] = a[1][0];
-    t[0][2] = a[2][0];
-
-    t[1][0] = a[0][1];
-    t[1][1] = a[1][1];
-    t[1][2] = a[2][1];
-
-    t[2][0] = a[0][2];
-    t[2][1] = a[1][2];
-    t[2][2] = a[2][2];
-
-    return t;
-}
+Geometry.transpose3x3Matrix = function (a) {
+  var t = [
+    [0, 0, 0],
+    [0, 0, 0],
+    [0, 0, 0],
+  ];
+
+  t[0][0] = a[0][0];
+  t[0][1] = a[1][0];
+  t[0][2] = a[2][0];
+
+  t[1][0] = a[0][1];
+  t[1][1] = a[1][1];
+  t[1][2] = a[2][1];
+
+  t[2][0] = a[0][2];
+  t[2][1] = a[1][2];
+  t[2][2] = a[2][2];
+
+  return t;
+};
 
 /**
  * Dot multiplication of a 3 by 3 and a 3 by 1 array
  *
  * @returns {Array} 3 by 1 array
  */
-Geometry.dot3x3and3x1 = function(a, b) {
-    var rs = [];
+Geometry.dot3x3and3x1 = function (a, b) {
+  var rs = [];
 
-    rs[0] = a[0][0]*b[0] + a[0][1] * b[1] + a[0][2] * b[2];
-    rs[1] = a[1][0]*b[0] + a[1][1] * b[1] + a[1][2] * b[2];
-    rs[2] = a[2][0]*b[0] + a[2][1] * b[1] + a[2][2] * b[2];
+  rs[0] = a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2];
+  rs[1] = a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2];
+  rs[2] = a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2];
 
-    return rs;
-}
+  return rs;
+};
 
 /**
  * Mulitplies each array element in a with the scalar s
@@ -72,14 +74,9 @@ Geometry.dot3x3and3x1 = function(a, b) {
  *
  * @returns {Array}
  */
-Geometry.multiplyArrayWithScalar = function(a, s) {
-  return [
-      a[0] * s,
-      a[1] * s,
-      a[2] * s
-    ];
-}
-
+Geometry.multiplyArrayWithScalar = function (a, s) {
+  return [a[0] * s, a[1] * s, a[2] * s];
+};
 
 /**
  * Divides each array element in a by scalar s
@@ -89,14 +86,9 @@ Geometry.multiplyArrayWithScalar = function(a, s) {
  *
  * @returns {Array}
  */
-Geometry.divideArrayWithScalar = function(a, s) {
-  return [
-      a[0] / s,
-      a[1] / s,
-      a[2] / s
-    ];
-}
-
+Geometry.divideArrayWithScalar = function (a, s) {
+  return [a[0] / s, a[1] / s, a[2] / s];
+};
 
 // Some useful defaults for the orientation calculations
 Geometry.Defaults = {};
@@ -105,7 +97,10 @@ Geometry.Defaults.X = [1, 0, 0]; // x mask
 Geometry.Defaults.Y = [0, 1, 0]; // y mask
 Geometry.Defaults.Z = [0, 0, 1]; // z mask
 
-Geometry.Defaults.NORTH = Geometry.multiplyArrayWithScalar(Geometry.Defaults.X, 0.33);
+Geometry.Defaults.NORTH = Geometry.multiplyArrayWithScalar(
+  Geometry.Defaults.X,
+  0.33,
+);
 
 // Gravity vector
 Geometry.Defaults.GRAVITY = Geometry.Defaults.Z;
@@ -113,10 +108,10 @@ Geometry.Defaults.GRAVITY = Geometry.Defaults.Z;
 /**
  * Constrain/clamp a given value to upper and lower limit
  */
-Geometry.clamp = function(value, min_value, max_value) {
-    var clampVal = Math.min(max_value, Math.max(min_value, value))
-    return clampVal;
-}
+Geometry.clamp = function (value, min_value, max_value) {
+  var clampVal = Math.min(max_value, Math.max(min_value, value));
+  return clampVal;
+};
 
 /**
  * Converts degrees to radians
@@ -125,16 +120,16 @@ Geometry.clamp = function(value, min_value, max_value) {
  *
  * @returns {Number|Array} depends on the deg param
  */
-Geometry.degToRad =  function(deg) {
+Geometry.degToRad = function (deg) {
   if (deg instanceof Array) {
     return [
-        deg[0] * Math.PI / 180,
-        deg[1] * Math.PI / 180,
-        deg[2] * Math.PI / 180
+      (deg[0] * Math.PI) / 180,
+      (deg[1] * Math.PI) / 180,
+      (deg[2] * Math.PI) / 180,
     ];
   }
-  return deg * Math.PI / 180;
-}
+  return (deg * Math.PI) / 180;
+};
 
 /**
  * Converts radians to degrees
@@ -143,15 +138,15 @@ Geometry.degToRad =  function(deg) {
  *
  * @returns {Number|Array} depends on the rad param
  */
-Geometry.radToDeg = function(rad) {
+Geometry.radToDeg = function (rad) {
   if (rad instanceof Array) {
     return [
-        rad[0] * 180 / Math.PI,
-        rad[1] * 180 / Math.PI,
-        rad[2] * 180 / Math.PI
+      (rad[0] * 180) / Math.PI,
+      (rad[1] * 180) / Math.PI,
+      (rad[2] * 180) / Math.PI,
     ];
   }
-  return rad * 180 / Math.PI;
-}
+  return (rad * 180) / Math.PI;
+};
 
-export {Geometry}
+export { Geometry };
diff --git a/src/utils/Notifications.js b/src/utils/Notifications.js
index d922da107..57c62f06b 100644
--- a/src/utils/Notifications.js
+++ b/src/utils/Notifications.js
@@ -5,61 +5,66 @@ import Button from "../components/Button/Button";
 
 const CloseButton = ({ closeToast }) => {
   return (
-    <Button ButtonIcon = {CloseIcon} onClickHandler = {closeToast} title={i18n.t('notifications.close')} label={i18n.t('notifications.close')} />
-  )
-}
+    <Button
+      ButtonIcon={CloseIcon}
+      onClickHandler={closeToast}
+      title={i18n.t("notifications.close")}
+      label={i18n.t("notifications.close")}
+    />
+  );
+};
 
 const bottomCenterSettings = {
   position: toast.POSITION.BOTTOM_CENTER,
   autoClose: 3000,
-  className: 'toast--bottom-center__message',
+  className: "toast--bottom-center__message",
   closeButton: false,
-  containerId: 'bottom-center',
-  hideProgressBar: true
-}
+  containerId: "bottom-center",
+  hideProgressBar: true,
+};
 
 const topCenterSettings = {
   position: toast.POSITION.TOP_CENTER,
   autoClose: 6000,
-  className: 'toast--top-center__message',
+  className: "toast--top-center__message",
   closeButton: CloseButton,
-  containerId: 'top-center',
-  hideProgressBar: true
-}
+  containerId: "top-center",
+  hideProgressBar: true,
+};
 
 export const showSavePrompt = () => {
-  toast(i18n.t('notifications.savePrompt'), {
+  toast(i18n.t("notifications.savePrompt"), {
     ...topCenterSettings,
     className: `${topCenterSettings.className} toast--info`,
-    icon: InfoIcon
+    icon: InfoIcon,
   });
-}
+};
 
 export const showLoginPrompt = () => {
-  toast(i18n.t('notifications.loginPrompt'), {
+  toast(i18n.t("notifications.loginPrompt"), {
     ...topCenterSettings,
     className: `${topCenterSettings.className} toast--info`,
-    icon: InfoIcon
+    icon: InfoIcon,
   });
-}
+};
 
 export const showSavedMessage = () => {
-  toast(i18n.t('notifications.projectSaved'), {
+  toast(i18n.t("notifications.projectSaved"), {
     ...bottomCenterSettings,
-    icon: TickIcon
+    icon: TickIcon,
   });
-}
+};
 
 export const showRenamedMessage = () => {
-  toast(i18n.t('notifications.projectRenamed'), {
+  toast(i18n.t("notifications.projectRenamed"), {
     ...bottomCenterSettings,
-    icon: TickIcon
-  })
-}
+    icon: TickIcon,
+  });
+};
 
 export const showRemixedMessage = () => {
-  toast(i18n.t('notifications.projectRemixed'), {
+  toast(i18n.t("notifications.projectRemixed"), {
     ...bottomCenterSettings,
-    icon: TickIcon
+    icon: TickIcon,
   });
-}
+};
diff --git a/src/utils/Notifications.test.js b/src/utils/Notifications.test.js
index 2d69c9aea..ffc395d1b 100644
--- a/src/utils/Notifications.test.js
+++ b/src/utils/Notifications.test.js
@@ -1,27 +1,44 @@
-import { toast } from 'react-toastify'
-import { showLoginPrompt, showRemixedMessage, showSavedMessage, showSavePrompt } from "./Notifications";
+import { toast } from "react-toastify";
+import {
+  showLoginPrompt,
+  showRemixedMessage,
+  showSavedMessage,
+  showSavePrompt,
+} from "./Notifications";
 
-jest.mock('../i18n', () => ({
-  t: (string) => string
-}))
-jest.mock('react-toastify')
+jest.mock("../i18n", () => ({
+  t: (string) => string,
+}));
+jest.mock("react-toastify");
 
-test('Calling showRemixedMessage calls toast with correct string', () => {
-  showRemixedMessage()
-  expect(toast).toHaveBeenCalledWith('notifications.projectRemixed', expect.anything())
-})
+test("Calling showRemixedMessage calls toast with correct string", () => {
+  showRemixedMessage();
+  expect(toast).toHaveBeenCalledWith(
+    "notifications.projectRemixed",
+    expect.anything(),
+  );
+});
 
-test('Calling showSavedMessage calls toast with correct string', () => {
-  showSavedMessage()
-  expect(toast).toHaveBeenCalledWith('notifications.projectSaved', expect.anything())
-})
+test("Calling showSavedMessage calls toast with correct string", () => {
+  showSavedMessage();
+  expect(toast).toHaveBeenCalledWith(
+    "notifications.projectSaved",
+    expect.anything(),
+  );
+});
 
-test('Calling showSavePrompt calls toast with correct string', () => {
-  showSavePrompt()
-  expect(toast).toHaveBeenCalledWith('notifications.savePrompt', expect.anything())
-})
+test("Calling showSavePrompt calls toast with correct string", () => {
+  showSavePrompt();
+  expect(toast).toHaveBeenCalledWith(
+    "notifications.savePrompt",
+    expect.anything(),
+  );
+});
 
-test('Calling showLoginPrompt calls toast with correct string', () => {
-  showLoginPrompt()
-  expect(toast).toHaveBeenCalledWith('notifications.loginPrompt', expect.anything())
-})
+test("Calling showLoginPrompt calls toast with correct string", () => {
+  showLoginPrompt();
+  expect(toast).toHaveBeenCalledWith(
+    "notifications.loginPrompt",
+    expect.anything(),
+  );
+});
diff --git a/src/utils/Orientation.js b/src/utils/Orientation.js
index 926233ce1..d5cbb7a82 100644
--- a/src/utils/Orientation.js
+++ b/src/utils/Orientation.js
@@ -1,20 +1,20 @@
-import { Geometry } from './Geometry';
-import Sk from 'skulpt';
+import { Geometry } from "./Geometry";
+import Sk from "skulpt";
 
-function getTimestamp () {
+function getTimestamp() {
   var time = Date.now(); // millis
-  var timestamp = time * 1e+3; // milliseconds
+  var timestamp = time * 1e3; // milliseconds
   return timestamp;
 }
 
 /**
-* Update call for periodically updating our internal sensehat data object.
-*
-* The UI events and the polling are async and therefore we can "simulate"
-* even changes when the user does not rotate.
-*/
+ * Update call for periodically updating our internal sensehat data object.
+ *
+ * The UI events and the polling are async and therefore we can "simulate"
+ * even changes when the user does not rotate.
+ */
 export function updateRTIMU() {
-// Retriev the previous timestamp
+  // Retriev the previous timestamp
   var oldTimestamp = Sk.sense_hat.rtimu.timestamp;
 
   // Special case, if we call this function the first time and
@@ -25,7 +25,7 @@ export function updateRTIMU() {
 
   // Get a new timestamp and calc the delta
   var newTimestamp = getTimestamp();
-  var timeDelta = (newTimestamp - oldTimestamp) / 1e+6;
+  var timeDelta = (newTimestamp - oldTimestamp) / 1e6;
 
   // Special case, when the delta is 0, everything gets null
   // Using a sane interval should avoid this case
@@ -39,7 +39,7 @@ export function updateRTIMU() {
   var oldOrientation = Sk.sense_hat.rtimu.raw_old_orientation;
 
   if (oldOrientation === null || oldOrientation === undefined) {
-    oldOrientation = [0,90,0];
+    oldOrientation = [0, 90, 0];
   }
   var newOrientation = Geometry.degToRad(Sk.sense_hat.rtimu.raw_orientation);
 
@@ -48,7 +48,7 @@ export function updateRTIMU() {
   var _gyro = [
     newOrientation[0] - oldOrientation[0],
     newOrientation[1] - oldOrientation[1],
-    newOrientation[2] - oldOrientation[2]
+    newOrientation[2] - oldOrientation[2],
   ];
 
   // Divide the orientation delta by the time delta
@@ -71,8 +71,8 @@ export function updateRTIMU() {
   var R = [
     [c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2],
     [c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3],
-    [-s2,     c2 * s3,                c2 * c3],
-  ]
+    [-s2, c2 * s3, c2 * c3],
+  ];
 
   // Transposed R matrix
   var T = Geometry.transpose3x3Matrix(R);
@@ -97,17 +97,12 @@ export function updateRTIMU() {
   Sk.sense_hat.rtimu.accel = [
     Geometry.clamp(_accel[0], -8, 8),
     Geometry.clamp(_accel[1], -8, 8),
-    Geometry.clamp(_accel[2], -8, 8)
+    Geometry.clamp(_accel[2], -8, 8),
   ];
 
   // _gyro = perturb(_gyro, .5);
   // radians per second
-  Sk.sense_hat.rtimu.gyro = [
-    _gyro[0],
-    _gyro[1],
-    _gyro[2],
-  ];
-
+  Sk.sense_hat.rtimu.gyro = [_gyro[0], _gyro[1], _gyro[2]];
 
   // _compass = perturb(_compass, .01);
   // multiply with 100 -> from Gauss to microteslas (µT)
@@ -118,24 +113,28 @@ export function updateRTIMU() {
   ];
 }
 
-window.rotatemodel = function(x, y, z){
+window.rotatemodel = function (x, y, z) {
   window.mod.rotation.x = x;
   window.mod.rotation.y = y;
   window.mod.rotation.z = z;
-}
+};
 
 export function resetModel(event) {
   event.preventDefault();
 
-    var x = 0
-      , y = 0
-      , z = 0;
-    window.rotatemodel(Geometry.degToRad(x), Geometry.degToRad(y), Geometry.degToRad(z));
+  var x = 0,
+    y = 0,
+    z = 0;
+  window.rotatemodel(
+    Geometry.degToRad(x),
+    Geometry.degToRad(y),
+    Geometry.degToRad(z),
+  );
 }
 
 export function extractRollPitchYaw(x, y, z) {
-  const roll = ((y * 180 / Math.PI) + 360) % 360
-  const pitch = ((x * 180 / Math.PI) + 90 + 360) % 360
-  const yaw = ((z * 180 / Math.PI) + 360) % 360
-  return [roll, pitch, yaw]
+  const roll = ((y * 180) / Math.PI + 360) % 360;
+  const pitch = ((x * 180) / Math.PI + 90 + 360) % 360;
+  const yaw = ((z * 180) / Math.PI + 360) % 360;
+  return [roll, pitch, yaw];
 }
diff --git a/src/utils/ResizableWithHandle.js b/src/utils/ResizableWithHandle.js
index c58a3bfaa..2a07f0cff 100644
--- a/src/utils/ResizableWithHandle.js
+++ b/src/utils/ResizableWithHandle.js
@@ -1,59 +1,92 @@
 import React, { useState, useMemo } from "react";
 import PropTypes from "prop-types";
-import { Resizable } from 're-resizable';
+import { Resizable } from "re-resizable";
 
-import './ResizableWithHandle.scss';
+import "./ResizableWithHandle.scss";
 
 const VerticalHandle = () => (
-  <svg data-testid="verticalHandle" width="44" height="56" viewBox="0 0 44 56" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <svg
+    data-testid="verticalHandle"
+    width="44"
+    height="56"
+    viewBox="0 0 44 56"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+  >
     <rect x="20" width="4" height="56" rx="2" fill="#616575" />
   </svg>
 );
 
 const HorizontalHandle = () => (
-  <svg data-testid="horizontalHandle" width="56" height="44" viewBox="0 0 56 44" fill="none" xmlns="http://www.w3.org/2000/svg">
-    <rect x="56" y="20" width="4" height="56" rx="2" transform="rotate(90 56 20)" fill="#616575"/>
+  <svg
+    data-testid="horizontalHandle"
+    width="56"
+    height="44"
+    viewBox="0 0 56 44"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+  >
+    <rect
+      x="56"
+      y="20"
+      width="4"
+      height="56"
+      rx="2"
+      transform="rotate(90 56 20)"
+      fill="#616575"
+    />
   </svg>
 );
 
-const ResizableWithHandle = props => {
-  const {children, defaultWidth, defaultHeight, handleDirection, ...rest} = props;
+const ResizableWithHandle = (props) => {
+  const { children, defaultWidth, defaultHeight, handleDirection, ...rest } =
+    props;
 
-  const [width, setWidth] = useState('auto');
-  const [height, setHeight] = useState('auto');
+  const [width, setWidth] = useState("auto");
+  const [height, setHeight] = useState("auto");
 
   useMemo(() => setWidth(defaultWidth), [defaultWidth]);
   useMemo(() => setHeight(defaultHeight), [defaultHeight]);
 
-  const onResizeStop = (...[,,, d]) => {
+  const onResizeStop = (...[, , , d]) => {
     setWidth(width + d.width);
     setHeight(height + d.height);
   };
 
-  let handleComponent = ['right', 'left'].includes(handleDirection) ? { [handleDirection]: <VerticalHandle /> } :
-      (['top', 'bottom'].includes(handleDirection) ? { [handleDirection]: <HorizontalHandle /> } : {});
+  let handleComponent = ["right", "left"].includes(handleDirection)
+    ? { [handleDirection]: <VerticalHandle /> }
+    : ["top", "bottom"].includes(handleDirection)
+    ? { [handleDirection]: <HorizontalHandle /> }
+    : {};
 
   let handleWrapperClass = `resizable-with-handle__handle resizable-with-handle__handle--${handleDirection}`;
 
   return (
     <Resizable
-      enable={{ top: false, right: false, bottom: false, left: false, ...{[handleDirection]: true} }}
+      enable={{
+        top: false,
+        right: false,
+        bottom: false,
+        left: false,
+        ...{ [handleDirection]: true },
+      }}
       handleComponent={handleComponent}
       handleWrapperClass={handleWrapperClass}
       onResizeStop={onResizeStop}
-      size={{width: width, height: height}}
+      size={{ width: width, height: height }}
       {...rest}
     >
       {children}
     </Resizable>
   );
-}
+};
 
 ResizableWithHandle.propTypes = {
   children: PropTypes.object.isRequired,
   defaultWidth: PropTypes.string,
   defaultHeight: PropTypes.string,
-  handleDirection: PropTypes.oneOf(['right', 'left', 'top', 'bottom']).isRequired,
+  handleDirection: PropTypes.oneOf(["right", "left", "top", "bottom"])
+    .isRequired,
 };
 
 export default ResizableWithHandle;
diff --git a/src/utils/ResizableWithHandle.test.js b/src/utils/ResizableWithHandle.test.js
index c90c9a3d8..79f6b76bf 100644
--- a/src/utils/ResizableWithHandle.test.js
+++ b/src/utils/ResizableWithHandle.test.js
@@ -1,23 +1,33 @@
 import React from "react";
-import {render, screen} from "@testing-library/react";
+import { render, screen } from "@testing-library/react";
 import ResizableWithHandle from "./ResizableWithHandle";
 
-test('renders a horizontal handle', () => {
-  render(<ResizableWithHandle handleDirection='bottom' />);
-  expect(screen.getByTestId('horizontalHandle')).toBeTruthy();
+test("renders a horizontal handle", () => {
+  render(<ResizableWithHandle handleDirection="bottom" />);
+  expect(screen.getByTestId("horizontalHandle")).toBeTruthy();
 });
 
-test('renders a vertical handle', () => {
-  render(<ResizableWithHandle handleDirection='right' />);
-  expect(screen.getByTestId('verticalHandle')).toBeTruthy();
+test("renders a vertical handle", () => {
+  render(<ResizableWithHandle handleDirection="right" />);
+  expect(screen.getByTestId("verticalHandle")).toBeTruthy();
 });
 
-test('it does not add an incorrect class to the handle', () => {
-  const {container} = render(<ResizableWithHandle handleDirection='bottom' />);
-  expect(container.getElementsByClassName('resizable-with-handle__handle--right').length).toBe(0);
+test("it does not add an incorrect class to the handle", () => {
+  const { container } = render(
+    <ResizableWithHandle handleDirection="bottom" />,
+  );
+  expect(
+    container.getElementsByClassName("resizable-with-handle__handle--right")
+      .length,
+  ).toBe(0);
 });
 
-test('it adds the expected class to the handle', () => {
-  const {container} = render(<ResizableWithHandle handleDirection='bottom' />);
-  expect(container.getElementsByClassName('resizable-with-handle__handle--bottom').length).toBe(1);
+test("it adds the expected class to the handle", () => {
+  const { container } = render(
+    <ResizableWithHandle handleDirection="bottom" />,
+  );
+  expect(
+    container.getElementsByClassName("resizable-with-handle__handle--bottom")
+      .length,
+  ).toBe(1);
 });
diff --git a/src/utils/ToastCloseButton.js b/src/utils/ToastCloseButton.js
index b894033fc..a1c0a9afd 100644
--- a/src/utils/ToastCloseButton.js
+++ b/src/utils/ToastCloseButton.js
@@ -5,10 +5,11 @@ import { CloseIcon } from "../Icons";
 const ToastCloseButton = ({ closeToast }) => {
   return (
     <Button
-      className='btn btn--tertiary'
+      className="btn btn--tertiary"
       onClickHandler={closeToast}
-      ButtonIcon={() => <CloseIcon scaleFactor={0.75} />}/>
-  )
-}
+      ButtonIcon={() => <CloseIcon scaleFactor={0.75} />}
+    />
+  );
+};
 
-export default ToastCloseButton
+export default ToastCloseButton;
diff --git a/src/utils/ToastCloseButton.test.js b/src/utils/ToastCloseButton.test.js
index 90827811f..88fd9fd48 100644
--- a/src/utils/ToastCloseButton.test.js
+++ b/src/utils/ToastCloseButton.test.js
@@ -2,18 +2,18 @@ import React from "react";
 import { fireEvent, render, screen } from "@testing-library/react";
 import ToastCloseButton from "./ToastCloseButton";
 
-const closeToast = jest.fn()
+const closeToast = jest.fn();
 
 beforeEach(() => {
-  render(<ToastCloseButton closeToast={closeToast}/>)
-})
+  render(<ToastCloseButton closeToast={closeToast} />);
+});
 
-test('Close button renders', () => {
-  expect(screen.queryByRole('button')).toBeInTheDocument()
-})
+test("Close button renders", () => {
+  expect(screen.queryByRole("button")).toBeInTheDocument();
+});
 
-test('Clicking close button calls closeToast function', () => {
-  const closeButton = screen.queryByRole('button')
-  fireEvent.click(closeButton)
-  expect(closeToast).toHaveBeenCalled()
-})
+test("Clicking close button calls closeToast function", () => {
+  const closeButton = screen.queryByRole("button");
+  fireEvent.click(closeButton);
+  expect(closeToast).toHaveBeenCalled();
+});
diff --git a/src/utils/apiCallHandler.js b/src/utils/apiCallHandler.js
index fe36f8207..69ef43784 100644
--- a/src/utils/apiCallHandler.js
+++ b/src/utils/apiCallHandler.js
@@ -1,68 +1,91 @@
-import axios from 'axios';
-import omit from 'lodash/omit'
+import axios from "axios";
+import omit from "lodash/omit";
 
 const host = process.env.REACT_APP_API_ENDPOINT;
 
 const get = async (url, headers) => {
   return await axios.get(url, headers);
-}
+};
 
 const post = async (url, body, headers) => {
   return await axios.post(url, body, headers);
-}
+};
 
 const put = async (url, body, headers) => {
-  return await axios.put(url, body, headers)
-}
+  return await axios.put(url, body, headers);
+};
 
 const headers = (accessToken) => {
-    let headersHash
-    if (accessToken) {
-        headersHash = {'Accept': 'application/json', 'Authorization': accessToken}
-    } else {
-        headersHash = {'Accept': 'application/json'}
-    }
-    return {headers: headersHash}
-}
+  let headersHash;
+  if (accessToken) {
+    headersHash = { Accept: "application/json", Authorization: accessToken };
+  } else {
+    headersHash = { Accept: "application/json" };
+  }
+  return { headers: headersHash };
+};
 
 export const createOrUpdateProject = async (projectWithUserId, accessToken) => {
-  const project = omit(projectWithUserId, ['user_id'])
+  const project = omit(projectWithUserId, ["user_id"]);
   if (!project.identifier) {
-    return await post(`${host}/api/projects`, { project }, headers(accessToken))
-  }
-  else {
-    return await put(`${host}/api/projects/${project.identifier}`, { project }, headers(accessToken))
+    return await post(
+      `${host}/api/projects`,
+      { project },
+      headers(accessToken),
+    );
+  } else {
+    return await put(
+      `${host}/api/projects/${project.identifier}`,
+      { project },
+      headers(accessToken),
+    );
   }
-}
+};
 
 export const deleteProject = async (identifier, accessToken) => {
-  return await axios.delete(`${host}/api/projects/${identifier}`, headers(accessToken));
-}
+  return await axios.delete(
+    `${host}/api/projects/${identifier}`,
+    headers(accessToken),
+  );
+};
 
 export const getImage = async (url) => {
-  return await get(url, headers())
-}
+  return await get(url, headers());
+};
 
 export const createRemix = async (project, accessToken) => {
-  return await post(`${host}/api/projects/${project.identifier}/remix`, { project: project}, headers(accessToken));
-}
+  return await post(
+    `${host}/api/projects/${project.identifier}/remix`,
+    { project: project },
+    headers(accessToken),
+  );
+};
 
 export const readProject = async (projectIdentifier, locale, accessToken) => {
-  const queryString = locale ? `?locale=${locale}` : ""
-  return await get(`${host}/api/projects/${projectIdentifier}${queryString}`, headers(accessToken));
-}
+  const queryString = locale ? `?locale=${locale}` : "";
+  return await get(
+    `${host}/api/projects/${projectIdentifier}${queryString}`,
+    headers(accessToken),
+  );
+};
 
 export const readProjectList = async (page, accessToken) => {
-  return await get(`${host}/api/projects`, {params: {page}, ...headers(accessToken)});
-}
+  return await get(`${host}/api/projects`, {
+    params: { page },
+    ...headers(accessToken),
+  });
+};
 
 export const uploadImages = async (projectIdentifier, accessToken, images) => {
   var formData = new FormData();
 
-  images.forEach(image => {
-    formData.append('images[]', image, image.name);
-  })
-
-  return await post(`${host}/api/projects/${projectIdentifier}/images`, formData, {...headers(accessToken), 'Content-Type': 'multipart/form-data'})
-}
+  images.forEach((image) => {
+    formData.append("images[]", image, image.name);
+  });
 
+  return await post(
+    `${host}/api/projects/${projectIdentifier}/images`,
+    formData,
+    { ...headers(accessToken), "Content-Type": "multipart/form-data" },
+  );
+};
diff --git a/src/utils/apiCallHandler.test.js b/src/utils/apiCallHandler.test.js
index a13e9a3e4..40a8fa7cb 100644
--- a/src/utils/apiCallHandler.test.js
+++ b/src/utils/apiCallHandler.test.js
@@ -1,111 +1,173 @@
 import axios from "axios";
 
-import { getImage, createOrUpdateProject, readProject, createRemix, uploadImages, readProjectList } from "./apiCallHandler";
-
-jest.mock('axios');
+import {
+  getImage,
+  createOrUpdateProject,
+  readProject,
+  createRemix,
+  uploadImages,
+  readProjectList,
+} from "./apiCallHandler";
+
+jest.mock("axios");
 const host = process.env.REACT_APP_API_ENDPOINT;
-const defaultHeaders = {'headers': {'Accept': 'application/json'}}
-const accessToken = "39a09671-be55-4847-baf5-8919a0c24a25"
-const authHeaders = {'headers': {'Accept': 'application/json', 'Authorization': accessToken}}
+const defaultHeaders = { headers: { Accept: "application/json" } };
+const accessToken = "39a09671-be55-4847-baf5-8919a0c24a25";
+const authHeaders = {
+  headers: { Accept: "application/json", Authorization: accessToken },
+};
 
 describe("Testing project API calls", () => {
-
   test("Creating project", async () => {
-    const newProject =  { project_type: 'python', components: [], name: 'Untitled'}
-    axios.post.mockImplementationOnce(() => Promise.resolve({
+    const newProject = {
+      project_type: "python",
+      components: [],
+      name: "Untitled",
+    };
+    axios.post.mockImplementationOnce(() =>
+      Promise.resolve({
+        status: 204,
+        data: {
+          project: {
+            identifier: "new-project-identifier",
+            ...newProject,
+          },
+        },
+      }),
+    );
+
+    const data = await createOrUpdateProject(newProject);
+    expect(axios.post).toHaveBeenCalledWith(
+      `${host}/api/projects`,
+      { project: newProject },
+      defaultHeaders,
+    );
+    expect(data).toStrictEqual({
       status: 204,
       data: {
         project: {
-          identifier: 'new-project-identifier',
-          ...newProject
-        }
-      }
-    }))
-
-    const data = await createOrUpdateProject(newProject)
-    expect(axios.post).toHaveBeenCalledWith(`${host}/api/projects`, {project: newProject}, defaultHeaders)
-    expect(data).toStrictEqual({
-      status: 204,
-      data: { project: { identifier: 'new-project-identifier', project_type: 'python', components: [], name: 'Untitled'}}
-    })
-  })
+          identifier: "new-project-identifier",
+          project_type: "python",
+          components: [],
+          name: "Untitled",
+        },
+      },
+    });
+  });
 
   test("Remixing project", async () => {
-    const originalProject = { identifier: 'original-hello-project', project_type: 'python'}
+    const originalProject = {
+      identifier: "original-hello-project",
+      project_type: "python",
+    };
     axios.post.mockImplementationOnce(() => {
-      const remixedProject = {'identifier': 'remixed-hello-project', 'project_type': 'python'}
-      Promise.resolve({data: remixedProject})
-    })
-
-    await createRemix(originalProject, accessToken)
-    expect(axios.post).toHaveBeenCalledWith((`${host}/api/projects/${originalProject['identifier']}/remix`), { "project": { "identifier": "original-hello-project", "project_type": "python" } }, authHeaders)
-  })
+      const remixedProject = {
+        identifier: "remixed-hello-project",
+        project_type: "python",
+      };
+      Promise.resolve({ data: remixedProject });
+    });
+
+    await createRemix(originalProject, accessToken);
+    expect(axios.post).toHaveBeenCalledWith(
+      `${host}/api/projects/${originalProject["identifier"]}/remix`,
+      {
+        project: {
+          identifier: "original-hello-project",
+          project_type: "python",
+        },
+      },
+      authHeaders,
+    );
+  });
 
   test("Updating project", async () => {
-    const project = {'identifier': 'my-wonderful-project', 'project_type': 'python', 'components': []}
-    axios.put.mockImplementationOnce(() => Promise.resolve(200))
-
-    await createOrUpdateProject(project)
+    const project = {
+      identifier: "my-wonderful-project",
+      project_type: "python",
+      components: [],
+    };
+    axios.put.mockImplementationOnce(() => Promise.resolve(200));
+
+    await createOrUpdateProject(project);
     expect(axios.put).toHaveBeenCalledWith(
-      `${host}/api/projects/${project['identifier']}`,
+      `${host}/api/projects/${project["identifier"]}`,
       { project: project },
-      defaultHeaders
-    )
-  })
+      defaultHeaders,
+    );
+  });
 
   test("Read project with identifier only", async () => {
-    const projectIdentifier = "hello-world-project"
-    axios.get.mockImplementationOnce(() => Promise.resolve())
+    const projectIdentifier = "hello-world-project";
+    axios.get.mockImplementationOnce(() => Promise.resolve());
 
-    await readProject(projectIdentifier)
-    expect(axios.get).toHaveBeenCalledWith(`${host}/api/projects/${projectIdentifier}`, defaultHeaders)
-  })
+    await readProject(projectIdentifier);
+    expect(axios.get).toHaveBeenCalledWith(
+      `${host}/api/projects/${projectIdentifier}`,
+      defaultHeaders,
+    );
+  });
 
   test("Read project with locale", async () => {
-    const projectIdentifier = "hello-world-project"
-    const locale = 'es-LA'
-    axios.get.mockImplementationOnce(() => Promise.resolve())
+    const projectIdentifier = "hello-world-project";
+    const locale = "es-LA";
+    axios.get.mockImplementationOnce(() => Promise.resolve());
 
-    await readProject(projectIdentifier, locale)
-    expect(axios.get).toHaveBeenCalledWith(`${host}/api/projects/${projectIdentifier}?locale=${locale}`, defaultHeaders)
-  })
+    await readProject(projectIdentifier, locale);
+    expect(axios.get).toHaveBeenCalledWith(
+      `${host}/api/projects/${projectIdentifier}?locale=${locale}`,
+      defaultHeaders,
+    );
+  });
 
   test("Read project with access token", async () => {
-    const projectIdentifier = "hello-world-project"
-    axios.get.mockImplementationOnce(() => Promise.resolve())
+    const projectIdentifier = "hello-world-project";
+    axios.get.mockImplementationOnce(() => Promise.resolve());
 
-    await readProject(projectIdentifier, null, accessToken)
-    expect(axios.get).toHaveBeenCalledWith(`${host}/api/projects/${projectIdentifier}`, authHeaders)
-  })
+    await readProject(projectIdentifier, null, accessToken);
+    expect(axios.get).toHaveBeenCalledWith(
+      `${host}/api/projects/${projectIdentifier}`,
+      authHeaders,
+    );
+  });
 
   test("Upload image", async () => {
-    const projectIdentifier = "my-amazing-project"
-    const image = new File(['(⌐□_□)'], 'image1.png', {type: 'image/png'})
-    axios.post.mockImplementationOnce(() => Promise.resolve({status: 200, url: 'google.drive.com/image1.png'}))
+    const projectIdentifier = "my-amazing-project";
+    const image = new File(["(⌐□_□)"], "image1.png", { type: "image/png" });
+    axios.post.mockImplementationOnce(() =>
+      Promise.resolve({ status: 200, url: "google.drive.com/image1.png" }),
+    );
 
     var formData = new FormData();
-    formData.append('images[]', image, image.name)
+    formData.append("images[]", image, image.name);
 
-    await uploadImages(projectIdentifier, accessToken, [image])
-    expect(axios.post).toHaveBeenCalledWith(`${host}/api/projects/${projectIdentifier}/images`, formData, {...authHeaders, "Content-Type": "multipart/form-data"})
-  })
+    await uploadImages(projectIdentifier, accessToken, [image]);
+    expect(axios.post).toHaveBeenCalledWith(
+      `${host}/api/projects/${projectIdentifier}/images`,
+      formData,
+      { ...authHeaders, "Content-Type": "multipart/form-data" },
+    );
+  });
 
   test("Get image", async () => {
-    const image = new File(['(⌐□_□)'], 'image1.png', {type: 'image/png'})
-    const imageUrl = 'google.drive.com/image1.png'
-
-    axios.get.mockImplementationOnce(() => Promise.resolve({image: image}))
-
-    await getImage(imageUrl)
-    expect(axios.get).toHaveBeenCalledWith(imageUrl, defaultHeaders)
-  })
-})
-
-describe('Index page API calls', () => {
-  test('Loading project list', async () => {
-    axios.get.mockImplementationOnce(() => Promise.resolve(200))
-    const page = 3
-    await readProjectList(page, accessToken)
-    expect(axios.get).toHaveBeenCalledWith(`${host}/api/projects`, {...authHeaders, params: {page}})
-  })
-})
+    const image = new File(["(⌐□_□)"], "image1.png", { type: "image/png" });
+    const imageUrl = "google.drive.com/image1.png";
+
+    axios.get.mockImplementationOnce(() => Promise.resolve({ image: image }));
+
+    await getImage(imageUrl);
+    expect(axios.get).toHaveBeenCalledWith(imageUrl, defaultHeaders);
+  });
+});
+
+describe("Index page API calls", () => {
+  test("Loading project list", async () => {
+    axios.get.mockImplementationOnce(() => Promise.resolve(200));
+    const page = 3;
+    await readProjectList(page, accessToken);
+    expect(axios.get).toHaveBeenCalledWith(`${host}/api/projects`, {
+      ...authHeaders,
+      params: { page },
+    });
+  });
+});
diff --git a/src/utils/apolloCache.js b/src/utils/apolloCache.js
index 85b2be02c..8c8e89bed 100644
--- a/src/utils/apolloCache.js
+++ b/src/utils/apolloCache.js
@@ -25,7 +25,7 @@ const apolloCache = new InMemoryCache({
             // Find prefix
             if (startCursor) {
               const index = existing.edges.findIndex(
-                (edge) => edge.cursor === startCursor
+                (edge) => edge.cursor === startCursor,
               );
               prefix =
                 index > -1 ? existing.edges.slice(0, index) : existing.edges;
@@ -34,7 +34,7 @@ const apolloCache = new InMemoryCache({
             // Find suffix
             if (endCursor) {
               const index = existing.edges.findIndex(
-                (edge) => edge.cursor === endCursor
+                (edge) => edge.cursor === endCursor,
               );
               suffix = index > -1 ? existing.edges.slice(index + 1) : [];
             }
diff --git a/src/utils/componentNameValidation.js b/src/utils/componentNameValidation.js
index 8c7e90294..21416e3f5 100644
--- a/src/utils/componentNameValidation.js
+++ b/src/utils/componentNameValidation.js
@@ -1,48 +1,62 @@
 import { setNameError } from "../components/Editor/EditorSlice";
 
 const allowedExtensions = {
-  "python": [
-    "py",
-    "csv",
-    "txt"
-  ],
-  "html": [
-    "html",
-    "css"
-  ]
-}
+  python: ["py", "csv", "txt"],
+  html: ["html", "css"],
+};
 
 const allowedExtensionsString = (projectType, t) => {
   const extensionsList = allowedExtensions[projectType];
   if (extensionsList.length === 1) {
-    return `'.${extensionsList[0]}'`
+    return `'.${extensionsList[0]}'`;
   } else {
-    return `'.${extensionsList.slice(0,-1).join(`', '.`)}' ${t('filePane.errors.or')} '.${extensionsList[extensionsList.length-1]}'`;
+    return `'.${extensionsList.slice(0, -1).join(`', '.`)}' ${t(
+      "filePane.errors.or",
+    )} '.${extensionsList[extensionsList.length - 1]}'`;
   }
-}
+};
 
 const isValidFileName = (fileName, projectType, componentNames) => {
-  const extension = fileName.split('.').slice(1).join('.')
-  if (allowedExtensions[projectType].includes(extension) && !componentNames.includes(fileName) && fileName.split(' ').length === 1) {
+  const extension = fileName.split(".").slice(1).join(".");
+  if (
+    allowedExtensions[projectType].includes(extension) &&
+    !componentNames.includes(fileName) &&
+    fileName.split(" ").length === 1
+  ) {
     return true;
   } else {
     return false;
   }
-}
+};
 
-export const validateFileName = (fileName, projectType="python", componentNames, dispatch, t, callback, currentFileName=null) => {
-  const extension = fileName.split('.').slice(1).join('.');
-  if (isValidFileName(fileName, projectType, componentNames) || (currentFileName && fileName === currentFileName)) {
-    callback()
+export const validateFileName = (
+  fileName,
+  projectType = "python",
+  componentNames,
+  dispatch,
+  t,
+  callback,
+  currentFileName = null,
+) => {
+  const extension = fileName.split(".").slice(1).join(".");
+  if (
+    isValidFileName(fileName, projectType, componentNames) ||
+    (currentFileName && fileName === currentFileName)
+  ) {
+    callback();
   } else if (componentNames.includes(fileName)) {
-    dispatch(setNameError(t('filePane.errors.notUnique')));
-  } else if (fileName.split(' ').length > 1) {
-    dispatch(setNameError(t('filePane.errors.containsSpaces')))
+    dispatch(setNameError(t("filePane.errors.notUnique")));
+  } else if (fileName.split(" ").length > 1) {
+    dispatch(setNameError(t("filePane.errors.containsSpaces")));
   } else if (!allowedExtensions[projectType].includes(extension)) {
-    dispatch(setNameError(t('filePane.errors.unsupportedExtension', {allowedExtensions: allowedExtensionsString(projectType, t)})));
+    dispatch(
+      setNameError(
+        t("filePane.errors.unsupportedExtension", {
+          allowedExtensions: allowedExtensionsString(projectType, t),
+        }),
+      ),
+    );
   } else {
-    dispatch(setNameError(t('filePane.errors.generalError')));
+    dispatch(setNameError(t("filePane.errors.generalError")));
   }
-}
-
-
+};
diff --git a/src/utils/containerQueries.js b/src/utils/containerQueries.js
index a90707b41..457357683 100644
--- a/src/utils/containerQueries.js
+++ b/src/utils/containerQueries.js
@@ -1,5 +1,5 @@
 export const projContainer = {
-  'width-larger-than-880': {
+  "width-larger-than-880": {
     minWidth: 880,
-  }
+  },
 };
diff --git a/src/utils/defaultProjects.js b/src/utils/defaultProjects.js
index 66c1baa00..6d3243691 100644
--- a/src/utils/defaultProjects.js
+++ b/src/utils/defaultProjects.js
@@ -1,23 +1,28 @@
 import i18n from "../i18n";
 
 export const defaultPythonProject = {
-  project_type: 'python',
-  name: i18n.t('project.untitled'),
+  project_type: "python",
+  name: i18n.t("project.untitled"),
   locale: null,
-  components: [
-    { extension: 'py', name: 'main',
-      content: "", default: true },
-  ],
-  image_list: []
-}
+  components: [{ extension: "py", name: "main", content: "", default: true }],
+  image_list: [],
+};
 
 export const defaultHtmlProject = {
-  project_type: 'html',
-  name: i18n.t('project.untitled'),
+  project_type: "html",
+  name: i18n.t("project.untitled"),
   components: [
-    { extension: 'html', name: 'index',
-      content: "<html>\n  <head>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head> <body>\n    <h1>Heading</h1>\n    <p>Paragraph</p>\n  </body>\n</html>" },
-    { extension: 'css', name: 'style', content: "h1 {\n  color: blue;\n}" },
-    { extension: 'css', name: 'test', content: "p {\n  background-color: red;\n}" }
-  ]
-}
+    {
+      extension: "html",
+      name: "index",
+      content:
+        '<html>\n  <head>\n    <link rel="stylesheet" type="text/css" href="style.css">\n  </head> <body>\n    <h1>Heading</h1>\n    <p>Paragraph</p>\n  </body>\n</html>',
+    },
+    { extension: "css", name: "style", content: "h1 {\n  color: blue;\n}" },
+    {
+      extension: "css",
+      name: "test",
+      content: "p {\n  background-color: red;\n}",
+    },
+  ],
+};
diff --git a/src/utils/login.js b/src/utils/login.js
index e0e74fb1e..5f4593803 100644
--- a/src/utils/login.js
+++ b/src/utils/login.js
@@ -1,15 +1,26 @@
-import userManager from "./userManager"
+import userManager from "./userManager";
 
-export const login = ({project, location, triggerSave, accessDeniedData} = {}) => {
-  window.plausible('Login button')
+export const login = ({
+  project,
+  location,
+  triggerSave,
+  accessDeniedData,
+} = {}) => {
+  window.plausible("Login button");
   if (accessDeniedData) {
-    localStorage.setItem('location', `/projects/${accessDeniedData.identifier}`)
+    localStorage.setItem(
+      "location",
+      `/projects/${accessDeniedData.identifier}`,
+    );
   } else {
-    localStorage.setItem('location', location.pathname)
-    localStorage.setItem(project.identifier || 'project', JSON.stringify(project))
+    localStorage.setItem("location", location.pathname);
+    localStorage.setItem(
+      project.identifier || "project",
+      JSON.stringify(project),
+    );
   }
   if (triggerSave) {
-    localStorage.setItem('awaitingSave', 'true')
+    localStorage.setItem("awaitingSave", "true");
   }
   userManager.signinRedirect();
-}
+};
diff --git a/src/utils/projectHelpers.js b/src/utils/projectHelpers.js
index da202901f..af4c9c1db 100644
--- a/src/utils/projectHelpers.js
+++ b/src/utils/projectHelpers.js
@@ -1,7 +1,7 @@
 export const isOwner = (user, project) => {
   return (
-    user && user.profile && 
+    user &&
+    user.profile &&
     (user.profile.user === project.user_id || !project.identifier)
-  )
-}
-  
\ No newline at end of file
+  );
+};
diff --git a/src/utils/projectHelpers.test.js b/src/utils/projectHelpers.test.js
index 8647412ad..7603fd813 100644
--- a/src/utils/projectHelpers.test.js
+++ b/src/utils/projectHelpers.test.js
@@ -1,77 +1,77 @@
-import { isOwner } from './projectHelpers'
+import { isOwner } from "./projectHelpers";
 
-describe('With logged in user', () => {
+describe("With logged in user", () => {
   const user = {
     profile: {
-      user: 'cd8a5b3d-f7bb-425e-908f-1386decd6bb1'
-    }
-  }
+      user: "cd8a5b3d-f7bb-425e-908f-1386decd6bb1",
+    },
+  };
 
-  describe('who owns current project', () => {
+  describe("who owns current project", () => {
     const project = {
-      identifier: 'hot-diggity-dog',
-      user_id: 'cd8a5b3d-f7bb-425e-908f-1386decd6bb1'
-    }
+      identifier: "hot-diggity-dog",
+      user_id: "cd8a5b3d-f7bb-425e-908f-1386decd6bb1",
+    };
 
-    test('isOwner returns true', () => {
-      expect(isOwner(user, project)).toBeTruthy()
-    })
-  })
+    test("isOwner returns true", () => {
+      expect(isOwner(user, project)).toBeTruthy();
+    });
+  });
 
-  describe('who does not own current project', () => {
+  describe("who does not own current project", () => {
     const project = {
-      identifier: 'hot-diggity-dog',
-      user_id: '14f7d384-9e55-470f-b4cc-961236e1becb'
-    }
+      identifier: "hot-diggity-dog",
+      user_id: "14f7d384-9e55-470f-b4cc-961236e1becb",
+    };
 
-    test('isOwner returns false', () => {
-      expect(isOwner(user, project)).toBeFalsy()
-    })
-  })
+    test("isOwner returns false", () => {
+      expect(isOwner(user, project)).toBeFalsy();
+    });
+  });
 
-  describe('and unsaved project', () => {
+  describe("and unsaved project", () => {
     const project = {
       identifier: undefined,
-    }
+    };
 
-    test('isOwner returns true', () => {
-      expect(isOwner(user, project)).toBeTruthy()
-    })
-  })
-})
+    test("isOwner returns true", () => {
+      expect(isOwner(user, project)).toBeTruthy();
+    });
+  });
+});
 
-describe('With no active user', () => {
-  const user = undefined
+describe("With no active user", () => {
+  const user = undefined;
 
-  describe('and public project', () => {
+  describe("and public project", () => {
     const project = {
-      identifier: 'blue-suede-shoes',
-      user_id: undefined
-    }
+      identifier: "blue-suede-shoes",
+      user_id: undefined,
+    };
 
-    test('isOwner returns false', () => {
-      expect(isOwner(user, project)).toBeFalsy()
-    })
-  })
+    test("isOwner returns false", () => {
+      expect(isOwner(user, project)).toBeFalsy();
+    });
+  });
 
-  describe('and private project', () => {
+  describe("and private project", () => {
     const project = {
-      identifier: 'rock-around-clock',
-      user_id: 'cee6040f-caf6-4029-b758-98f5ad9c0c7a'
-    }
+      identifier: "rock-around-clock",
+      user_id: "cee6040f-caf6-4029-b758-98f5ad9c0c7a",
+    };
 
-    test('isOwner returns false', () => {
-      expect(isOwner(user, project)).toBeFalsy()
-    })
-  })
+    test("isOwner returns false", () => {
+      expect(isOwner(user, project)).toBeFalsy();
+    });
+  });
 
-  describe('and unsaved project', () => {
+  describe("and unsaved project", () => {
     const project = {
       identifier: undefined,
-    }
+    };
 
-    test('isOwner returns false', () => {
-      expect(isOwner(user, project)).toBeFalsy()
-    })
-  })
-})
+    test("isOwner returns false", () => {
+      expect(isOwner(user, project)).toBeFalsy();
+    });
+  });
+});
diff --git a/src/web-component.js b/src/web-component.js
index d55d596ec..5d1693d75 100644
--- a/src/web-component.js
+++ b/src/web-component.js
@@ -1,12 +1,12 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import * as ReactDOMClient from 'react-dom/client';
-import * as Sentry from '@sentry/react'
-import { BrowserTracing } from '@sentry/tracing';
-import WebComponentLoader from './components/WebComponent/WebComponentLoader/WebComponentLoader';
-import store from './app/store'
-import { Provider } from 'react-redux'
-import './i18n';
+import React from "react";
+import ReactDOM from "react-dom";
+import * as ReactDOMClient from "react-dom/client";
+import * as Sentry from "@sentry/react";
+import { BrowserTracing } from "@sentry/tracing";
+import WebComponentLoader from "./components/WebComponent/WebComponentLoader/WebComponentLoader";
+import store from "./app/store";
+import { Provider } from "react-redux";
+import "./i18n";
 
 Sentry.init({
   dsn: process.env.REACT_APP_SENTRY_DSN,
@@ -17,7 +17,7 @@ Sentry.init({
   // of transactions for performance monitoring.
   // We recommend adjusting this value in production
   tracesSampleRate: 1.0,
-})
+});
 
 class WebComponent extends HTMLElement {
   root;
@@ -34,7 +34,7 @@ class WebComponent extends HTMLElement {
   }
 
   static get observedAttributes() {
-    return ['code', 'sense_hat_always_enabled'];
+    return ["code", "sense_hat_always_enabled"];
   }
 
   attributeChangedCallback(name, _oldVal, newVal) {
@@ -58,7 +58,7 @@ class WebComponent extends HTMLElement {
   set menuItems(newValue) {
     // update properties in the web component via js calls from host app
     // see public/web-component/index.html
-    console.log('menu items set')
+    console.log("menu items set");
     this.componentProperties.menuItems = newValue;
 
     this.mountReactApp();
@@ -70,21 +70,21 @@ class WebComponent extends HTMLElement {
 
   mountReactApp() {
     if (!this.mountPoint) {
-      this.mountPoint = document.createElement('div');
+      this.mountPoint = document.createElement("div");
       this.mountPoint.setAttribute("id", "root");
       this.mountPoint.setAttribute("style", "height: 100%");
-      this.attachShadow({ mode: 'open' }).appendChild(this.mountPoint);
+      this.attachShadow({ mode: "open" }).appendChild(this.mountPoint);
       this.root = ReactDOMClient.createRoot(this.mountPoint);
     }
 
     this.root.render(
       <React.StrictMode>
         <Provider store={store}>
-            <WebComponentLoader { ...this.reactProps() }/>
+          <WebComponentLoader {...this.reactProps()} />
         </Provider>
-      </React.StrictMode>
+      </React.StrictMode>,
     );
   }
 }
 
-window.customElements.define('editor-wc', WebComponent);
+window.customElements.define("editor-wc", WebComponent);
diff --git a/yarn.lock b/yarn.lock
index 063c98039..2c1055b47 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5771,6 +5771,11 @@ escodegen@^2.0.0:
   optionalDependencies:
     source-map "~0.6.1"
 
+eslint-config-prettier@^8.8.0:
+  version "8.8.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348"
+  integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==
+
 eslint-config-react-app@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e"
@@ -5852,6 +5857,13 @@ eslint-plugin-jsx-a11y@^6.3.1:
     object.fromentries "^2.0.6"
     semver "^6.3.0"
 
+eslint-plugin-prettier@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b"
+  integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==
+  dependencies:
+    prettier-linter-helpers "^1.0.0"
+
 eslint-plugin-react-hooks@^4.2.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
@@ -6271,6 +6283,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
   integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
 
+fast-diff@^1.1.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
+  integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
+
 fast-glob@^2.2.6:
   version "2.2.7"
   resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@@ -11028,6 +11045,18 @@ prepend-http@^1.0.0:
   resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
   integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==
 
+prettier-linter-helpers@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
+  integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
+  dependencies:
+    fast-diff "^1.1.2"
+
+prettier@^2.8.8:
+  version "2.8.8"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
+  integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
+
 pretty-bytes@^5.3.0, pretty-bytes@^5.6.0:
   version "5.6.0"
   resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"