1
1
import { test as jupyterLabTest , galata , IJupyterLabPageFixture } from "@jupyterlab/galata" ;
2
- import { APIRequestContext , expect , Frame } from "@playwright/test" ;
2
+ import { APIRequestContext , expect , Frame , Locator } from "@playwright/test" ;
3
3
import * as path from "path" ;
4
4
import * as os from "os" ;
5
5
import * as fs from "fs" ;
@@ -27,6 +27,7 @@ let mainPanelTabCount = 1;
27
27
const baseTestUse = {
28
28
tmpPath : tempPath ,
29
29
mockSettings : {
30
+ ...galata . DEFAULT_SETTINGS ,
30
31
'@jupyterlab/apputils-extension:notification' : {
31
32
fetchNews : 'false'
32
33
}
@@ -59,6 +60,14 @@ test.beforeEach(async ({ request, tmpPath }) => {
59
60
60
61
const contents = galata . newContentsHelper ( request ) ;
61
62
63
+ if ( await contents . fileExists ( "nbgrader_config.py" ) ) {
64
+ await contents . deleteFile ( "nbgrader_config.py" ) ;
65
+ }
66
+ await contents . uploadFile (
67
+ path . resolve ( __dirname , "./files/nbgrader_config.py" ) ,
68
+ "nbgrader_config.py"
69
+ ) ;
70
+
62
71
await contents . createDirectory ( tmpPath ) ;
63
72
64
73
if ( ! isWindows ) {
@@ -82,14 +91,23 @@ test.afterEach(async ({ request, tmpPath }) => {
82
91
83
92
const contents = galata . newContentsHelper ( request ) ;
84
93
await contents . deleteDirectory ( tmpPath ) ;
94
+ } ) ;
85
95
86
- if ( await contents . fileExists ( "nbgrader_config.py" ) )
87
- contents . deleteFile ( "nbgrader_config.py" ) ;
88
- contents . uploadFile (
89
- path . resolve ( __dirname , "./files/nbgrader_config.py" ) ,
90
- "nbgrader_config.py"
96
+ const openSettings = async ( page : IJupyterLabPageFixture ) : Promise < Locator > => {
97
+ await page . evaluate ( async ( ) => {
98
+ await window . jupyterapp . commands . execute ( 'settingeditor:open' ) ;
99
+ } ) ;
100
+
101
+ // Activate the settings tab, sometimes it does not automatically.
102
+ const settingsTab = page
103
+ . getByRole ( 'main' )
104
+ . locator ( '.lm-TabBar-tab[data-id="setting-editor"]' ) ;
105
+ await settingsTab . click ( ) ;
106
+ await page . waitForCondition (
107
+ async ( ) => ( await settingsTab . getAttribute ( 'aria-selected' ) ) === 'true'
91
108
) ;
92
- } ) ;
109
+ return ( await page . activity . getPanelLocator ( 'Settings' ) ) as Locator ;
110
+ } ;
93
111
94
112
/*
95
113
* Create a nbgrader file system
@@ -344,7 +362,6 @@ test("Load manage assignments", async ({ page, baseURL, request, tmpPath }) => {
344
362
await createEnv ( testDir , tmpPath , exchange_dir , cache_dir , isWindows ) ;
345
363
await addCourses ( request , tmpPath ) ;
346
364
await openFormgrader ( page ) ;
347
-
348
365
// get formgrader iframe and check for breadcrumbs
349
366
const iframe = page . mainFrame ( ) . childFrames ( ) [ 0 ] ;
350
367
@@ -856,3 +873,137 @@ test("Switch views", async ({ page, baseURL, request, tmpPath }) => {
856
873
}
857
874
}
858
875
} ) ;
876
+
877
+ /**
878
+ * Local Formgrader.
879
+ */
880
+ test . describe ( '#localFormgrader' , ( ) => {
881
+ test ( "Should have formgrader settings" , async ( { page, tmpPath } ) => {
882
+ test . skip ( isWindows , "This test does not work on Windows" ) ;
883
+
884
+ if ( isNotebook ) await page . goto ( `tree/${ tmpPath } ` ) ;
885
+
886
+ const settings = await openSettings ( page ) ;
887
+ const formgraderSettings = settings . locator (
888
+ '.jp-PluginList-entry[data-id="@jupyter/nbgrader:formgrader"]'
889
+ ) ;
890
+ await expect ( formgraderSettings ) . toBeVisible ( ) ;
891
+
892
+ await formgraderSettings . click ( ) ;
893
+ const settingsList = settings . locator ( '.jp-SettingsPanel fieldset > .form-group' ) ;
894
+ await expect ( settingsList ) . toHaveCount ( 1 ) ;
895
+ await expect (
896
+ settingsList . locator ( 'input' ) . first ( )
897
+ ) . toHaveAttribute ( 'type' , 'checkbox' ) ;
898
+ await expect (
899
+ settingsList . locator ( 'input' ) . first ( )
900
+ ) . not . toBeChecked ( ) ;
901
+ await expect (
902
+ settingsList . locator ( 'label' ) . first ( )
903
+ ) . toHaveText ( 'Allow local nbgrader config file' ) ;
904
+ } ) ;
905
+
906
+ test ( 'should add option to open formgrader locally' , async ( { page, tmpPath } ) => {
907
+ if ( isNotebook ) await page . goto ( `tree/${ tmpPath } ` ) ;
908
+
909
+ const nbgrader_menu = page . locator (
910
+ `${ menuPanelId } div.lm-MenuBar-itemLabel:text("Nbgrader")`
911
+ ) ;
912
+ const formgrader_menu = page . locator (
913
+ '#jp-mainmenu-nbgrader li[data-command="nbgrader:open-formgrader-local"]'
914
+ ) ;
915
+ await nbgrader_menu . click ( ) ;
916
+ expect ( formgrader_menu ) . toHaveCount ( 0 ) ;
917
+
918
+ const settings = await openSettings ( page ) ;
919
+ const formgraderSettings = settings . locator (
920
+ '.jp-PluginList-entry[data-id="@jupyter/nbgrader:formgrader"]'
921
+ ) ;
922
+ await formgraderSettings . click ( ) ;
923
+ await settings
924
+ . locator ( '.jp-SettingsPanel fieldset > .form-group input' )
925
+ . first ( )
926
+ . check ( ) ;
927
+
928
+ // wait for the settings to be saved
929
+ const settingsTab = page
930
+ . getByRole ( 'main' )
931
+ . locator ( '.lm-TabBar-tab[data-id="setting-editor"]' ) ;
932
+ await expect ( settingsTab ) . toHaveAttribute ( 'class' , / j p - m o d - d i r t y / ) ;
933
+ await expect ( settingsTab ) . not . toHaveAttribute ( 'class' , / j p - m o d - d i r t y / ) ;
934
+ await nbgrader_menu . click ( ) ;
935
+ expect ( formgrader_menu ) . toHaveCount ( 1 ) ;
936
+ } ) ;
937
+
938
+ test ( 'should open formgrader locally' , async ( { page, tmpPath } ) => {
939
+ if ( isNotebook ) await page . goto ( `tree/${ tmpPath } ` ) ;
940
+
941
+ const nbgraderMenu = page . locator (
942
+ `${ menuPanelId } div.lm-MenuBar-itemLabel:text("Nbgrader")`
943
+ ) ;
944
+ const formgraderMenu = page . locator (
945
+ '#jp-mainmenu-nbgrader li[data-command="nbgrader:open-formgrader"]'
946
+ ) ;
947
+ const localFormgraderMenu = page . locator (
948
+ '#jp-mainmenu-nbgrader li[data-command="nbgrader:open-formgrader-local"]'
949
+ ) ;
950
+
951
+ const settings = await openSettings ( page ) ;
952
+ const formgraderSettings = settings . locator (
953
+ '.jp-PluginList-entry[data-id="@jupyter/nbgrader:formgrader"]'
954
+ ) ;
955
+ await formgraderSettings . click ( ) ;
956
+ await settings
957
+ . locator ( '.jp-SettingsPanel fieldset > .form-group input' )
958
+ . first ( )
959
+ . check ( ) ;
960
+
961
+ // wait for the settings to be saved
962
+ const settingsTab = page
963
+ . getByRole ( 'main' )
964
+ . locator ( '.lm-TabBar-tab[data-id="setting-editor"]' ) ;
965
+ await expect ( settingsTab ) . toHaveAttribute ( 'class' , / j p - m o d - d i r t y / ) ;
966
+ await expect ( settingsTab ) . not . toHaveAttribute ( 'class' , / j p - m o d - d i r t y / ) ;
967
+
968
+ // Add a local formgrader in another directory
969
+ const newDirectory = path . resolve ( testDir , 'localFormgrader' ) ;
970
+
971
+ if ( fs . existsSync ( newDirectory ) ) {
972
+ fs . rmSync ( newDirectory , { recursive : true } ) ;
973
+ }
974
+ fs . mkdirSync ( newDirectory ) ;
975
+ fs . copyFileSync (
976
+ path . resolve ( testDir , "nbgrader_config.py" ) ,
977
+ path . resolve ( testDir , tmpPath , "nbgrader_config.py" )
978
+ ) ;
979
+
980
+ var text_to_append = `
981
+ c.CourseDirectory.course_id = "test_course"
982
+ c.Exchange.root = r"${ exchange_dir } "
983
+ c.Exchange.cache = r"${ cache_dir } "
984
+ c.Exchange.assignment_dir = r"${ newDirectory } "
985
+
986
+ ` ;
987
+
988
+ fs . appendFileSync (
989
+ path . resolve ( newDirectory , "nbgrader_config.py" ) ,
990
+ text_to_append
991
+ ) ;
992
+
993
+ // open regular formgrader and expect warning because of wrong configuration
994
+ await nbgraderMenu . click ( ) ;
995
+ await formgraderMenu . click ( ) ;
996
+ let iframe = page . mainFrame ( ) . childFrames ( ) [ 0 ] ;
997
+ await ( await iframe . frameElement ( ) ) . contentFrame ( ) ;
998
+ await expect ( iframe . locator ( '#warning-exchange' ) ) . toBeAttached ( ) ;
999
+ await page . activity . closeAll ( ) ;
1000
+
1001
+ // open local formgrader and expect no warning
1002
+ await page . filebrowser . openDirectory ( 'localFormgrader' ) ;
1003
+ await nbgraderMenu . click ( ) ;
1004
+ await localFormgraderMenu . click ( ) ;
1005
+ iframe = page . mainFrame ( ) . childFrames ( ) [ 0 ] ;
1006
+ await ( await iframe . frameElement ( ) ) . contentFrame ( ) ;
1007
+ await expect ( iframe . locator ( '#warning-exchange' ) ) . not . toBeAttached ( ) ;
1008
+ } ) ;
1009
+ } ) ;
0 commit comments