Skip to content

Commit ca0cfb5

Browse files
authored
Fix stop button in the web component (#1083)
1 parent 801c591 commit ca0cfb5

File tree

4 files changed

+97
-31
lines changed

4 files changed

+97
-31
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88

99
### Fixed
1010

11-
- Enabling web component to find the `turtle` canvas
11+
- Enabling web component to find the `turtle` canvas (#1082)
12+
- Ability to stop code in the web component (#1083)
1213

1314
## [0.27.0] - 2024-09-26
1415

cypress/e2e/spec-wc.cy.js

Lines changed: 93 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ describe("default behaviour", () => {
3838
.should("contain", "Hello world");
3939
});
4040

41+
it("interrupts the code when the stop button is clicked", () => {
42+
cy.get("editor-wc")
43+
.shadow()
44+
.find("div[class=cm-content]")
45+
.invoke(
46+
"text",
47+
"from time import sleep\nfor i in range(100):\n\tprint(i)\n\tsleep(1)",
48+
);
49+
cy.get("editor-wc").shadow().find(".btn--run").click();
50+
cy.get("editor-wc").shadow().find(".btn--stop").click();
51+
cy.get("editor-wc")
52+
.shadow()
53+
.find(".error-message__content")
54+
.should("contain", "Execution interrupted");
55+
});
56+
4157
it("runs p5 code", () => {
4258
const code = `from p5 import *\n\ndef setup():\n size(400, 400) # width and height of screen\n\ndef draw():\n fill('cyan') # Set the fill color for the sky to cyan\n rect(0, 0, 400, 250) # Draw a rectangle for the sky with these values for x, y, width, height \n \nrun(frame_rate=2)\n`;
4359
cy.get("editor-wc")
@@ -61,7 +77,10 @@ describe("default behaviour", () => {
6177
.find("div[class=cm-content]")
6278
.invoke("text", "import sense_hat");
6379
cy.get("editor-wc").shadow().find(".btn--run").click();
64-
cy.get("editor-wc").shadow().find("#root").should("contain", "Visual output");
80+
cy.get("editor-wc")
81+
.shadow()
82+
.find("#root")
83+
.should("contain", "Visual output");
6584
});
6685

6786
it("does not render astro pi component on page load", () => {
@@ -84,7 +103,10 @@ describe("default behaviour", () => {
84103
.find("div[class=cm-content]")
85104
.invoke("text", "import sense_hat");
86105
cy.get("editor-wc").shadow().find(".btn--run").click();
87-
cy.get("editor-wc").shadow().find("div[class=cm-content]").invoke("text", "");
106+
cy.get("editor-wc")
107+
.shadow()
108+
.find("div[class=cm-content]")
109+
.invoke("text", "");
88110
cy.get("editor-wc").shadow().find(".btn--run").click();
89111
cy.get("editor-wc").shadow().contains("Visual output").click();
90112
cy.get("editor-wc").shadow().find("#root").should("not.contain", "yaw");
@@ -106,7 +128,7 @@ describe("when load_remix_disabled is true, e.g. in editor-standalone", () => {
106128
};
107129

108130
beforeEach(() => {
109-
cy.on('window:before:load', (win) => {
131+
cy.on("window:before:load", (win) => {
110132
win.localStorage.setItem(authKey, JSON.stringify(user));
111133
});
112134
});
@@ -124,22 +146,33 @@ describe("when load_remix_disabled is true, e.g. in editor-standalone", () => {
124146

125147
// Check receipt of an event to trigger a redirect to the remixed project URL
126148
cy.get("#project-identifier").should("not.have.text", originalIdentifier);
127-
cy.get("#project-identifier").invoke("text").then((remixIdentifier) => {
128-
// Check we're still seeing the changed code
129-
cy.get("editor-wc").shadow().find("[contenteditable]").should("have.text", "# remixed!");
130-
131-
// Visit the original project again
132-
cy.visit(urlFor(originalIdentifier));
133-
134-
// Check we no longer see the changed code, i.e. `load_remix_disabled=true` is respected
135-
cy.get("editor-wc").shadow().find("[contenteditable]").should("not.have.text", "# remixed!");
136-
137-
// View the remixed project
138-
cy.visit(urlFor(remixIdentifier));
139-
140-
// Check we're still seeing the changed code
141-
cy.get("editor-wc").shadow().find("[contenteditable]").should("have.text", "# remixed!");
142-
});
149+
cy.get("#project-identifier")
150+
.invoke("text")
151+
.then((remixIdentifier) => {
152+
// Check we're still seeing the changed code
153+
cy.get("editor-wc")
154+
.shadow()
155+
.find("[contenteditable]")
156+
.should("have.text", "# remixed!");
157+
158+
// Visit the original project again
159+
cy.visit(urlFor(originalIdentifier));
160+
161+
// Check we no longer see the changed code, i.e. `load_remix_disabled=true` is respected
162+
cy.get("editor-wc")
163+
.shadow()
164+
.find("[contenteditable]")
165+
.should("not.have.text", "# remixed!");
166+
167+
// View the remixed project
168+
cy.visit(urlFor(remixIdentifier));
169+
170+
// Check we're still seeing the changed code
171+
cy.get("editor-wc")
172+
.shadow()
173+
.find("[contenteditable]")
174+
.should("have.text", "# remixed!");
175+
});
143176
});
144177
});
145178

@@ -160,41 +193,73 @@ describe("when embedded, output_only & output_split_view are true", () => {
160193
// Check text output panel is visible and has a run button
161194
// Important to wait for this before making the negative assertions that follow
162195
cy.get("editor-wc").shadow().contains("Text output").should("be.visible");
163-
cy.get("editor-wc").shadow().find("button").contains("Run").should("be.visible");
196+
cy.get("editor-wc")
197+
.shadow()
198+
.find("button")
199+
.contains("Run")
200+
.should("be.visible");
164201

165202
// Check that the side bar is not displayed
166203
cy.get("editor-wc").shadow().contains("Project files").should("not.exist");
167204
// Check that the project bar is not displayed
168-
cy.get("editor-wc").shadow().contains("Don't Collide: Clean Car").should("not.exist");
205+
cy.get("editor-wc")
206+
.shadow()
207+
.contains("Don't Collide: Clean Car")
208+
.should("not.exist");
169209
// Check that the editor input containing the code is not displayed
170-
cy.get("editor-wc").shadow().contains("# The draw_obstacle function goes here").should("not.exist");
210+
cy.get("editor-wc")
211+
.shadow()
212+
.contains("# The draw_obstacle function goes here")
213+
.should("not.exist");
171214

172215
// Run the code and check it executed without error
173216
cy.get("editor-wc").shadow().find("button").contains("Run").click();
174217
cy.get("#results").should("contain", '{"errorDetails":{}}');
175218

176219
// Check that the visual output panel is displayed in split view mode (vs tabbed view)
177220
cy.get("editor-wc").shadow().contains("Visual output").should("be.visible");
178-
cy.get("editor-wc").shadow().contains("Visual output").parents("ul").children().should("have.length", 1);
221+
cy.get("editor-wc")
222+
.shadow()
223+
.contains("Visual output")
224+
.parents("ul")
225+
.children()
226+
.should("have.length", 1);
179227
});
180228

181229
it("displays the embedded view for an HTML project", () => {
182230
cy.visit(urlFor("anime-expressions-solution"));
183231

184232
// Check HTML preview output panel is visible and has a run button
185233
// Important to wait for this before making the negative assertions that follow
186-
cy.get("editor-wc").shadow().contains("index.html preview").should("be.visible");
187-
cy.get("editor-wc").shadow().find("button").contains("Run").should("be.visible");
234+
cy.get("editor-wc")
235+
.shadow()
236+
.contains("index.html preview")
237+
.should("be.visible");
238+
cy.get("editor-wc")
239+
.shadow()
240+
.find("button")
241+
.contains("Run")
242+
.should("be.visible");
188243

189244
// Check that the code has automatically run i.e. the HTML has been rendered
190-
cy.get("editor-wc").shadow().find("iframe#output-frame").its("0.contentDocument.body").should("contain", "Draw anime with me");
245+
cy.get("editor-wc")
246+
.shadow()
247+
.find("iframe#output-frame")
248+
.its("0.contentDocument.body")
249+
.should("contain", "Draw anime with me");
191250

192251
// Check that the side bar is not displayed
193252
cy.get("editor-wc").shadow().contains("Project files").should("not.exist");
194253
// Check that the project bar is not displayed
195-
cy.get("editor-wc").shadow().contains("Anime expressions solution").should("not.exist");
254+
cy.get("editor-wc")
255+
.shadow()
256+
.contains("Anime expressions solution")
257+
.should("not.exist");
196258
// Check that the editor input containing the code is not displayed
197-
cy.get("editor-wc").shadow().contains("<h1>Draw anime with me</h1>").should("not.exist");
259+
cy.get("editor-wc")
260+
.shadow()
261+
.contains("<h1>Draw anime with me</h1>")
262+
.should("not.exist");
198263

199264
// Run the code and check it executed without error
200265
cy.get("editor-wc").shadow().find("button").contains("Run").click();

cypress/e2e/spec.cy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ it("Interrupts py5 draws when stop button clicked", () => {
99
cy.visit(baseUrl);
1010
cy.get("div[class=cm-content]").invoke(
1111
"text",
12-
"import py5\ndef setup():\n\tsize(400, 400)\ndef draw():\n\tbackground(255)\nrun()",
12+
"import py5\ndef setup():\n\tpy5.size(400, 400)\ndef draw():\n\tpy5.background(255)\npy5.run_sketch()",
1313
);
1414
cy.get(".btn--run").click();
1515

src/components/Editor/Runners/PythonRunner/PythonRunner.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from "../../../../redux/EditorSlice";
1717
import ErrorMessage from "../../ErrorMessage/ErrorMessage";
1818
import { createError } from "../../../../utils/apiCallHandler";
19-
import store from "../../../../app/store";
19+
import store from "../../../../redux/stores/WebComponentStore";
2020
import VisualOutputPane from "./VisualOutputPane";
2121
import OutputViewToggle from "./OutputViewToggle";
2222
import { SettingsContext } from "../../../../utils/settings";

0 commit comments

Comments
 (0)