diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png new file mode 100644 index 000000000..39802e9d4 Binary files /dev/null and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-filled.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png new file mode 100644 index 000000000..fe62f406d Binary files /dev/null and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-open.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png new file mode 100644 index 000000000..8eb2f1a1b Binary files /dev/null and b/docs/assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png differ diff --git a/docs/assets/tutorials/multiple/pathexpansion-basepath.png b/docs/assets/tutorials/multiple/pathexpansion-basepath.png new file mode 100644 index 000000000..74d3ea158 Binary files /dev/null and b/docs/assets/tutorials/multiple/pathexpansion-basepath.png differ diff --git a/docs/assets/tutorials/multiple/preview-page.png b/docs/assets/tutorials/multiple/preview-page.png index 58298a11e..39da26941 100644 Binary files a/docs/assets/tutorials/multiple/preview-page.png and b/docs/assets/tutorials/multiple/preview-page.png differ diff --git a/docs/tutorials/multiple_sessions.rst b/docs/tutorials/multiple_sessions.rst index 1c317b7fa..c8c56fb14 100644 --- a/docs/tutorials/multiple_sessions.rst +++ b/docs/tutorials/multiple_sessions.rst @@ -33,13 +33,29 @@ Format strings are specified using two components: the **base directory**, which Given the structure of the tutorial dataset, we’ll select **~/NWB_GUIDE/test-data/dataset** as the **base directory**, where **~** is the home directory of your system. -We can take advantage of the **Autocomplete** feature of this page. Instead of manually filling out the format string, click the **Autocomplete** button and provide an example source data path (for example, the ``mouse1_Session2_g0_t0.imec0.lf.bin`` file for SpikeGLX). Then, indicate the Subject (``mouse1``) and Session ID (``Session2``) for this particular path. When you submit this form, you’ll notice that the Format String Path input has been auto-filled with a pattern for all the sessions. +We can take advantage of the **Autocomplete** feature of this page. Instead of manually filling out the format string, click the **Autocomplete** button to open a pop-up form that will derive the format string from a single example path. + +.. figure:: ../assets/tutorials/multiple/pathexpansion-autocomplete-open.png + :align: center + :alt: Autocomplete modal on path expansion page + +Provide an example source data path (for example, the ``mouse1_Session1_g0_t0.imec0.lf.bin`` file for SpikeGLX), followed by the Subject (``mouse1``) and Session ID (``Session1``) for this particular path. + +.. figure:: ../assets/tutorials/multiple/pathexpansion-autocomplete-filled.png + :align: center + :alt: Autocomplete modal completed + +When you submit this form, you’ll notice that the Format String Path input has been auto-filled with a pattern for all the sessions. + +.. figure:: ../assets/tutorials/multiple/pathexpansion-autocomplete-submitted.png + :align: center + :alt: Path expansion page with autocompleted format string Repeat this process for Phy, where ``mouse1_Session2_phy`` will be the example source data path. .. figure:: ../assets/tutorials/multiple/pathexpansion-completed.png :align: center - :alt: Blank path expansion page + :alt: Completed path expansion information Advance to the next page when you have entered the data locations for both formats. diff --git a/tests/e2e/config.ts b/tests/e2e/config.ts index a824bf2b5..86d1cb00b 100644 --- a/tests/e2e/config.ts +++ b/tests/e2e/config.ts @@ -35,6 +35,13 @@ export const alwaysDelete = [ // ------------------------ Configuration Options ------------------------ // ----------------------------------------------------------------------- +const autocompleteOptions = { + subject_id: 'mouse1', + session_id: 'Session1' +} + +const { subject_id, session_id } = autocompleteOptions + export const testInterfaceInfo = { common: { SpikeGLXRecordingInterface: { @@ -46,10 +53,12 @@ export const testInterfaceInfo = { }, multi: { SpikeGLXRecordingInterface: { - format: '{subject_id}/{subject_id}_{session_id}/{subject_id}_{session_id}_g0/{subject_id}_{session_id}_g0_imec0/{subject_id}_{session_id}_g0_t0.imec0.ap.bin' + format: '{subject_id}/{subject_id}_{session_id}/{subject_id}_{session_id}_g0/{subject_id}_{session_id}_g0_imec0/{subject_id}_{session_id}_g0_t0.imec0.ap.bin', + autocomplete: {} }, PhySortingInterface: { - format: '{subject_id}/{subject_id}_{session_id}/{subject_id}_{session_id}_phy' + format: '{subject_id}/{subject_id}_{session_id}/{subject_id}_{session_id}_phy', + autocomplete: {} } }, single: { @@ -62,6 +71,16 @@ export const testInterfaceInfo = { } } +// Add autocomplete options +Object.entries(testInterfaceInfo.multi).forEach(([key, value]) => { + const format = value.format + value.autocomplete = { + path: join(testDatasetPath, format.replace(/{subject_id}/g, subject_id).replace(/{session_id}/g, session_id)), + ...autocompleteOptions, + } +}) + + export const subjectInfo = { common: { sex: 'M', @@ -83,8 +102,8 @@ export const subjectInfo = { } } -// export const regenerateTestData = !existsSync(testDataRootPath) || false // Generate only if doesn't exist -export const regenerateTestData = true // Force regeneration +export const regenerateTestData = !existsSync(testDataRootPath) || false // Generate only if doesn't exist +// export const regenerateTestData = true // Force regeneration export const dandiInfo = { id: '212750', diff --git a/tests/e2e/workflow.ts b/tests/e2e/workflow.ts index b7a4ded02..29e2ef3ed 100644 --- a/tests/e2e/workflow.ts +++ b/tests/e2e/workflow.ts @@ -124,29 +124,77 @@ export default async function runWorkflow (name, workflow, identifier) { await takeScreenshot(join(identifier, 'pathexpansion-page')) - // Fill out the path expansion information - await evaluate(({ multi, common }, basePath) => { + // Provide base path for all interfaces + await evaluate(({ common }, basePath) => { const dashboard = document.querySelector('nwb-dashboard') const form = dashboard.page.form Object.entries(common).forEach(([ name, info ]) => { - const id = info.id const baseInput = form.getFormElement([id, 'base_directory']) baseInput.updateData(basePath) + }) - const { format } = multi[name] + dashboard.main.querySelector('main > section').scrollTop = 200 // Scroll down to see all interfaces + + }, + testInterfaceInfo, + testDatasetPath + ) + await takeScreenshot(join(identifier, 'pathexpansion-basepath'), 300) + + const name = Object.keys(testInterfaceInfo.common)[0] + const interfaceId = testInterfaceInfo.common[name].id + const autocompleteInfo = testInterfaceInfo.multi[name].autocomplete + + await evaluate(id => { + const dashboard = document.querySelector('nwb-dashboard') + const form = dashboard.page.form + const formatInput = form.getFormElement([id, 'format_string_path']) + const autocompleteButton = formatInput.controls[0] + autocompleteButton.onClick() + }, interfaceId) + + await takeScreenshot(join(identifier, 'pathexpansion-autocomplete-open'), 300) + + await evaluate(info => { + const modal = document.querySelector('nwb-modal') as any + const form = modal.querySelector('nwb-jsonschema-form') + + Object.entries(info).forEach(([key, value]) => { + const formatInput = form.getFormElement([ key ]) + formatInput.updateData(value) + }) + + }, autocompleteInfo) + + await takeScreenshot(join(identifier, 'pathexpansion-autocomplete-filled'), 300) + + // Submit the autocomplete information + await evaluate(() => { + const modal = document.querySelector('nwb-modal') as any + modal.footer.onClick() + }, autocompleteInfo) + + await takeScreenshot(join(identifier, 'pathexpansion-autocomplete-submitted'), 1000) + + // Fill out the other path expansion information + await evaluate(({ multi, common }) => { + const dashboard = document.querySelector('nwb-dashboard') + const form = dashboard.page.form + + // Fill out the path expansion information for non-autocompleted interfaces + Object.entries(common).slice(1).forEach(([ name, info ]) => { + const id = info.id + const { format } = multi[name] const formatInput = form.getFormElement([id, 'format_string_path']) formatInput.updateData(format) }) dashboard.main.querySelector('main > section').scrollTop = 200 - }, - testInterfaceInfo, - testDatasetPath - ) + }, testInterfaceInfo) await takeScreenshot(join(identifier, 'pathexpansion-completed'), 300)