From be406f2c64f1ee5569998b9e5efc74a14cd65be8 Mon Sep 17 00:00:00 2001 From: krassowski Date: Wed, 8 Jan 2020 19:31:39 +0000 Subject: [PATCH 1/3] Fix R foreign extractor, add bash alias, add notebook and extractors acceptance tests --- CHANGELOG.md | 2 + atest/01_Editor.robot | 62 +++---------- atest/03_Notebook.robot | 23 +++++ atest/Keywords.robot | 50 ++++++++++ atest/Variables.robot | 14 ++- atest/examples/Foreign extractors.ipynb | 92 +++++++++++++++++++ atest/examples/Python.ipynb | 43 +++++++++ .../jupyterlab-lsp/src/extractors/defaults.ts | 6 +- 8 files changed, 240 insertions(+), 52 deletions(-) create mode 100644 atest/03_Notebook.robot create mode 100644 atest/examples/Foreign extractors.ipynb create mode 100644 atest/examples/Python.ipynb diff --git a/CHANGELOG.md b/CHANGELOG.md index ce64614a0..289e01a3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - all commands are now accessible from the command palette ( [#142](https://github.com/krassowski/jupyterlab-lsp/pull/142) ) + - bash LSP now covers also `%%bash` magic cell in addition to `%%sh` - bugfixes - diagnostics in foreign documents are now correctly updated ( [133fd3d](https://github.com/krassowski/jupyterlab-lsp/pull/129/commits/133fd3d71401c7e5affc0a8637ee157de65bef62) @@ -31,6 +32,7 @@ - the workaround for relative root path is now also applied on Mac ( [#139](https://github.com/krassowski/jupyterlab-lsp/pull/139) ) + - fixed LSP of R in Python (`%%R` magic cell from rpy2) ## `lsp-ws-connection 0.3.0` diff --git a/atest/01_Editor.robot b/atest/01_Editor.robot index 0b6d2e5f4..4233f9bd9 100644 --- a/atest/01_Editor.robot +++ b/atest/01_Editor.robot @@ -5,15 +5,9 @@ Resource Keywords.robot *** Variables *** ${MENU EDITOR} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(., "Editor")] -${MENU OPEN WITH} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(text(), "Open With")] ${MENU JUMP} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(text(), "Jump to definition")] -${MENU RENAME} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(text(), "Rename")] ${CM CURSOR} css:.CodeMirror-cursor ${CM CURSORS} css:.CodeMirror-cursors:not([style='visibility: hidden']) -${DIALOG WINDOW} css:.jp-Dialog -${DIALOG INPUT} css:.jp-Input-Dialog input -${DIAGNOSTICS PANEL} css:#lsp-diagnostics-panel -${DIAGNOSTIC PANEL CLOSE} css:.p-DockPanel-tabBar .p-TabBar-tab[data-id="lsp-diagnostics-panel"] .p-TabBar-tabCloseIcon *** Test Cases *** Bash @@ -74,7 +68,7 @@ Editor Shows Features for Language Set Screenshot Directory ${OUTPUT DIR}${/}screenshots${/}editor${/}${Language.lower()} Copy File examples${/}${file} ${OUTPUT DIR}${/}home${/}${file} Lab Command Close All Tabs - Open ${file} in Editor + Open ${file} in ${MENU EDITOR} Capture Page Screenshot 00-opened.png FOR ${f} IN @{features} Run Keyword If "${f}" == "Diagnostics" Editor Should Show Diagnostics ${features["${f}"]} @@ -84,37 +78,16 @@ Editor Shows Features for Language Capture Page Screenshot 99-done.png [Teardown] Clean Up After Working With File ${file} -Clean Up After Working With File - [Arguments] ${file} - Remove File ${OUTPUT DIR}${/}home${/}${file} - Reset Application State - -Open ${file} in Editor - Ensure File Browser is Open - Click Element css:button[title="Refresh File List"] - Open Context Menu css:.jp-DirListing-item[title="${file}"] - Mouse Over ${MENU OPEN WITH} - Wait Until Page Contains Element ${MENU EDITOR} - Mouse Over ${MENU EDITOR} - Click Element ${MENU EDITOR} - -Ensure File Browser is Open - ${sel} = Set Variable css:.p-TabBar-tab[data-id="filebrowser"]:not(.p-mod-current) - ${els} = Get WebElements ${sel} - Run Keyword If ${els.__len__()} Click Element ${sel} - Editor Should Show Diagnostics [Arguments] ${diagnostic} Set Tags feature:diagnostics Wait Until Page Contains Element css:.cm-lsp-diagnostic[title*="${diagnostic}"] timeout=20s Capture Page Screenshot 01-diagnostics.png - Lab Command Show Diagnostics Panel - Wait Until Page Contains Element ${DIAGNOSTICS PANEL} timeout=20s + Open Diagnostics Panel Capture Page Screenshot 02-diagnostics.png - ${count} = Get Element Count css:.lsp-diagnostics-listing tr - SHOULD BE TRUE ${count} >= 1 - Mouse Over ${DIAGNOSTIC PANEL CLOSE} - Click Element ${DIAGNOSTIC PANEL CLOSE} + ${count} = Count Diagnostics In Panel + Should Be True ${count} >= 1 + Close Diagnostics Panel Editor Should Jump To Definition [Arguments] ${symbol} @@ -139,20 +112,19 @@ Measure Cursor Position ${position} = Wait Until Keyword Succeeds 20 x 0.05s Get Vertical Position ${CM CURSOR} [Return] ${position} -Wait For Dialog - Wait Until Page Contains Element ${DIALOG WINDOW} timeout=180s - Open Context Menu Over [Arguments] ${sel} - Mouse Over ${sel} - Sleep 10s - Mouse Over ${sel} + Wait Until Keyword Succeeds 10 x 0.1 s Mouse Over ${sel} Wait Until Keyword Succeeds 10 x 0.1 s Click Element ${sel} Wait Until Keyword Succeeds 10 x 0.1 s Open Context Menu ${sel} +Get Editor Content + ${content} Execute JavaScript return document.querySelector('.CodeMirror').CodeMirror.getValue() + [Return] ${content} + Editor Content Changed [Arguments] ${old_content} - ${new_content} Execute JavaScript return document.querySelector('.CodeMirror').CodeMirror.getValue() + ${new_content} Get Editor Content Should Not Be Equal ${old_content} ${new_content} [Return] ${new_content} @@ -161,18 +133,14 @@ Editor Should Rename Set Tags feature:rename ${sel} = Set Variable If "${symbol}".startswith(("xpath", "css")) ${symbol} xpath:(//span[@role="presentation"][contains(., "${symbol}")])[last()] Open Context Menu Over ${sel} - ${old_content} Execute JavaScript return document.querySelector('.CodeMirror').CodeMirror.getValue() + ${old_content} Get Editor Content Capture Page Screenshot 03-rename-0.png Mouse Over ${MENU RENAME} Capture Page Screenshot 03-rename-1.png Click Element ${MENU RENAME} - Wait For Dialog - Click Element ${DIALOG INPUT} - Capture Page Screenshot 03-rename-3.png - Input Text ${DIALOG INPUT} new_name - Capture Page Screenshot 03-rename-4.png - Click Element css:button.jp-Dialog-button.jp-mod-accept + Capture Page Screenshot 03-rename-2.png + Input Into Dialog new_name Sleep 2s - Capture Page Screenshot 03-rename-5.png + Capture Page Screenshot 03-rename-3.png ${new_content} Wait Until Keyword Succeeds 10 x 0.1 s Editor Content Changed ${old_content} Should Be True "new_name" in """${new_content}""" diff --git a/atest/03_Notebook.robot b/atest/03_Notebook.robot new file mode 100644 index 000000000..513bf3d3c --- /dev/null +++ b/atest/03_Notebook.robot @@ -0,0 +1,23 @@ +*** Settings *** +Suite Setup Setup Suite For Screenshots notebook +Resource Keywords.robot + +*** Test Cases *** +Python + [Setup] Reset Application State + Setup Notebook Python Python.ipynb + Capture Page Screenshot 01-python.png + ${diagnostic} = Set Variable W291 trailing whitespace (pycodestyle) + Wait Until Page Contains Element css:.cm-lsp-diagnostic[title="${diagnostic}"] timeout=20s + Capture Page Screenshot 02-python.png + Clean Up After Working With File Python.ipynb + +Foregin Extractors + [Setup] Reset Application State + Setup Notebook Python Foreign extractors.ipynb + @{diagnostics} = Create List Failed to parse expression Name 'valid' is not defined (mypy) Trailing whitespace is superfluous. (lintr) + FOR ${diagnostic} IN @{diagnostics} + Wait Until Page Contains Element css:.cm-lsp-diagnostic[title="${diagnostic}"] timeout=30s + Capture Page Screenshot 0x-${diagnostic}.png + END + Clean Up After Working With File Foreign Extractors.ipynb diff --git a/atest/Keywords.robot b/atest/Keywords.robot index e8dac6ee7..956056d1f 100644 --- a/atest/Keywords.robot +++ b/atest/Keywords.robot @@ -126,3 +126,53 @@ Open With JupyterLab Menu FOR ${submenu} IN @{submenus} Click JupyterLab Menu Item ${submenu} END + +Ensure File Browser is Open + ${sel} = Set Variable css:.p-TabBar-tab[data-id="filebrowser"]:not(.p-mod-current) + ${els} = Get WebElements ${sel} + Run Keyword If ${els.__len__()} Click Element ${sel} + +Input Into Dialog + [Arguments] ${text} + Wait For Dialog + Click Element ${DIALOG INPUT} + Input Text ${DIALOG INPUT} ${text} + Click Element ${DIALOG ACCEPT} + +Open ${file} in ${editor} + Ensure File Browser is Open + Click Element css:button[title="Refresh File List"] + Open Context Menu css:.jp-DirListing-item[title="${file}"] + Mouse Over ${MENU OPEN WITH} + Wait Until Page Contains Element ${editor} + Mouse Over ${editor} + Click Element ${editor} + +Clean Up After Working With File + [Arguments] ${file} + Remove File ${OUTPUT DIR}${/}home${/}${file} + Reset Application State + +Setup Notebook + [Arguments] ${Language} ${file} + Set Tags language:${Language.lower()} + Set Screenshot Directory ${OUTPUT DIR}${/}screenshots${/}notebook${/}${file.lower()} + Copy File examples${/}${file} ${OUTPUT DIR}${/}home${/}${file} + Lab Command Close All Tabs + Open ${file} in ${MENU NOTEBOOK} + Capture Page Screenshot 00-opened.png + +Open Diagnostics Panel + Lab Command Show Diagnostics Panel + Wait Until Page Contains Element ${DIAGNOSTICS PANEL} timeout=20s + +Count Diagnostics In Panel + ${count} = Get Element Count css:.lsp-diagnostics-listing tbody tr + [Return] ${count} + +Close Diagnostics Panel + Mouse Over ${DIAGNOSTIC PANEL CLOSE} + Click Element ${DIAGNOSTIC PANEL CLOSE} + +Wait For Dialog + Wait Until Page Contains Element ${DIALOG WINDOW} timeout=180s diff --git a/atest/Variables.robot b/atest/Variables.robot index 7d494ff67..ce1ff16ac 100644 --- a/atest/Variables.robot +++ b/atest/Variables.robot @@ -4,10 +4,20 @@ ${SPLASH} id:jupyterlab-splash ${BASE} /@est/ # override with `python scripts/atest.py --variable HEADLESS:0` ${HEADLESS} 1 -${CMD PALETTE INPUT} css:.p-CommandPalette-input -${CMD PALETTE ITEM ACTIVE} css:.p-CommandPalette-item.p-mod-active +${CMD PALETTE INPUT} css:#command-palette .p-CommandPalette-input +${CMD PALETTE ITEM ACTIVE} css:#command-palette .p-CommandPalette-item.p-mod-active ${JLAB XP TOP} //div[@id='jp-top-panel'] ${JLAB XP MENU ITEM LABEL} //div[@class='p-Menu-itemLabel'] ${JLAB XP MENU LABEL} //div[@class='p-MenuBar-itemLabel'] ${JLAB CSS VERSION} css:.jp-About-version ${CSS DIALOG OK} css:.jp-Dialog .jp-mod-accept +${MENU OPEN WITH} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(text(), "Open With")] +# R is missing on purpose (may need to use .) +${MENU RENAME} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(., "ename")] +# N is missing on purpose +${MENU NOTEBOOK} xpath://div[contains(@class, 'p-Menu-itemLabel')][contains(., "otebook")] +${DIAGNOSTICS PANEL} id:lsp-diagnostics-panel +${DIAGNOSTIC PANEL CLOSE} css:.p-DockPanel-tabBar .p-TabBar-tab[data-id="lsp-diagnostics-panel"] .p-TabBar-tabCloseIcon +${DIALOG WINDOW} css:.jp-Dialog +${DIALOG INPUT} css:.jp-Input-Dialog input +${DIALOG ACCEPT} css:button.jp-Dialog-button.jp-mod-accept diff --git a/atest/examples/Foreign extractors.ipynb b/atest/examples/Foreign extractors.ipynb new file mode 100644 index 000000000..bb57fe08d --- /dev/null +++ b/atest/examples/Foreign extractors.ipynb @@ -0,0 +1,92 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Smoke" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "valid = 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%python\n", + "valid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### R" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%R\n", + "test \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### bash" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "echo $" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/atest/examples/Python.ipynb b/atest/examples/Python.ipynb new file mode 100644 index 000000000..5ce97ded6 --- /dev/null +++ b/atest/examples/Python.ipynb @@ -0,0 +1,43 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "test = 1 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/packages/jupyterlab-lsp/src/extractors/defaults.ts b/packages/jupyterlab-lsp/src/extractors/defaults.ts index a08f51c42..a1ed66f62 100644 --- a/packages/jupyterlab-lsp/src/extractors/defaults.ts +++ b/packages/jupyterlab-lsp/src/extractors/defaults.ts @@ -9,14 +9,14 @@ export let foreign_code_extractors: IForeignCodeExtractorsRegistry = { // R magics (non-standalone: the R code will always be in the same, single R-namespace) // new RegExpForeignCodeExtractor({ - language: 'R', + language: 'r', pattern: '^%%R( .*?)?\n([^]*)', extract_to_foreign: '$2', is_standalone: false, file_extension: 'R' }), new RegExpForeignCodeExtractor({ - language: 'R', + language: 'r', pattern: '(^|\n)%R (.*)\n?', extract_to_foreign: '$2', is_standalone: false, @@ -49,7 +49,7 @@ export let foreign_code_extractors: IForeignCodeExtractorsRegistry = { }), new RegExpForeignCodeExtractor({ language: 'sh', - pattern: '^%%(sh)( .*?)?\n([^]*)', + pattern: '^%%(sh|bash)( .*?)?\n([^]*)', extract_to_foreign: '$3', is_standalone: true, file_extension: 'sh' From 8359400ffa3ee771e2455b7bb4e5942efccf56b5 Mon Sep 17 00:00:00 2001 From: krassowski Date: Wed, 8 Jan 2020 21:29:07 +0000 Subject: [PATCH 2/3] Use pyflakes to avoid test dependency on mypy --- atest/03_Notebook.robot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atest/03_Notebook.robot b/atest/03_Notebook.robot index 513bf3d3c..da0ca6de2 100644 --- a/atest/03_Notebook.robot +++ b/atest/03_Notebook.robot @@ -15,7 +15,7 @@ Python Foregin Extractors [Setup] Reset Application State Setup Notebook Python Foreign extractors.ipynb - @{diagnostics} = Create List Failed to parse expression Name 'valid' is not defined (mypy) Trailing whitespace is superfluous. (lintr) + @{diagnostics} = Create List Failed to parse expression undefined name 'valid' (pyflakes) Trailing whitespace is superfluous. (lintr) FOR ${diagnostic} IN @{diagnostics} Wait Until Page Contains Element css:.cm-lsp-diagnostic[title="${diagnostic}"] timeout=30s Capture Page Screenshot 0x-${diagnostic}.png From d42d0de797f2e6082991590451a721c3f6717461 Mon Sep 17 00:00:00 2001 From: krassowski Date: Thu, 9 Jan 2020 19:40:21 +0000 Subject: [PATCH 3/3] Add PR links to the CHANGELOG.md --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 289e01a3f..5401298d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,9 @@ - all commands are now accessible from the command palette ( [#142](https://github.com/krassowski/jupyterlab-lsp/pull/142) ) - - bash LSP now covers also `%%bash` magic cell in addition to `%%sh` + - bash LSP now also covers `%%bash` magic cell in addition to `%%sh` ( + [#144](https://github.com/krassowski/jupyterlab-lsp/pull/144) + ) - bugfixes - diagnostics in foreign documents are now correctly updated ( [133fd3d](https://github.com/krassowski/jupyterlab-lsp/pull/129/commits/133fd3d71401c7e5affc0a8637ee157de65bef62) @@ -32,7 +34,9 @@ - the workaround for relative root path is now also applied on Mac ( [#139](https://github.com/krassowski/jupyterlab-lsp/pull/139) ) - - fixed LSP of R in Python (`%%R` magic cell from rpy2) + - fixed LSP of R in Python (`%%R` magic cell from rpy2) ( + [#144](https://github.com/krassowski/jupyterlab-lsp/pull/144) + ) ## `lsp-ws-connection 0.3.0`