Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with notebook #112

Merged
merged 8 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
- name: Execute integration tests
working-directory: ui-tests
run: |
jlpm playwright test --retries=2
jlpm test --retries=2

- name: Upload Playwright Test report
if: always()
Expand All @@ -151,6 +151,63 @@ jobs:
ui-tests/test-results
ui-tests/playwright-report

integration-tests-notebook:
name: Integration tests notebook
needs: build_extension
runs-on: ubuntu-latest

env:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/pw-browsers

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Download extension package
uses: actions/download-artifact@v3
with:
name: jupyterlab_chat-artifacts

- name: Install the extension
run: |
set -eux
python -m pip install "notebook>=7.0.0,<8" jupyterlab_chat*.whl

- name: Install dependencies
working-directory: ui-tests
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: 0
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
run: jlpm install

- name: Set up browser cache
uses: actions/cache@v3
with:
path: |
${{ github.workspace }}/pw-browsers
key: ${{ runner.os }}-${{ hashFiles('ui-tests/yarn.lock') }}

- name: Install browser
run: jlpm playwright install chromium
working-directory: ui-tests

- name: Execute integration tests
working-directory: ui-tests
run: |
jlpm test:notebook --retries=2

- name: Upload Playwright Test report
if: always()
uses: actions/upload-artifact@v3
with:
name: jupyterlab_chat-notebook-playwright-tests
path: |
ui-tests/test-results
ui-tests/playwright-report

typing-tests:
name: Typing test
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions python/jupyterlab-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
"@jupyter-notebook/application": "^7.2.0",
"@jupyter/docprovider": "^2.1.4",
"@jupyter/ydoc": "^1.1.1",
"@jupyterlab/application": "^4.2.0",
Expand Down
21 changes: 19 additions & 2 deletions python/jupyterlab-chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Distributed under the terms of the Modified BSD License.
*/

import { NotebookShell } from '@jupyter-notebook/application';
import {
ActiveCellManager,
AutocompletionRegistry,
Expand Down Expand Up @@ -517,8 +518,24 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
}

if (inSidePanel && chatPanel) {
// The chat is opened in the chat panel.
app.shell.activateById(chatPanel.id);
/**
* The chat is opened in the chat panel, ensure the chat panel is opened.
*
* NOTES: In Notebook application, the panel is collapsed when using the
* `activateById` when it is already opened.
* See https://github.com/jupyter/notebook/issues/7534
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would indeed be nice to fix this upstream, so we could then remove that logic here and the dependency on @jupyter-notebook/application.

*/
if (app.shell instanceof NotebookShell) {
const shell: NotebookShell = app.shell;
if (
shell.leftHandler?.currentWidget?.id !== chatPanel.id ||
!shell.leftHandler.isVisible
) {
shell.activateById(chatPanel.id);
}
} else {
app.shell.activateById(chatPanel.id);
}

if (chatPanel.openIfExists(filepath)) {
return;
Expand Down
27 changes: 27 additions & 0 deletions ui-tests/jupyter_server_test_config_notebook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

"""Server configuration for integration tests.
!! Never use this configuration in production because it
opens the server to the world and provide access to JupyterLab
JavaScript objects through the global window variable.
"""
from pathlib import Path
import jupyterlab

c.ServerApp.port = 8888
c.ServerApp.port_retries = 0
c.ServerApp.open_browser = False

c.ServerApp.token = ""
c.ServerApp.password = ""
c.ServerApp.disable_check_xsrf = True

c.JupyterNotebookApp.expose_app_in_browser = True

c.LabServerApp.extra_labextensions_path = str(Path(jupyterlab.__file__).parent / "galata")

c.FileContentsManager.delete_to_trash = False

# Uncomment to set server log level to debug level
# c.ServerApp.log_level = "DEBUG"
2 changes: 2 additions & 0 deletions ui-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"private": true,
"scripts": {
"start": "jupyter lab --config jupyter_server_test_config.py",
"start:notebook": "jupyter notebook --config jupyter_server_test_config_notebook.py",
"test": "jlpm playwright test",
"test:notebook": "jlpm playwright test --config=playwright.notebook.config.js",
"test:update": "jlpm playwright test --update-snapshots"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions ui-tests/playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI
},
testIgnore: 'tests/notebook-application.spec.ts',
use: {
contextOptions: {
permissions: ['clipboard-read', 'clipboard-write']
Expand Down
20 changes: 20 additions & 0 deletions ui-tests/playwright.notebook.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/

/**
* Configuration for Playwright using default from @jupyterlab/galata
*/
const baseConfig = require('@jupyterlab/galata/lib/playwright-config');

module.exports = {
...baseConfig,
webServer: {
command: 'jlpm start:notebook',
url: 'http://localhost:8888/tree',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI
},
testMatch: 'tests/notebook-application.spec.ts'
};
65 changes: 65 additions & 0 deletions ui-tests/tests/notebook-application.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/

import { expect, test as base } from '@jupyterlab/galata';

export const test = base.extend({
waitForApplication: async ({ baseURL }, use, testInfo) => {
const waitIsReady = async (page): Promise<void> => {
await page.waitForSelector('#main-panel');
};
await use(waitIsReady);
},
});

test.use({
autoGoto: false,
appPath: '',
viewport: { width: 1024, height: 900 },
});

const NAME = 'my_chat';
const FILENAME = `${NAME}.chat`;

test.describe('#NotebookApp', () => {
test.beforeEach(async ({ page }) => {
// Create a chat file
await page.filebrowser.contents.uploadContent('{}', 'text', FILENAME);
});

test.afterEach(async ({ page }) => {
if (await page.filebrowser.contents.fileExists(FILENAME)) {
await page.filebrowser.contents.deleteFile(FILENAME);
}
});

test('Should open side panel and list existing chats', async ({ page }) => {
await page.goto('tree');
await page.menu.clickMenuItem('View>Left Sidebar>Show Jupyter Chat');
const panel = page.locator('#jp-left-stack');
await expect(panel).toBeVisible();
await expect(panel.locator('.jp-lab-chat-sidepanel')).toBeVisible();

const select = panel.locator(
'.jp-SidePanel-toolbar .jp-Toolbar-item.jp-lab-chat-open select'
);

await expect(select.locator('option')).toHaveCount(2);
await expect(select.locator('option').last()).toHaveText(NAME);
});

test('Should open main panel in a separate tab', async ({ page, context }) => {
await page.goto('tree');

const pagePromise = context.waitForEvent('page');
await page.dblclick(`.jp-FileBrowser-listing >> text=${FILENAME}`);

const newPage = await pagePromise;
//wait for Load
// await newPage.waitForLoadState();

await expect(newPage.locator('.jp-MainAreaWidget')).toHaveClass(/jp-lab-chat-main-panel/);
});
});
50 changes: 47 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2430,6 +2430,25 @@ __metadata:
languageName: node
linkType: hard

"@jupyter-notebook/application@npm:^7.2.0":
version: 7.2.1
resolution: "@jupyter-notebook/application@npm:7.2.1"
dependencies:
"@jupyterlab/application": ~4.2.0
"@jupyterlab/coreutils": ~6.2.0
"@jupyterlab/docregistry": ~4.2.0
"@jupyterlab/rendermime-interfaces": ~3.10.0
"@jupyterlab/ui-components": ~4.2.0
"@lumino/algorithm": ^2.0.1
"@lumino/coreutils": ^2.1.2
"@lumino/messaging": ^2.0.1
"@lumino/polling": ^2.1.2
"@lumino/signaling": ^2.1.2
"@lumino/widgets": ^2.3.2
checksum: 14114a2f7144e2a7bbf5e80476ef9f4b229bd9ca65d5620a97aba2e9d666cd4ae2a04cb4c96f6b0575e6383a930073945fae580eb441e3b3d48fc0ac61629376
languageName: node
linkType: hard

"@jupyter/chat@^0.6.2, @jupyter/chat@workspace:packages/jupyter-chat":
version: 0.0.0-use.local
resolution: "@jupyter/chat@workspace:packages/jupyter-chat"
Expand Down Expand Up @@ -2546,7 +2565,7 @@ __metadata:
languageName: node
linkType: hard

"@jupyterlab/application@npm:^4.2.0":
"@jupyterlab/application@npm:^4.2.0, @jupyterlab/application@npm:~4.2.0":
version: 4.2.3
resolution: "@jupyterlab/application@npm:4.2.3"
dependencies:
Expand Down Expand Up @@ -2788,6 +2807,20 @@ __metadata:
languageName: node
linkType: hard

"@jupyterlab/coreutils@npm:~6.2.0":
version: 6.2.6
resolution: "@jupyterlab/coreutils@npm:6.2.6"
dependencies:
"@lumino/coreutils": ^2.1.2
"@lumino/disposable": ^2.1.2
"@lumino/signaling": ^2.1.2
minimist: ~1.2.0
path-browserify: ^1.0.0
url-parse: ~1.5.4
checksum: edb955a1d96a96546dce96a04329fe3ee38be301805337b9fd6ae7f21227625aab76f77ce5adacb80675831aed9b869525af787cbbbd64acf415ed67256e693a
languageName: node
linkType: hard

"@jupyterlab/docmanager@npm:^4.2.3":
version: 4.2.3
resolution: "@jupyterlab/docmanager@npm:4.2.3"
Expand All @@ -2813,7 +2846,7 @@ __metadata:
languageName: node
linkType: hard

"@jupyterlab/docregistry@npm:^4.2.0, @jupyterlab/docregistry@npm:^4.2.3":
"@jupyterlab/docregistry@npm:^4.2.0, @jupyterlab/docregistry@npm:^4.2.3, @jupyterlab/docregistry@npm:~4.2.0":
version: 4.2.3
resolution: "@jupyterlab/docregistry@npm:4.2.3"
dependencies:
Expand Down Expand Up @@ -3045,6 +3078,16 @@ __metadata:
languageName: node
linkType: hard

"@jupyterlab/rendermime-interfaces@npm:~3.10.0":
version: 3.10.6
resolution: "@jupyterlab/rendermime-interfaces@npm:3.10.6"
dependencies:
"@lumino/coreutils": ^1.11.0 || ^2.1.2
"@lumino/widgets": ^1.37.2 || ^2.3.2
checksum: c3fed69c4df34ad203870522af9741662029b59aacfff07f19e4725750746d18195b4f41123fa1280c13aa8303e2a1a30697a50fc98bdba53bb4cbbbdda2d2b1
languageName: node
linkType: hard

"@jupyterlab/rendermime@npm:^4.2.0, @jupyterlab/rendermime@npm:^4.2.3":
version: 4.2.3
resolution: "@jupyterlab/rendermime@npm:4.2.3"
Expand Down Expand Up @@ -3190,7 +3233,7 @@ __metadata:
languageName: node
linkType: hard

"@jupyterlab/ui-components@npm:^4.2.0, @jupyterlab/ui-components@npm:^4.2.3":
"@jupyterlab/ui-components@npm:^4.2.0, @jupyterlab/ui-components@npm:^4.2.3, @jupyterlab/ui-components@npm:~4.2.0":
version: 4.2.3
resolution: "@jupyterlab/ui-components@npm:4.2.3"
dependencies:
Expand Down Expand Up @@ -10020,6 +10063,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "jupyterlab-chat-extension@workspace:python/jupyterlab-chat"
dependencies:
"@jupyter-notebook/application": ^7.2.0
"@jupyter/docprovider": ^2.1.4
"@jupyter/ydoc": ^1.1.1
"@jupyterlab/application": ^4.2.0
Expand Down
Loading