From 278dc52c6fbb9b1e37202e16d06f09a666570fc0 Mon Sep 17 00:00:00 2001 From: Nicolas Brichet Date: Tue, 19 Mar 2024 17:51:02 +0100 Subject: [PATCH] Add tests on chat --- ui-tests/jupyter_server_test_config.py | 2 + ui-tests/tests/chat.spec.ts | 145 ++++++++++++++++++ .../chat-icon-linux.png | Bin 0 -> 467 bytes 3 files changed, 147 insertions(+) create mode 100644 ui-tests/tests/chat.spec.ts create mode 100644 ui-tests/tests/chat.spec.ts-snapshots/chat-icon-linux.png diff --git a/ui-tests/jupyter_server_test_config.py b/ui-tests/jupyter_server_test_config.py index 86fd4353..40174569 100644 --- a/ui-tests/jupyter_server_test_config.py +++ b/ui-tests/jupyter_server_test_config.py @@ -14,5 +14,7 @@ c: Any configure_jupyter_server(c) # noqa +c.FileContentsManager.delete_to_trash = False + # Uncomment to set server log level to debug level # c.ServerApp.log_level = "DEBUG" diff --git a/ui-tests/tests/chat.spec.ts b/ui-tests/tests/chat.spec.ts new file mode 100644 index 00000000..91bda7f4 --- /dev/null +++ b/ui-tests/tests/chat.spec.ts @@ -0,0 +1,145 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +import { expect, IJupyterLabPageFixture, test } from '@jupyterlab/galata'; +import type { User } from '@jupyterlab/services'; +import type { Locator } from '@playwright/test'; + +const openPanel = async (page: IJupyterLabPageFixture): Promise => { + const panel = page.locator('.jp-SidePanel.jp-collab-chat-sidepanel'); + + if (!(await panel?.isVisible())) { + const chatIcon = page.getByTitle('Jupyter Chat'); + await chatIcon.click(); + await expect(panel).toBeVisible(); + } + return panel.first(); +}; + +test.describe('Initialization', () => { + test('should contain the chat panel icon', async ({ page }) => { + const chatIcon = page.getByTitle('Jupyter Chat'); + expect(chatIcon).toHaveCount(1); + expect(await chatIcon.screenshot()).toMatchSnapshot( + 'chat_icon.png' + ); + }); + + test('chat panel should contain a toolbar', async ({ page }) => { + const panel = await openPanel(page); + const toolbar = panel.locator('.jp-SidePanel-toolbar'); + await expect(toolbar).toHaveCount(1); + + const items = toolbar.locator('.jp-Toolbar-item'); + await expect(items).toHaveCount(2); + await expect(items.first()).toHaveClass(/.jp-collab-chat-add/); + await expect(items.last()).toHaveClass(/.jp-collab-chat-open/); + }); + + test('chat panel should not contain a chat at init', async ({ page }) => { + const panel = await openPanel(page); + const content = panel.locator('.jp-SidePanel-content'); + await expect(content).toBeEmpty(); + }); +}) + +test.describe('Chat creation', () => { + let panel: Locator; + let dialog: Locator; + + test.beforeEach(async ({ page }) => { + panel = await openPanel(page); + const addButton = panel.locator( + '.jp-SidePanel-toolbar .jp-Toolbar-item.jp-collab-chat-add' + ); + await addButton.click(); + + dialog = page.locator('.jp-Dialog'); + await dialog.waitFor(); + }); + + test('should create a chat', async ({ page }) => { + await dialog.locator('input[type="text"]').type('chat-test'); + await dialog.getByRole('button').getByText('Ok').click(); + expect(await page.filebrowser.contents.fileExists('chat-test.chat')).toBeTruthy(); + + const chatTitle = panel.locator('.jp-SidePanel-content .jp-AccordionPanel-title'); + await expect(chatTitle).toHaveCount(1); + await expect(chatTitle.locator('.lm-AccordionPanel-titleLabel')).toHaveText( + 'chat-test' + ); + }); + + test('should create an untitled file if no name is provided', async ({ page }) => { + await dialog.getByRole('button').getByText('Ok').click(); + expect(await page.filebrowser.contents.fileExists('untitled.chat')).toBeTruthy(); + + const chatTitle = panel.locator('.jp-SidePanel-content .jp-AccordionPanel-title'); + await expect(chatTitle).toHaveCount(1); + await expect(chatTitle.locator('.lm-AccordionPanel-titleLabel')).toHaveText( + 'untitled' + ); + }); + + test('should not create a chat if dialog is cancelled', async ({ page }) => { + await dialog.getByRole('button').getByText('Cancel').click(); + + const content = panel.locator('.jp-SidePanel-content'); + await expect(content).toBeEmpty(); + }); +}) + +test.describe('Opening/closing chat', () => { + const name = 'my-chat'; + let panel: Locator; + let select: Locator; + + test.beforeEach(async ({ page }) => { + await page.filebrowser.contents.uploadContent('{}', 'text', `${name}.chat`); + }); + + test.afterEach(async ({ page }) => { + await page.filebrowser.contents.deleteFile( `${name}.chat`); + }); + + test('should list existing chat', async ({ page }) => { + // reload to update the chat list + // FIX: add listener on file creation + await page.reload(); + panel = await openPanel(page); + select = panel.locator( + '.jp-SidePanel-toolbar .jp-Toolbar-item.jp-collab-chat-open select' + ); + + for (let i=0; i< await select.locator('option').count(); i++) { + console.log(await select.locator('option').nth(i).textContent()); + } + await expect(select.locator('option')).toHaveCount(2); + await expect(select.locator('option').last()).toHaveText(name); + }); + + test('should open an existing chat and close it', async ({ page }) => { + // reload to update the chat list + // FIX: add listener on file creation + await page.reload(); + panel = await openPanel(page); + select = panel.locator( + '.jp-SidePanel-toolbar .jp-Toolbar-item.jp-collab-chat-open select' + ); + + await select.selectOption(name); + + const chatTitle = panel.locator('.jp-SidePanel-content .jp-AccordionPanel-title'); + await expect(chatTitle).toHaveCount(1); + await expect(chatTitle.locator('.lm-AccordionPanel-titleLabel')).toHaveText( + name + ); + + await page.pause(); + await chatTitle.getByRole('button').click(); + await page.pause(); + await expect(chatTitle).toHaveCount(0); + }); +}); diff --git a/ui-tests/tests/chat.spec.ts-snapshots/chat-icon-linux.png b/ui-tests/tests/chat.spec.ts-snapshots/chat-icon-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..76b5d4e04f0889b55dfdcfe77cdf2ec9495ba328 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^3P5bi!3JU_zPtmZ7>k44ofy`glX(eb_jjeh1yG*%cxpZ%3xH@HwU@K2GPbVvyE$bTJ6!TD)L= z*ZJ?BMUS5^wcO2>a=%vW`Mhe*i!#S|PFi3$Nk@-?Ndbl!CUhC)m`U5559T_Zwppb6 z=yk?5VcKnn6W2K0-gfe7(RxM;xqb$d*}guPd3dArrt64x-<~y{;fK~#uMn-N0q3js z_JvxAH7v{A=v2O2w)tR#kDBxP>(1A|I;_8>xg$>gchPs7{=aqduRQ-qsPPF{G5@=_ zd)?^_lSd_1tW~nde{Or0e$1I+-?7Jr3{Q(JFHAoF+>oc)Y2kr~1p%GCY#-X+7wx?8 zwrr!0x8|3+jKypbE1Bo|v7g>F!*974!@Ae^=FPv?RJPl9Z5VTc*=$Y5JFi#rg{%$@ zTB+Z??sd-g+Yt=@r4RO5IPAY4u4Og<{7fG;hZ6RCMf@gGyiseXO$yKCkPqA&_y6j_ z{Y&=#7C-y5Mh$5CzWU#xGGTw>85XI)LP>$4levaT@?E~d4W5KHU@S3sy85}Sb4q9e E0DtPe1ONa4 literal 0 HcmV?d00001