From fcdc4c6b6fb1c49c855286ff29c2a973fb355fd8 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 10:11:13 +0200 Subject: [PATCH 01/11] Improve tests --- ui-tests/tests/jupyterlite_xeus.spec.ts | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 15027c76..44d74c92 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -2,6 +2,18 @@ import { test } from '@jupyterlab/galata'; import { expect } from '@playwright/test'; +async function runAndCheckNotebook(page: any, notebook: string) { + await page.notebook.open(notebook); + await page.notebook.runCellByCell(); + + const nCells = await page.notebook.getCellCount(); + + for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { + const output = await page.notebook.getCellTextOutput(cellIdx); + expect(output).toBeTruthy(); + } +} + test.describe('General Tests', () => { test.beforeEach(({ page }) => { page.setDefaultTimeout(600000); @@ -42,33 +54,20 @@ test.describe('General Tests', () => { test('xeus-cpp should execute code', async ({ page }) => { await page.goto('lab/index.html'); - let notebook = 'cpp.ipynb'; - - await page.notebook.open(notebook); - await page.notebook.runCellByCell(); - - notebook = 'cpp-third-party-libs.ipynb'; - - await page.notebook.open(notebook); - await page.notebook.runCellByCell(); + await runAndCheckNotebook(page, 'cpp.ipynb') + await runAndCheckNotebook(page, 'cpp-third-party-libs.ipynb') }); test('xeus-python should execute code', async ({ page }) => { await page.goto('lab/index.html'); - const notebook = 'Lorenz.ipynb'; - - await page.notebook.open(notebook); - await page.notebook.runCellByCell(); + await runAndCheckNotebook(page, 'Lorenz.ipynb') }); test('xeus-r should execute code', async ({ page }) => { await page.goto('lab/index.html'); - const notebook = 'r.ipynb'; - - await page.notebook.open(notebook); - await page.notebook.runCellByCell(); + await runAndCheckNotebook(page, 'r.ipynb') }); test('(Multi-kernels test) xeus-python from env-default should execute some code', async ({ From 6df1b84eb4fd0fd6b321e7977b98732b3ef077be Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 10:13:28 +0200 Subject: [PATCH 02/11] Linter --- ui-tests/tests/jupyterlite_xeus.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 44d74c92..3d55d881 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -54,20 +54,20 @@ test.describe('General Tests', () => { test('xeus-cpp should execute code', async ({ page }) => { await page.goto('lab/index.html'); - await runAndCheckNotebook(page, 'cpp.ipynb') - await runAndCheckNotebook(page, 'cpp-third-party-libs.ipynb') + await runAndCheckNotebook(page, 'cpp.ipynb'); + await runAndCheckNotebook(page, 'cpp-third-party-libs.ipynb'); }); test('xeus-python should execute code', async ({ page }) => { await page.goto('lab/index.html'); - await runAndCheckNotebook(page, 'Lorenz.ipynb') + await runAndCheckNotebook(page, 'Lorenz.ipynb'); }); test('xeus-r should execute code', async ({ page }) => { await page.goto('lab/index.html'); - await runAndCheckNotebook(page, 'r.ipynb') + await runAndCheckNotebook(page, 'r.ipynb'); }); test('(Multi-kernels test) xeus-python from env-default should execute some code', async ({ From 4907135f1aa4d98ca2f7b9032e01a997980150be Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 12:54:38 +0200 Subject: [PATCH 03/11] Make a notebook fail for testing --- ui-tests/notebooks/Lorenz.ipynb | 221 +++++++++++++++++------- ui-tests/tests/jupyterlite_xeus.spec.ts | 10 +- 2 files changed, 167 insertions(+), 64 deletions(-) diff --git a/ui-tests/notebooks/Lorenz.ipynb b/ui-tests/notebooks/Lorenz.ipynb index d557ea49..b67d8de3 100644 --- a/ui-tests/notebooks/Lorenz.ipynb +++ b/ui-tests/notebooks/Lorenz.ipynb @@ -1,155 +1,258 @@ { - "metadata": { - "kernelspec": { - "name": "xpython (env-python)", - "display_name": "Python 3.13 (XPython) [env-python]", - "language": "python" - }, - "language_info": { - "codemirror_mode": { - "name": "python", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8" - } - }, - "nbformat_minor": 4, - "nbformat": 4, "cells": [ { "cell_type": "markdown", - "source": "# The Lorenz Differential Equations", - "metadata": {} + "metadata": {}, + "source": [ + "# The Lorenz Differential Equations" + ] }, { "cell_type": "markdown", - "source": "Before we start, we import some preliminary libraries.", - "metadata": {} + "metadata": {}, + "source": [ + "Before we start, we import some preliminary libraries." + ] }, { "cell_type": "code", - "source": "import numpy as np\nfrom matplotlib import pyplot as plt\nfrom scipy import integrate\n\nfrom ipywidgets import interactive", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "from scipy import integrate\n", + "\n", + "from ipywidgets import interactive" + ] }, { "cell_type": "markdown", - "source": "We will also define the actual solver and plotting routine.", - "metadata": {} + "metadata": {}, + "source": [ + "We will also define the actual solver and plotting routine." + ] }, { "cell_type": "code", - "source": "def solve_lorenz(sigma=10.0, beta=8./3, rho=28.0):\n \"\"\"Plot a solution to the Lorenz differential equations.\"\"\"\n\n max_time = 4.0\n N = 30\n\n fig = plt.figure(1)\n ax = fig.add_axes([0, 0, 1, 1], projection='3d')\n ax.axis('off')\n\n # prepare the axes limits\n ax.set_xlim((-25, 25))\n ax.set_ylim((-35, 35))\n ax.set_zlim((5, 55))\n\n def lorenz_deriv(x_y_z, t0, sigma=sigma, beta=beta, rho=rho):\n \"\"\"Compute the time-derivative of a Lorenz system.\"\"\"\n x, y, z = x_y_z\n return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]\n\n # Choose random starting points, uniformly distributed from -15 to 15\n np.random.seed(1)\n x0 = -15 + 30 * np.random.random((N, 3))\n\n # Solve for the trajectories\n t = np.linspace(0, max_time, int(250*max_time))\n x_t = np.asarray([integrate.odeint(lorenz_deriv, x0i, t)\n for x0i in x0])\n\n # choose a different color for each trajectory\n colors = plt.cm.viridis(np.linspace(0, 1, N))\n\n for i in range(N):\n x, y, z = x_t[i,:,:].T\n lines = ax.plot(x, y, z, '-', c=colors[i])\n plt.setp(lines, linewidth=2)\n angle = 104\n ax.view_init(30, angle)\n plt.show()\n\n return t, x_t", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "def solve_lorenz(sigma=10.0, beta=8./3, rho=28.0):\n", + " \"\"\"Plot a solution to the Lorenz differential equations.\"\"\"\n", + "\n", + " max_time = 4.0\n", + " N = 30\n", + "\n", + " fig = plt.figure(1)\n", + " ax = fig.add_axes([0, 0, 1, 1], projection='3d')\n", + " ax.axis('off')\n", + "\n", + " # prepare the axes limits\n", + " ax.set_xlim((-25, 25))\n", + " ax.set_ylim((-35, 35))\n", + " ax.set_zlim((5, 55))\n", + "\n", + " def lorenz_deriv(x_y_z, t0, sigma=sigma, beta=beta, rho=rho):\n", + " \"\"\"Compute the time-derivative of a Lorenz system.\"\"\"\n", + " x, y, z = x_y_z\n", + " return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]\n", + "\n", + " # Choose random starting points, uniformly distributed from -15 to 15\n", + " np.random.seed(1)\n", + " x0 = -15 + 30 * np.random.random((N, 3))\n", + "\n", + " # Solve for the trajectories\n", + " t = np.linspace(0, max_time, int(250*max_time))\n", + " x_t = np.asarray([integrate.odeint(lorenz_deriv, x0i, t)\n", + " for x0i in x0])\n", + "\n", + " # choose a different color for each trajectory\n", + " colors = plt.cm.viridis(np.linspace(0, 1, N))\n", + "\n", + " for i in range(N):\n", + " x, y, z = x_t[i,:,:].T\n", + " lines = ax.plot(x, y, z, '-', c=colors[i])\n", + " plt.setp(lines, linewidth=2)\n", + " angle = 104\n", + " ax.view_init(30, angle)\n", + " plt.show()\n", + "\n", + " return t, x_t" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "raise RuntimeError('yo')" + ] }, { "cell_type": "markdown", - "source": "We explore the Lorenz system of differential equations:\n\n$$\n\\begin{aligned}\n\\dot{x} & = \\sigma(y-x) \\\\\n\\dot{y} & = \\rho x - y - xz \\\\\n\\dot{z} & = -\\beta z + xy\n\\end{aligned}\n$$\n\nLet's change (\\\\(\\sigma\\\\), \\\\(\\beta\\\\), \\\\(\\rho\\\\)) with ipywidgets and examine the trajectories.", - "metadata": {} + "metadata": {}, + "source": [ + "We explore the Lorenz system of differential equations:\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "\\dot{x} & = \\sigma(y-x) \\\\\n", + "\\dot{y} & = \\rho x - y - xz \\\\\n", + "\\dot{z} & = -\\beta z + xy\n", + "\\end{aligned}\n", + "$$\n", + "\n", + "Let's change (\\\\(\\sigma\\\\), \\\\(\\beta\\\\), \\\\(\\rho\\\\)) with ipywidgets and examine the trajectories." + ] }, { "cell_type": "code", - "source": "w=interactive(solve_lorenz,sigma=(0.0,50.0),rho=(0.0,50.0))\nw", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "w=interactive(solve_lorenz,sigma=(0.0,50.0),rho=(0.0,50.0))\n", + "w" + ] }, { "cell_type": "markdown", - "source": "For the default set of parameters, we see the trajectories swirling around two points, called attractors. ", - "metadata": {} + "metadata": {}, + "source": [ + "For the default set of parameters, we see the trajectories swirling around two points, called attractors. " + ] }, { "cell_type": "markdown", - "source": "The object returned by `interactive` is a `Widget` object and it has attributes that contain the current result and arguments:", - "metadata": {} + "metadata": {}, + "source": [ + "The object returned by `interactive` is a `Widget` object and it has attributes that contain the current result and arguments:" + ] }, { "cell_type": "code", - "source": "t, x_t = w.result", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "t, x_t = w.result" + ] }, { "cell_type": "code", - "source": "w.kwargs", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "w.kwargs" + ] }, { "cell_type": "markdown", - "source": "After interacting with the system, we can take the result and perform further computations. In this case, we compute the average positions in \\\\(x\\\\), \\\\(y\\\\) and \\\\(z\\\\).", - "metadata": {} + "metadata": {}, + "source": [ + "After interacting with the system, we can take the result and perform further computations. In this case, we compute the average positions in \\\\(x\\\\), \\\\(y\\\\) and \\\\(z\\\\)." + ] }, { "cell_type": "code", - "source": "xyz_avg = x_t.mean(axis=1)", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "xyz_avg = x_t.mean(axis=1)" + ] }, { "cell_type": "code", - "source": "xyz_avg.shape", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "xyz_avg.shape" + ] }, { "cell_type": "markdown", - "source": "Creating histograms of the average positions (across different trajectories) show that, on average, the trajectories swirl about the attractors.", - "metadata": {} + "metadata": {}, + "source": [ + "Creating histograms of the average positions (across different trajectories) show that, on average, the trajectories swirl about the attractors." + ] }, { "cell_type": "code", - "source": "from matplotlib import pyplot as plt\n%matplotlib inline", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "from matplotlib import pyplot as plt\n", + "%matplotlib inline" + ] }, { "cell_type": "code", - "source": "plt.hist(xyz_avg[:,0])\nplt.title('Average $x(t)$');", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "plt.hist(xyz_avg[:,0])\n", + "plt.title('Average $x(t)$');" + ] }, { "cell_type": "code", - "source": "plt.hist(xyz_avg[:,1])\nplt.title('Average $y(t)$');", + "execution_count": null, "metadata": { "trusted": true }, "outputs": [], - "execution_count": null + "source": [ + "plt.hist(xyz_avg[:,1])\n", + "plt.title('Average $y(t)$');" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.13 (XPython) [env-python]", + "language": "python", + "name": "xpython (env-python)" + }, + "language_info": { + "codemirror_mode": { + "name": "python", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8" } - ] -} \ No newline at end of file + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 3d55d881..a6a6add9 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -6,12 +6,12 @@ async function runAndCheckNotebook(page: any, notebook: string) { await page.notebook.open(notebook); await page.notebook.runCellByCell(); - const nCells = await page.notebook.getCellCount(); + // const nCells = await page.notebook.getCellCount(); - for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { - const output = await page.notebook.getCellTextOutput(cellIdx); - expect(output).toBeTruthy(); - } + // for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { + // const output = await page.notebook.getCellTextOutput(cellIdx); + // expect(output).toBeTruthy(); + // } } test.describe('General Tests', () => { From dc020b38ff5b5312f392b035fee7ecca06400c70 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 13:09:30 +0200 Subject: [PATCH 04/11] Try failing on exec failure --- ui-tests/tests/jupyterlite_xeus.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index a6a6add9..405a7d54 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -4,7 +4,7 @@ import { expect } from '@playwright/test'; async function runAndCheckNotebook(page: any, notebook: string) { await page.notebook.open(notebook); - await page.notebook.runCellByCell(); + expect(await page.notebook.runCellByCell()).toBeTruthy(); // const nCells = await page.notebook.getCellCount(); From bbaf85430287e6467efa4ad2d8ca013c7c0b282d Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 13:46:35 +0200 Subject: [PATCH 05/11] Try --- ui-tests/tests/jupyterlite_xeus.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 405a7d54..898071be 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -6,12 +6,12 @@ async function runAndCheckNotebook(page: any, notebook: string) { await page.notebook.open(notebook); expect(await page.notebook.runCellByCell()).toBeTruthy(); - // const nCells = await page.notebook.getCellCount(); + const nCells = await page.notebook.getCellCount(); - // for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { - // const output = await page.notebook.getCellTextOutput(cellIdx); - // expect(output).toBeTruthy(); - // } + for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { + // @ts-expect-error: missing typing for galata + expect(window.galata.haveBeenExecuted(cellIdx)); + } } test.describe('General Tests', () => { From d9313e841d9c26f44bdcdfc2bab8ba5fed0183a3 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 14:57:36 +0200 Subject: [PATCH 06/11] Try another approach --- ui-tests/tests/jupyterlite_xeus.spec.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 898071be..11557826 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -1,16 +1,22 @@ -import { test } from '@jupyterlab/galata'; +import { IJupyterLabPageFixture, test } from '@jupyterlab/galata'; import { expect } from '@playwright/test'; -async function runAndCheckNotebook(page: any, notebook: string) { +async function runAndCheckNotebook( + page: IJupyterLabPageFixture, + notebook: string +) { await page.notebook.open(notebook); expect(await page.notebook.runCellByCell()).toBeTruthy(); const nCells = await page.notebook.getCellCount(); for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { - // @ts-expect-error: missing typing for galata - expect(window.galata.haveBeenExecuted(cellIdx)); + expect( + await page.evaluate(cellIdx => { + return Promise.resolve(window.galata.haveBeenExecuted(cellIdx)); + }, cellIdx) + ).toBeTruthy(); } } From 648fec889455e82679a9cdbca5c87be2a546c6c6 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 15:33:04 +0200 Subject: [PATCH 07/11] Dumb debug --- ui-tests/tests/jupyterlite_xeus.spec.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 11557826..9efd95f3 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -9,15 +9,11 @@ async function runAndCheckNotebook( await page.notebook.open(notebook); expect(await page.notebook.runCellByCell()).toBeTruthy(); - const nCells = await page.notebook.getCellCount(); - - for (let cellIdx = 0; cellIdx < nCells; cellIdx++) { - expect( - await page.evaluate(cellIdx => { - return Promise.resolve(window.galata.haveBeenExecuted(cellIdx)); - }, cellIdx) - ).toBeTruthy(); - } + expect( + await page.evaluate(() => { + return Promise.resolve(window.galata.haveBeenExecuted()); + }) + ).toBeTruthy(); } test.describe('General Tests', () => { @@ -68,12 +64,16 @@ test.describe('General Tests', () => { await page.goto('lab/index.html'); await runAndCheckNotebook(page, 'Lorenz.ipynb'); + + expect('3').toBeNull(); }); test('xeus-r should execute code', async ({ page }) => { await page.goto('lab/index.html'); await runAndCheckNotebook(page, 'r.ipynb'); + + expect('3').toBeNull(); }); test('(Multi-kernels test) xeus-python from env-default should execute some code', async ({ From e52e64d3c029dea88bda35fd3c98a9176106e372 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 16:22:58 +0200 Subject: [PATCH 08/11] Try another approach --- ui-tests/tests/jupyterlite_xeus.spec.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 9efd95f3..61af6ebb 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -7,7 +7,21 @@ async function runAndCheckNotebook( notebook: string ) { await page.notebook.open(notebook); - expect(await page.notebook.runCellByCell()).toBeTruthy(); + + // Wait for the notebook to be ready + await page.waitForSelector('.jp-Notebook.jp-mod-commandMode'); + + // Execute "Restart Kernel and Run All Cells..." + // This is stupid that we have to do this really, but this is the only way + // I found to get galata to stop the execution upon error and detect an error + await page.menu.clickMenuItem('Kernel>Restart Kernel and Run All Cells…'); + await page.getByRole('button', { name: 'Confirm Kernel Restart' }).click(); + + // Wait for the notebook to be in command mode after restart + await page.waitForSelector('.jp-Notebook.jp-mod-commandMode'); + + // Verify the kernel status shows it's idle (not busy) + await page.locator('.jp-KernelStatus-success').waitFor(); expect( await page.evaluate(() => { @@ -64,16 +78,12 @@ test.describe('General Tests', () => { await page.goto('lab/index.html'); await runAndCheckNotebook(page, 'Lorenz.ipynb'); - - expect('3').toBeNull(); }); test('xeus-r should execute code', async ({ page }) => { await page.goto('lab/index.html'); await runAndCheckNotebook(page, 'r.ipynb'); - - expect('3').toBeNull(); }); test('(Multi-kernels test) xeus-python from env-default should execute some code', async ({ From c634cfa2c4d48c02ada6a4aa232070ec766b2a54 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 16:50:20 +0200 Subject: [PATCH 09/11] Try another approach --- ui-tests/notebooks/cpp.ipynb | 23 ----------------------- ui-tests/tests/jupyterlite_xeus.spec.ts | 24 ++++-------------------- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/ui-tests/notebooks/cpp.ipynb b/ui-tests/notebooks/cpp.ipynb index cde4e74f..92421f33 100644 --- a/ui-tests/notebooks/cpp.ipynb +++ b/ui-tests/notebooks/cpp.ipynb @@ -76,29 +76,6 @@ "std::cout << \"some output\" << std::endl;" ] }, - { - "cell_type": "code", - "execution_count": 2, - "id": "9622f20f-5925-4544-a97b-aada3a14209a", - "metadata": { - "trusted": true, - "vscode": { - "languageId": "c++" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "some error\n" - ] - } - ], - "source": [ - "std::cerr << \"some error\" << std::endl;" - ] - }, { "cell_type": "code", "execution_count": 3, diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index 61af6ebb..b4159000 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -8,26 +8,10 @@ async function runAndCheckNotebook( ) { await page.notebook.open(notebook); - // Wait for the notebook to be ready - await page.waitForSelector('.jp-Notebook.jp-mod-commandMode'); - - // Execute "Restart Kernel and Run All Cells..." - // This is stupid that we have to do this really, but this is the only way - // I found to get galata to stop the execution upon error and detect an error - await page.menu.clickMenuItem('Kernel>Restart Kernel and Run All Cells…'); - await page.getByRole('button', { name: 'Confirm Kernel Restart' }).click(); - - // Wait for the notebook to be in command mode after restart - await page.waitForSelector('.jp-Notebook.jp-mod-commandMode'); - - // Verify the kernel status shows it's idle (not busy) - await page.locator('.jp-KernelStatus-success').waitFor(); - - expect( - await page.evaluate(() => { - return Promise.resolve(window.galata.haveBeenExecuted()); - }) - ).toBeTruthy(); + await page.notebook.runCellByCell(); + + const stderrElements = page.locator('[data-mime-type="application/vnd.jupyter.stderr"]'); + await expect(stderrElements).toHaveCount(0); } test.describe('General Tests', () => { From c3dee092623d6a79eb7301bfd1c4e668ec412df0 Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 16:52:22 +0200 Subject: [PATCH 10/11] Linter --- ui-tests/tests/jupyterlite_xeus.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui-tests/tests/jupyterlite_xeus.spec.ts b/ui-tests/tests/jupyterlite_xeus.spec.ts index b4159000..c6fcfa24 100644 --- a/ui-tests/tests/jupyterlite_xeus.spec.ts +++ b/ui-tests/tests/jupyterlite_xeus.spec.ts @@ -10,7 +10,9 @@ async function runAndCheckNotebook( await page.notebook.runCellByCell(); - const stderrElements = page.locator('[data-mime-type="application/vnd.jupyter.stderr"]'); + const stderrElements = page.locator( + '[data-mime-type="application/vnd.jupyter.stderr"]' + ); await expect(stderrElements).toHaveCount(0); } From c368c0a10609c49b5de67d8e18908386df57f5bf Mon Sep 17 00:00:00 2001 From: martinRenou Date: Tue, 2 Sep 2025 17:08:02 +0200 Subject: [PATCH 11/11] Make it green --- ui-tests/notebooks/Lorenz.ipynb | 9 --------- ui-tests/notebooks/r.ipynb | 31 ------------------------------- 2 files changed, 40 deletions(-) diff --git a/ui-tests/notebooks/Lorenz.ipynb b/ui-tests/notebooks/Lorenz.ipynb index b67d8de3..55408189 100644 --- a/ui-tests/notebooks/Lorenz.ipynb +++ b/ui-tests/notebooks/Lorenz.ipynb @@ -87,15 +87,6 @@ " return t, x_t" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "raise RuntimeError('yo')" - ] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/ui-tests/notebooks/r.ipynb b/ui-tests/notebooks/r.ipynb index 8b7b5b1a..46627283 100644 --- a/ui-tests/notebooks/r.ipynb +++ b/ui-tests/notebooks/r.ipynb @@ -165,13 +165,6 @@ "## Plotting" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Some of the following R Code was pulled from https://www.datacamp.com/doc/r/graphics-with-ggplot2, and updated to use newer `ggplot2` APIs." - ] - }, { "cell_type": "code", "execution_count": null, @@ -413,30 +406,6 @@ "print(hsv_color)\n", "print(lab_color)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true, - "vscode": { - "languageId": "r" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "trusted": true, - "vscode": { - "languageId": "r" - } - }, - "outputs": [], - "source": [] } ], "metadata": {