Skip to content

Commit

Permalink
Fix skulpt support for output panels attribute (#1158)
Browse files Browse the repository at this point in the history
  • Loading branch information
loiswells97 authored Jan 6, 2025
1 parent 8204181 commit bbdfad8
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 97 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

## [0.28.14] - 2025-01-06

### Fixed

- Support for the `outputPanels` attribute in the `SkulptRunner` (#1158)

## [0.28.13] - 2024-12-18

### Changed
Expand Down Expand Up @@ -1019,7 +1027,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- Events in Web Component indicating whether Mission Zero criteria have been met (#113)

[unreleased]: https://github.com/RaspberryPiFoundation/editor-ui/compare/v0.28.13...HEAD
[unreleased]: https://github.com/RaspberryPiFoundation/editor-ui/compare/v0.28.14...HEAD
[0.28.14]: https://github.com/RaspberryPiFoundation/editor-ui/releases/tag/v0.28.14
[0.28.13]: https://github.com/RaspberryPiFoundation/editor-ui/releases/tag/v0.28.13
[0.28.12]: https://github.com/RaspberryPiFoundation/editor-ui/releases/tag/v0.28.12
[0.28.11]: https://github.com/RaspberryPiFoundation/editor-ui/releases/tag/v0.28.11
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@raspberrypifoundation/editor-ui",
"version": "0.28.13",
"version": "0.28.14",
"private": true,
"dependencies": {
"@apollo/client": "^3.7.8",
Expand Down
7 changes: 5 additions & 2 deletions src/components/Editor/Runners/PythonRunner/PythonRunner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const SKULPT_ONLY_MODULES = [
"turtle",
];

const PythonRunner = () => {
const PythonRunner = ({ outputPanels = ["text", "visual"] }) => {
const dispatch = useDispatch();

const project = useSelector((state) => state.editor.project);
Expand Down Expand Up @@ -93,7 +93,10 @@ const PythonRunner = () => {
return (
<>
<PyodideRunner active={activeRunner === "pyodide"} />
<SkulptRunner active={activeRunner === "skulpt"} />
<SkulptRunner
active={activeRunner === "skulpt"}
outputPanels={outputPanels}
/>
</>
);
};
Expand Down
227 changes: 134 additions & 93 deletions src/components/Editor/Runners/PythonRunner/PythonRunner.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render } from "@testing-library/react";
import { render, within } from "@testing-library/react";
import { Provider } from "react-redux";
import { act } from "react-dom/test-utils";
import PythonRunner from "./PythonRunner";
Expand Down Expand Up @@ -56,110 +56,151 @@ const updateRunner = ({
store.dispatch(setSenseHatAlwaysEnabled(senseHatAlwaysEnabled));
});
};
describe("PythonRunner with default props", () => {
beforeEach(() => {
window.crossOriginIsolated = true;
render(
<Provider store={store}>
<PythonRunner />
</Provider>,
);
updateRunner({ code: "print('some loaded code')" });
});

beforeEach(() => {
window.crossOriginIsolated = true;
render(
<Provider store={store}>
<PythonRunner />
</Provider>,
);
updateRunner({ code: "print('some loaded code')" });
});
test("Renders with Pyodide runner initially", () => {
updateRunner({});
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
});

test("Renders with Pyodide runner initially", () => {
updateRunner({});
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
});
test("Uses pyodide when no skulpt-only modules are imported", () => {
updateRunner({ code: "import math" });
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
});

test("Uses pyodide when no skulpt-only modules are imported", () => {
updateRunner({ code: "import math" });
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
});
test("Uses skulpt when skulpt-only modules are imported", () => {
updateRunner({ code: "import p5" });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});

test("Uses skulpt when skulpt-only modules are imported", () => {
updateRunner({ code: "import p5" });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});
test("Uses skulpt when senseHatAlwaysEnabled is true", () => {
updateRunner({ code: "import math", senseHatAlwaysEnabled: true });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});

test("Uses skulpt when senseHatAlwaysEnabled is true", () => {
updateRunner({ code: "import math", senseHatAlwaysEnabled: true });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});
test("Uses skulpt if not cross origin isolated", () => {
window.crossOriginIsolated = false;
updateRunner({ code: "import math" });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});

test("Uses skulpt if not cross origin isolated", () => {
window.crossOriginIsolated = false;
updateRunner({ code: "import math" });
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
});
test("Switches runners if the import has a from clause", () => {
updateRunner({ code: "from p5 import *" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});

test("Switches runners if the import has a from clause", () => {
updateRunner({ code: "from p5 import *" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});
test("Switches runners if the import is indented", () => {
updateRunner({ code: " import p5" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});

test("Switches runners if the import is indented", () => {
updateRunner({ code: " import p5" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});
test("Uses skulpt if the py5 magic comment is used", () => {
updateRunner({ code: "# input.comment.py5" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});

test("Uses skulpt if the py5 magic comment is used", () => {
updateRunner({ code: "# input.comment.py5" });
expect(document.querySelector(".skulptrunner--active")).toBeInTheDocument();
expect(
document.querySelector(".pyodiderunner--active"),
).not.toBeInTheDocument();
});
test("Does not switch runners while the code is running", () => {
updateRunner({ code: "import p5", codeRunTriggered: true });
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});

test("Does not switch runners while the code is running", () => {
updateRunner({ code: "import p5", codeRunTriggered: true });
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});
test("Does not switch runners if the import is in a comment", () => {
updateRunner({ code: "# import p5" });
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});

test("Does not switch runners if the import is in a comment", () => {
updateRunner({ code: "# import p5" });
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});
test("Does not switch runners if the import is in a string", () => {
updateRunner({ code: 'print("import p5")' });
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});

test("Does not switch runners if the import is in a string", () => {
updateRunner({ code: 'print("import p5")' });
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
test("Does not switch runners if the import is in a multiline string", () => {
updateRunner({ code: '"""\nimport p5\n"""' });
expect(
document.querySelector(".pyodiderunner--active"),
).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
});

test("Renders the text output in the skulpt runner", () => {
updateRunner({ code: "import p5" });
const skulptRunner = document.querySelector(".skulptrunner");
expect(
within(skulptRunner).queryByText("output.textOutput"),
).toBeInTheDocument();
});
});

test("Does not switch runners if the import is in a multiline string", () => {
updateRunner({ code: '"""\nimport p5\n"""' });
expect(document.querySelector(".pyodiderunner--active")).toBeInTheDocument();
expect(
document.querySelector(".skulptrunner--active"),
).not.toBeInTheDocument();
describe("PythonRunner with output panels set to visual only", () => {
beforeEach(() => {
window.crossOriginIsolated = true;
render(
<Provider store={store}>
<PythonRunner outputPanels={["visual"]} />
</Provider>,
);
updateRunner({ code: "print('some loaded code')" });
});

test("Does not render text output in the skulpt runner", () => {
updateRunner({ code: "import p5" });
const skulptRunner = document.querySelector(".skulptrunner");
expect(
within(skulptRunner).queryByText("output.textOutput"),
).not.toBeInTheDocument();
});
});

0 comments on commit bbdfad8

Please sign in to comment.