Repository: MetaCell/NetPyNE-UI (language: python)

Issue:
Feature/netpyne 111
Closes netpyne-111 and netpyne-110


Syntax on electrode positions
Hello,

I modelled a ball-and-stick neuron so I guess that the soma is the center (0,0,0). What I want to do next is to set a electrode located at (0,50,250) (for example).

So I go in Simulation configuration > Record > Add new Record LFP electrode locations to type the coordinates. However... what is the syntax ?

I tried many <[0,50,250] or (0,50,250) ... > but I only get an error :  "Only comma separated float number are allowed"..

Thanks in advance

Harry
Syntax on electrode positions
Hello,

I modelled a ball-and-stick neuron so I guess that the soma is the center (0,0,0). What I want to do next is to set a electrode located at (0,50,250) (for example).

So I go in Simulation configuration > Record > Add new Record LFP electrode locations to type the coordinates. However... what is the syntax ?

I tried many <[0,50,250] or (0,50,250) ... > but I only get an error :  "Only comma separated float number are allowed"..

Thanks in advance

Harry
Syntax on electrode positions
Hello,

I modelled a ball-and-stick neuron so I guess that the soma is the center (0,0,0). What I want to do next is to set a electrode located at (0,50,250) (for example).

So I go in Simulation configuration > Record > Add new Record LFP electrode locations to type the coordinates. However... what is the syntax ?

I tried many <[0,50,250] or (0,50,250) ... > but I only get an error :  "Only comma separated float number are allowed"..

Thanks in advance

Harry


Discussion / hints:

Hi Harry, I think what you are looking for it just. 0,50,250 .  no [] or () are required
Yes it works.

Thank your for your quick answer !
No problem =) 
Hi Harry, I think what you are looking for it just. 0,50,250 .  no [] or () are required
Yes it works.

Thank your for your quick answer !
No problem =) 
Hi Harry, I think what you are looking for it just. 0,50,250 .  no [] or () are required
Yes it works.

Thank your for your quick answer !
No problem =) 

Fix patch:
diff --git a/webapp/components/NetPyNE.js b/webapp/components/NetPyNE.js
index 03ae0283..0826b593 100644
--- a/webapp/components/NetPyNE.js
+++ b/webapp/components/NetPyNE.js
@@ -10,6 +10,7 @@ import {
   Dialog,
   ConfirmationDialog,
   LaunchDialog,
+  TutorialObserver
 } from 'netpyne/components';
 import { loadModel } from '../redux/actions/general';
 
@@ -39,6 +40,7 @@ const styles = ({ zIndex }) => ({
   noGrow: { flexGrow: 0 },
 });
 
+
 class NetPyNE extends React.Component {
   constructor (props) {
     super(props);
@@ -108,27 +110,29 @@ class NetPyNE extends React.Component {
 
     const Layout = LayoutManager();
     return (
-      <div className={classes.root}>
-        <div className={classes.container}>
-          <div className={classes.topbar}>
-            <Topbar />
-          </div>
-          <Box p={1} flex={1} display="flex" alignItems="stretch">
-            <Grid container spacing={1} className={classes.content} alignItems="stretch">
-              <Grid item className={classes.noGrow}>
-                <Drawer />
+      <TutorialObserver>
+        <div className={classes.root}>
+          <div className={classes.container}>
+            <div className={classes.topbar}>
+              <Topbar />
+            </div>
+            <Box p={1} flex={1} display="flex" alignItems="stretch">
+              <Grid container spacing={1} className={classes.content} alignItems="stretch">
+                <Grid item className={classes.noGrow}>
+                  <Drawer />
+                </Grid>
+                <Grid item>
+                  <Layout />
+                </Grid>
               </Grid>
-              <Grid item>
-                <Layout />
-              </Grid>
-            </Grid>
-          </Box>
+            </Box>
+          </div>
+          <Dialog />
+          <ConfirmationDialog />
+          <ErrorDialog />
+          <LaunchDialog />
         </div>
-        <Dialog />
-        <ConfirmationDialog />
-        <ErrorDialog />
-        <LaunchDialog />
-      </div>
+      </TutorialObserver>
     );
   }
 }
diff --git a/webapp/components/definition/cellRules/SelectCellTemplate.js b/webapp/components/definition/cellRules/SelectCellTemplate.js
index 01d68b91..628b4ebe 100644
--- a/webapp/components/definition/cellRules/SelectCellTemplate.js
+++ b/webapp/components/definition/cellRules/SelectCellTemplate.js
@@ -1,12 +1,14 @@
 import React, { Component } from 'react';
 import Menu from '@material-ui/core/Menu';
 import MenuItem from '@material-ui/core/MenuItem';
+import { connect } from 'react-redux';
+import { runControlledStep } from '../../../redux/actions/tutorials';
 
 import Fab from '@material-ui/core/Fab';
 import Tooltip from '../../general/Tooltip';
 import Utils from '../../../Utils';
 
-export default class NetPyNENewPlot extends React.Component {
+class NetPyNENewPlot extends React.Component {
   constructor (props) {
     super(props);
     this.handleClick = this.handleSelection.bind(this);
@@ -14,6 +16,10 @@ export default class NetPyNENewPlot extends React.Component {
     this.state = { anchorEl: null };
   }
 
+  componentDidMount() {
+    //this.props.dispatch(runControlledStep({ tourStep: 1 }));
+  }
+
   handleButtonClick = (event) => {
     // This prevents ghost click.
     event.preventDefault();
@@ -42,8 +48,11 @@ export default class NetPyNENewPlot extends React.Component {
       handleButtonClick,
       anchorEl,
       clearAnchorEl,
+      tourRunning
     } = this.props;
 
+    const displayMenu = Boolean(anchorEl);
+
     return (
       <div>
         <Tooltip title={tooltip} placement="top">
@@ -71,7 +80,7 @@ export default class NetPyNENewPlot extends React.Component {
         </Tooltip>
 
         <Menu
-          open={Boolean(anchorEl)}
+          open={displayMenu}
           id="selectCellMenu"
           anchorEl={anchorEl}
           onClose={() => clearAnchorEl()}
@@ -117,3 +126,11 @@ export default class NetPyNENewPlot extends React.Component {
     );
   }
 }
+
+const mapStateToProps = (state) => {
+  return {
+    tourRunning: state.tutorial.tourRunning
+  };
+};
+
+export default connect(mapStateToProps)(NetPyNENewPlot);
diff --git a/webapp/components/general/PythonControlledCapability.js b/webapp/components/general/PythonControlledCapability.js
index 773effea..24874a8f 100644
--- a/webapp/components/general/PythonControlledCapability.js
+++ b/webapp/components/general/PythonControlledCapability.js
@@ -420,7 +420,7 @@ define((require) => {
         }
 
         callPythonMethod = (value) => {
-          const params = this.props?.pythonParams || [];
+          const params = this.props?.pythonparams || [];
           if (this.props.method) {
             GeppettoUtils.evalPythonMessage(this.props.method, params)
               .then((response) => {
diff --git a/webapp/components/general/Select.js b/webapp/components/general/Select.js
index ac5c69c6..86826e34 100644
--- a/webapp/components/general/Select.js
+++ b/webapp/components/general/Select.js
@@ -21,7 +21,7 @@ class Select extends React.Component {
           value={value}
           onChange={this.props.onChange}
           multiple={!!this.props.multiple}
-          pythonParams={this.props.pythonParams}
+          pythonparams={this.props.pythonparams}
         >
           {this.props.children}
         </MuiSelect>
diff --git a/webapp/components/general/TutorialBubble.js b/webapp/components/general/TutorialBubble.js
new file mode 100644
index 00000000..34fe5253
--- /dev/null
+++ b/webapp/components/general/TutorialBubble.js
@@ -0,0 +1,211 @@
+import React, { useState, useRef, useEffect } from 'react';
+import {
+  Box, Button, Grid, Typography,
+} from '@material-ui/core';
+import {
+  primaryColor, secondaryColor, bgLight, bgDark, primaryTextColor, secondaryTextColor, fontColor,
+} from '../../theme';
+
+const rectMargin = 4;
+
+const TutorialBubble = ({
+  requestedTourStep, steps, lastCheckRender, stopTutorial, incrementTutorialStep, validateTutorialStep, currentTourStep,
+}) => {
+  const tutorialTarget = useRef(null);
+
+  useEffect(() => () => {
+    tutorialTarget.current = null;
+  }, []);
+
+  const getDOMTarget = (target, config) => {
+    // We query the DOM with the selector
+    let DOMtargets = document.querySelectorAll(target);
+
+    if (!DOMtargets || DOMtargets.length == 0) {
+      DOMtargets = document.getElementsByClassName(target);
+      if (!DOMtargets || DOMtargets.length == 0) {
+        DOMtargets = document.getElementsByTagName(target);
+      }
+    }
+
+    // if there is no DOM element, we stop the tutorial
+    if (!DOMtargets || DOMtargets.length == 0) {
+      return null;
+    }
+
+    // we pass the element index as configuration or 0 by default
+    return DOMtargets[config?.collectionIndex || 0];
+  };
+
+  function calculateVisiblePosition (rect1, width2, height2) {
+    const windowHeight = window.innerHeight;
+    const windowWidth = window.innerWidth;
+
+    let x = rect1.left + (rect1.width / 2) - (width2 / 2);
+    let y = (rect1.top - windowHeight) + rect1.height;
+
+    // Check if element2 is outside the viewport horizontally
+    if (x + width2 > windowWidth) {
+      x = rect1.left - width2;
+    }
+
+    if (x < 0) {
+      x = rect1.left + rect1.width + (2 * rectMargin);
+      y = rect1.top - windowHeight - rect1.height - rectMargin;
+    }
+
+    // Check if element2 is outside the viewport vertically
+    if (y + height2 > windowHeight) {
+      y = (rect1.top - windowHeight) + rect1.height - height2;
+    }
+
+    return { x, y };
+  }
+
+  const tourStep = steps[requestedTourStep - 1];
+  if (!tourStep) {
+    return null;
+  }
+
+  const nextTourStep = steps[requestedTourStep];
+  const { target: nextTarget } = nextTourStep || { target: undefined };
+
+  const { target, title, content } = tourStep;
+
+  const DOMtarget = getDOMTarget(target, tourStep);
+  const nextDOMtarget = getDOMTarget(nextTarget, nextTourStep);
+  const visible = DOMtarget?.checkVisibility();
+
+  if (!visible) {
+    return <></>;
+  }
+
+  // validateTutorialStep({ tourStep: requestedTourStep });
+  const isEditable = (el) => {
+    if (el && ~['input', 'textarea'].indexOf(el.tagName.toLowerCase())) {
+      return !el.readOnly && !el.disabled;
+    }
+    el = getSelection().anchorNode;
+    if (!el) {
+      return false;
+    }
+    return el.parentNode.isContentEditable;
+  };
+
+  const isAnyEditable = (element) => {
+    if (isEditable(element)) {
+      return true;
+    }
+
+    for (const child of element.children) {
+      if (isAnyEditable(child)) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  const listen = (event) => {
+    tutorialTarget.current = null;
+    incrementTutorialStep();
+  };
+
+  const stop = (event) => {
+    stopTutorial(event);
+    tutorialTarget.current = null;
+  };
+
+  if (currentTourStep === requestedTourStep) {
+    tutorialTarget.current = null;
+  }
+
+  if (!tutorialTarget.current && currentTourStep !== requestedTourStep) {
+    tutorialTarget.current = DOMtarget;
+    let { waitFor } = tourStep;
+    if (!waitFor) {
+      waitFor = isAnyEditable(DOMtarget) ? 'fieldEdition' : 'click';
+    }
+    switch (waitFor) {
+      case 'click':
+        if (requestedTourStep === steps.length) {
+          DOMtarget.addEventListener('click', stop, { once: true, capture: true });
+        } else {
+          DOMtarget.addEventListener('click', listen, { once: true, capture: true });
+        }
+        break;
+      case 'fieldEdition': // Do nothing, we wait for a click on "next"
+        break;
+      default:
+        break;
+    }
+  }
+
+  const targetRect = DOMtarget.getBoundingClientRect();
+  const { x, y } = calculateVisiblePosition(targetRect, 150, 300);
+
+  const hasOtherSteps = requestedTourStep < steps.length;
+  const nextIsVisible = nextDOMtarget?.checkVisibility();
+
+  return (
+    <Box className="tutorials">
+      <Box
+        className="tutorials_highlight"
+        id="tutorialTargetRectangle"
+        style={{
+          top: targetRect.top - rectMargin,
+          left: targetRect.left - rectMargin,
+          width: targetRect.width + (2 * rectMargin),
+          height: targetRect.height + (2 * rectMargin),
+          borderColor: primaryColor,
+
+        }}
+      />
+
+      <Box className="tutorials_wrapper" id="tutorialBubble">
+        <Box
+          className="tutorials_content"
+          style={{
+            top: y,
+            left: x,
+          }}
+        >
+          <Typography component="h3">
+            {title}
+          </Typography>
+
+          {content}
+
+          <Box pt={2.5} display="flex" alignItems="center" justifyContent="space-between">
+            <Typography>
+              {requestedTourStep}
+              /
+              {steps.length}
+            </Typography>
+
+            <Box display="flex" alignItems="center">
+              <Button
+                onClick={stop}
+                color="primary"
+              >
+                {hasOtherSteps ? 'Skip' : 'Close'}
+              </Button>
+
+              {hasOtherSteps && (
+                <Button
+                  variant="contained"
+                  color="primary"
+                  onClick={listen}
+                  disabled={!nextIsVisible}
+                >
+                  Next
+                </Button>
+              )}
+            </Box>
+          </Box>
+        </Box>
+      </Box>
+    </Box>
+  );
+};
+
+export default TutorialBubble;
diff --git a/webapp/components/general/TutorialObserver.js b/webapp/components/general/TutorialObserver.js
new file mode 100644
index 00000000..81fec689
--- /dev/null
+++ b/webapp/components/general/TutorialObserver.js
@@ -0,0 +1,77 @@
+import React, { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+import TutorialBubble from './TutorialBubble';
+
+export default function TutorialObserver (props) {
+  const tourRunning = useSelector((state) => state.tutorial.tourRunning);
+  const [observer, setObserver] = useState(null);
+
+  const {
+    steps,
+    tourStep,
+    requestedTourStep,
+    startTutorialStep,
+    stopTutorialStep,
+    incrementTutorialStep,
+    validateTutorialStep,
+    checkBubbleRender,
+    lastCheckRender,
+    children,
+  } = props;
+
+  const bubbleUpdate = () => {
+    checkBubbleRender({ epoch: Date.now() });
+  };
+
+  useEffect(() => {
+    if (!tourRunning) {
+      // Stop observing the DOM when the component unmounts
+      // console.log("Tutorial is finished")
+      observer?.disconnect();
+      return;
+    }
+    // Listen for new components being added to the DOM
+    // eslint-disable-next-line no-undef
+    const obs = new MutationObserver((mutationsList) => {
+      if (mutationsList.length > 0) {
+        bubbleUpdate();
+      }
+    });
+
+    // Start observing the DOM
+    obs.observe(document.body, { childList: true, subtree: true, attributes: true });
+    setObserver(obs);
+  }, [tourRunning]);
+
+  const startTutorialCallBack = () => {
+    startTutorialStep();
+  };
+
+  const stopTutorial = () => {
+    stopTutorialStep();
+  };
+
+  const doIncrementTutorialStep = () => {
+    validateTutorialStep({ tourStep: requestedTourStep });
+    incrementTutorialStep();
+  };
+
+  return (
+    <>
+      {children}
+      {tourRunning && (
+        <>
+          <TutorialBubble
+            requestedTourStep={requestedTourStep}
+            currentTourStep={tourStep}
+            steps={steps}
+            stopTutorial={() => stopTutorial()}
+            incrementTutorialStep={doIncrementTutorialStep}
+            validateTutorialStep={validateTutorialStep}
+            lastCheckRender={lastCheckRender}
+          />
+        </>
+      )}
+    </>
+  );
+}
diff --git a/webapp/components/index.js b/webapp/components/index.js
index e3e177d5..a3a80266 100644
--- a/webapp/components/index.js
+++ b/webapp/components/index.js
@@ -18,6 +18,7 @@ import {
   createAndSimulateNetwork, showNetwork, pythonCall, deleteNetParamsObj, resetModel,
   setDefaultWidgets, changeInstanceColor, openConfirmationDialog, closeConfirmationDialog, selectInstances,
 } from '../redux/actions/general';
+import { runControlledStep, startTutorial, stopTutorial, addDiscoveredStep, runControlledStepByElementId, incrementTutorialStep, validateTutorialStep, checkBubbleRender } from '../redux/actions/tutorials';
 
 import {
   cloneExperiment,
@@ -71,6 +72,7 @@ import _ExperimentManager from './experiments/ExperimentManager';
 import _LaunchDialog from './topbar/dialogs/LaunchDialog';
 import _NetPyNEPythonConsole from './general/NetPyNEPythonConsole';
 import _PlotViewer from './general/PlotViewer';
+import _TutorialObserver from './general/TutorialObserver';
 import _ExperimentControlPanel from './general/ExperimentControlPanel';
 import _Rxd from './rxd/Wrapper';
 import { WidgetStatus } from '@metacell/geppetto-meta-client/common/layout/model';
@@ -424,6 +426,27 @@ export const Rxd = connect(
   ),
 );
 
+export const TutorialObserver = connect(
+  (state) => ({
+    steps: state.tutorial.steps,
+    tourStep: state.tutorial.tourStep,
+    tourRunning: state.tutorial.tourRunning,
+    requestedTourStep: state.tutorial.requestedTourStep,
+    lastCheckRender: state.tutorial.lastCheckRender,
+  }),
+  (dispatch) => ({
+    startTutorialStep: () => { dispatch(startTutorial()) },
+    runControlledStep: () => { dispatch(runControlledStep()) },
+    stopTutorialStep: () => { dispatch(stopTutorial()) },
+    validateTutorialStep: (e) => { dispatch(validateTutorialStep(e)) },
+    addDiscoveredStep: (nodeIdList) => { dispatch(addDiscoveredStep(nodeIdList)) },
+    runControlledStepByElementId: (e) => { dispatch(runControlledStepByElementId(e))},
+    incrementTutorialStep: (e) => { dispatch(incrementTutorialStep()); },
+    checkBubbleRender: (e) => { dispatch(checkBubbleRender(e))}
+  }),
+)(_TutorialObserver);
+
+
 // ---------------------------------------------------------------------------------------- //
 
 // DEFAULTS
diff --git a/webapp/components/rxd/RxdRegion.js b/webapp/components/rxd/RxdRegion.js
index 75a7c163..3f6e8762 100644
--- a/webapp/components/rxd/RxdRegion.js
+++ b/webapp/components/rxd/RxdRegion.js
@@ -251,7 +251,7 @@ const RxdRegion = (props) => {
                 multiple={1}
                 model={`${baseTag}['secs']`}
                 method="netpyne_geppetto.getAvailableRxDSections"
-                pythonParams={[props.id]}
+                pythonparams={[props.id]}
                 postProcessItems={postProcessSecs}
               />
             </NetPyNEField>
diff --git a/webapp/components/topbar/Topbar.js b/webapp/components/topbar/Topbar.js
index 9693d94b..1b29ad3f 100644
--- a/webapp/components/topbar/Topbar.js
+++ b/webapp/components/topbar/Topbar.js
@@ -23,6 +23,11 @@ import ImportExportHLSDialog from './dialogs/ImportExportHLS';
 import ImportCellParamsDialog from './dialogs/ImportCellParams';
 import UploadDownloadFilesDialog from './dialogs/UploadDownloadFiles';
 
+import tutorial_steps from '../../redux/reducers/data/tutorial_steps';
+import tutorial2_steps from '../../redux/reducers/data/tutorial2_steps';
+import tutorial3_steps from '../../redux/reducers/data/tutorial3_steps';
+
+import { startTutorial } from '../../redux/actions/tutorials';
 import { TOPBAR_CONSTANTS, MODEL_STATE, DEFAULT_CONFIRMATION_DIALOG_MESSAGE, NETPYNE_COMMANDS } from '../../constants';
 import { LOAD_TUTORIAL, registerModelPath, loadModel } from '../../redux/actions/general';
 import OverwriteModel from './dialogs/OverwriteModel';
@@ -120,7 +125,13 @@ class Topbar extends Component {
 
         break;
       }
-
+      case 'triggerTutorials': {
+        const [index] = click.parameters;
+        const tutorials = [tutorial_steps, tutorial2_steps, tutorial3_steps];
+        const action = startTutorial(tutorials[index]);
+        this.props.dispatchAction(action);
+        break;
+      }
       default:
         console.log(`Menu action not mapped, it is ${click}`);
     }
diff --git a/webapp/components/topbar/dialogs/ImportCellParams.js b/webapp/components/topbar/dialogs/ImportCellParams.js
index 5d7ae803..ae8f300a 100644
--- a/webapp/components/topbar/dialogs/ImportCellParams.js
+++ b/webapp/components/topbar/dialogs/ImportCellParams.js
@@ -133,6 +133,7 @@ class ImportCellParams extends React.Component {
 
         <NetPyNEField id="netParams.importCellParams.fileName">
           <TextField
+            id="importCellParamsFileName"
             variant="filled"
             fullWidth
             value={fileName}
@@ -155,6 +156,7 @@ class ImportCellParams extends React.Component {
 
         <NetPyNEField id="netParams.importCellParams.modFolder">
           <TextField
+            id="importCellParamsModFolder"
             fullWidth
             variant="filled"
             value={modFolder}
diff --git a/webapp/components/topbar/menuConfiguration.js b/webapp/components/topbar/menuConfiguration.js
index 1cf0edd8..57df0c6e 100644
--- a/webapp/components/topbar/menuConfiguration.js
+++ b/webapp/components/topbar/menuConfiguration.js
@@ -286,7 +286,7 @@ export default {
       },
     },
     {
-      label: 'Tutorials',
+      label: 'Examples',
       icon: '',
       position: 'bottom-start',
       style: topLevelMenuItemStyle,
@@ -309,6 +309,36 @@ export default {
             parameters: ['http://netpyne.org/'],
           },
         },
+        {
+          label: 'Tutorials',
+          icon: '',
+          list: [
+            {
+              label: 'Open tutorial 1',
+              icon: '',
+              action: {
+                handlerAction: 'triggerTutorials',
+                parameters: [0],
+              },
+            },
+            {
+              label: 'Open tutorial 2',
+              icon: '',
+              action: {
+                handlerAction: 'triggerTutorials',
+                parameters: [1],
+              },
+            },
+            {
+              label: 'Open tutorial 3',
+              icon: '',
+              action: {
+                handlerAction: 'triggerTutorials',
+                parameters: [2],
+              },
+            },
+          ],
+        },
       ],
     },
   ],
diff --git a/webapp/constants.js b/webapp/constants.js
index 857280c6..dd246436 100644
--- a/webapp/constants.js
+++ b/webapp/constants.js
@@ -696,12 +696,12 @@ export const EXPERIMENT_TEXTS = {
 };
 
 export const TUTORIALS_LIST = {
-  tut1: 'Tut 1: Simple cell network',
-  tut2: 'Tut 2: Detailed cell network',
-  tut3: 'Tut 3a: Multiscale network (low IP3)',
-  tut3_ip3high: 'Tut 3b: Multiscale network (high IP3)',
-  tut3_norxd: 'Tut 3c: Multiscale network (no RxD)',
-  tut_osc: 'Tut 4: Simple oscillatory network',
+  tut1: 'Model 1: Simple cell network',
+  tut2: 'Model 2: Detailed cell network',
+  tut3: 'Model 3a: Multiscale network (low IP3)',
+  tut3_ip3high: 'Model 3b: Multiscale network (high IP3)',
+  tut3_norxd: 'Model 3c: Multiscale network (no RxD)',
+  tut_osc: 'Model 4: Simple oscillatory network',
 };
 
 export const EXPERIMENT_VIEWS = {
diff --git a/webapp/css/netpyne.less b/webapp/css/netpyne.less
index 661c40a1..f8282e2b 100644
--- a/webapp/css/netpyne.less
+++ b/webapp/css/netpyne.less
@@ -618,3 +618,55 @@ body {
     }
   }
 }
+
+.tutorials {
+	&_highlight {
+		position: absolute;
+		border-radius: 0.25rem;
+		pointer-events: none;
+		border: solid 0.125rem;
+		z-index: 1501; // Just over the menus items (1500)
+	}
+
+	&_wrapper {
+		position: relative;
+	}
+
+	&_content {
+		position: absolute;
+		background: @bgRegular;
+		box-shadow: @tutorialShadow;
+		backdrop-filter: blur(1.25rem);
+		border-radius: 0.25rem;
+		padding: 1.25rem;
+		width: 25rem;
+		z-index: 1501; // Just over the menus items (1500)
+
+		h3 {
+			margin: 0 0 0.75rem;
+			font-weight: 600;
+			font-size: 1.25rem;
+			line-height: 1.5rem;
+			color: @textColor;
+		}
+
+		p {
+			font-weight: 400;
+			font-size: 1rem;
+			margin: 0;
+			line-height: 1.5rem;
+			color: rgba(@textColor, 0.8);
+
+      & + p {
+        margin-top: 0.5rem;
+      }
+		}
+
+		.MuiButton-root {
+			font-weight: 600;
+			&:not(:first-child) {
+				margin-left: 0.5rem;
+			}
+		}
+	}
+}
diff --git a/webapp/css/variables.less b/webapp/css/variables.less
index 2ed99011..4d83d679 100644
--- a/webapp/css/variables.less
+++ b/webapp/css/variables.less
@@ -38,3 +38,4 @@
 @fabDisableColor: rgba(255, 255, 255, 0.3);
 @navShadow: rgba(255, 255, 255, 0.2);
 @tabsTextColor: rgba(255, 255, 255, 0.7);
+@tutorialShadow: 0px 10px 60px rgba(0, 0, 0, 0.5);
\ No newline at end of file
diff --git a/webapp/package.bak b/webapp/package.bak
index 3f4ee302..5eeb75a3 100644
--- a/webapp/package.bak
+++ b/webapp/package.bak
@@ -6,7 +6,7 @@
   "license": "MIT",
   "scripts": {
     "lint": "eslint . --color --fix",
-    "build": "webpack --mode production -p --progress --devtool source-map",
+    "build": "webpack --mode development -p --progress --devtool source-map",
     "build-dev": "webpack --mode development --devtool source-map",
     "build-dev-noTest": "webpack --mode development --devtool source-map --env.noTest=true",
     "build-dev-noTest:watch": "webpack --mode development --devtool source-map --env.noTest=true --progress --watch",
@@ -19,9 +19,9 @@
     "@material-ui/core": "4.12.1",
     "@material-ui/icons": "^4.11.2",
     "@material-ui/lab": "^4.0.0-alpha.60",
-    "@metacell/geppetto-meta-client": "1.1.0",
-    "@metacell/geppetto-meta-core": "1.1.0",
-    "@metacell/geppetto-meta-ui": "1.1.0",
+    "@metacell/geppetto-meta-client": "1.2.0",
+    "@metacell/geppetto-meta-core": "1.2.0",
+    "@metacell/geppetto-meta-ui": "1.2.0",
     "@nosferatu500/react-sortable-tree": "3.0.5",
     "@sentry/integrations": "^6.16.1",
     "@sentry/react": "^6.16.1",
@@ -96,4 +96,4 @@
       ]
     }
   }
-}
\ No newline at end of file
+}
diff --git a/webapp/redux/actions/tutorials.js b/webapp/redux/actions/tutorials.js
new file mode 100644
index 00000000..21ecde2f
--- /dev/null
+++ b/webapp/redux/actions/tutorials.js
@@ -0,0 +1,19 @@
+// Action Types
+export const START_TUTORIAL = 'START_TUTORIAL';
+export const STOP_TUTORIAL = 'STOP_TUTORIAL';
+export const INCREMENT_TUTORIAL_STEP = 'INCREMENT_TUTORIAL_STEP';
+export const RUN_CONTROLLED_STEP = 'RUN_CONTROLLED_STEP'; 
+export const ADD_DISCOVERED_STEP = 'ADD_DISCOVERED_STEP'; 
+export const RUN_CONTROLLED_STEP_BY_ELEMENT_ID = 'RUN_CONTROLLED_STEP_BY_ELEMENT_ID';
+export const VALIDATE_TUTORIAL_STEP = 'VALIDATE_TUTORIAL_STEP';
+export const CHECK_BUBBLE_RENDER = 'CHECK_BUBBLE_RENDER';
+
+// Actions
+export const startTutorial         = (payload, metadata = {}) => ({ type: START_TUTORIAL, payload, metadata });
+export const stopTutorial          = (payload, metadata = {}) => ({ type: STOP_TUTORIAL, metadata });
+export const incrementTutorialStep = (payload, metadata = {}) => ({ type: INCREMENT_TUTORIAL_STEP, payload, metadata });;
+export const runControlledStep     = (payload, metadata = {}) => ({ type: RUN_CONTROLLED_STEP, payload, metadata })
+export const runControlledStepByElementId     = (payload, metadata = {}) => ({ type: RUN_CONTROLLED_STEP_BY_ELEMENT_ID, payload, metadata })
+export const addDiscoveredStep     = (payload, metadata = {}) => ({ type: ADD_DISCOVERED_STEP, payload, metadata })
+export const validateTutorialStep  = (payload, metadata = {}) => ({ type: VALIDATE_TUTORIAL_STEP, payload, metadata })
+export const checkBubbleRender     = (payload, metadata = {}) => ({ type: CHECK_BUBBLE_RENDER, payload, metadata })
\ No newline at end of file
diff --git a/webapp/redux/middleware/middleware.js b/webapp/redux/middleware/middleware.js
index f83c5a40..58ae6390 100644
--- a/webapp/redux/middleware/middleware.js
+++ b/webapp/redux/middleware/middleware.js
@@ -11,7 +11,6 @@ import {
 import { NETPYNE_COMMANDS, EDIT_WIDGETS } from '../../constants';
 import * as GeppettoActions from '@metacell/geppetto-meta-client/common/actions';
 import * as ExperimentsApi from '../../api/experiments';
-
 import {
   UPDATE_CARDS,
   CREATE_NETWORK,
@@ -386,7 +385,7 @@ export default (store) => (next) => (action) => {
         default:
           break;
       }
-      
+
       pythonCall(action)
         .then(callback, pythonErrorCallback);
       next(action);
diff --git a/webapp/redux/reducers/all.js b/webapp/redux/reducers/all.js
index bbca212b..f92e6055 100644
--- a/webapp/redux/reducers/all.js
+++ b/webapp/redux/reducers/all.js
@@ -4,6 +4,7 @@ import notebook from './notebook';
 import errors from './errors';
 import drawer from './drawer';
 import topbar from './topbar';
+import tutorial from './tutorial'
 import experiments from './experiments';
 
 export default {
@@ -12,5 +13,6 @@ export default {
   errors: errors,
   drawer: drawer,
   topbar: topbar,
+  tutorial: tutorial,
   experiments: experiments,
 };
diff --git a/webapp/redux/reducers/data/tutorial2_steps.js b/webapp/redux/reducers/data/tutorial2_steps.js
new file mode 100644
index 00000000..79c662cd
--- /dev/null
+++ b/webapp/redux/reducers/data/tutorial2_steps.js
@@ -0,0 +1,190 @@
+import React from 'react';
+const tutorial2_steps = [
+  {
+    target: '#selectCellButton',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>We will create first a new cell using a cell template.</p>
+        <p>Click on the "+" to create a new cell.</p>
+      </div>
+    )
+  },
+  {
+    target: '#fromTemplateCellTemplate',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Select "Import cell template from file..."</p>
+      </div>
+    )
+  },
+  {
+    target: '#importCellParamsFileName',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Click on the folder icon to select the template:</p>
+        <p> NetPyNE tutorials &gt; netpyne_workspace-master</p>
+        <p> &gt; cells &gt; PTcells.hoc</p>
+      </div>
+    )
+  },
+  // {
+  //   target: '#TreeContainerCutting_component',
+  //   content: (
+  //     <div>
+  //       <p>Select "NetPyNE tutorials &gt; netpyne_workspace-master &gt; cells &gt; PTcells.hoc".</p>
+  //     </div>
+  //   )
+  // },
+  {
+    target: '#importCellParamsModFolder',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Click on the folder icon to select the folder containing the "mod" file:</p>
+        <p>"NetPyNE tutorials &gt; netpyne_workspace-master &gt; mod</p>
+      </div>
+    )
+  },
+  // {
+  //   target: '#TreeContainerCutting_component',
+  //   content: (
+  //     <div>
+  //       <p>Select "NetPyNE tutorials &gt; netpyne_workspace-master &gt; mod".</p>
+  //     </div>
+  //   )
+  // },
+  {
+    target: '#appBarPerformActionButton',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Click on "Import" to import the cell template.</p>
+      </div>
+    )
+  },
+  {
+    target: '#PTcell',
+    title: (
+      <div>Cell Modifications</div>
+    ),
+    content: (
+      <div>
+        <p>Select the PT cell.</p>
+      </div>
+    )
+  },
+  {
+    target: '#newSectionButton',
+    title: (
+      <div>Cell Modifications</div>
+    ),
+    content: (
+      <div>
+        <p>Click on "Section" to see all the sections of the cell.</p>
+      </div>
+    )
+  },
+  {
+    target: '#selectCellButton',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Go back to the cell creation and import a new one from a template as before.</p>
+      </div>
+    )
+  },
+  {
+    target: '#importCellParamsFileName',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Click on the folder icon to select the template.</p>
+      </div>
+    )
+  },
+  {
+    target: '#TreeContainerCutting_component',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Select "NetPyNE tutorials &gt; netpyne_workspace-master &gt; cells &gt; SRI.hoc".</p>
+      </div>
+    )
+  },
+  {
+    target: '#importCellParamsModFolder',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Click on the folder icon to select the folder containing the "mod" file.</p>
+      </div>
+    )
+  },
+  {
+    target: '#TreeContainerCutting_component',
+    title: (
+      <div>Cell Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Select, as for the last created cell:</p>
+        <p>"NetPyNE tutorials &gt; netpyne_workspace-master &gt; mod".</p>
+      </div>
+    )
+  },
+  {
+    target: 'img[src*="popParams"]',
+    title: (
+      <div>Population Update</div>
+    ),
+    content: (
+      <div>
+        <p>Click on "Populations" to change cells populations.</p>
+      </div>
+    )
+  },
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: (
+      <div>Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Create now the network!</p>
+      </div>
+    )
+  },
+  {
+    target: 'img[src*="experimentControlPanel"]',
+    title: (
+      <div>Visualization</div>
+    ),
+    content: (
+      <div>
+        <p>You can open the control panel to see the the cell population and identify them in the 3D view.</p>
+      </div>
+    )
+  }
+]
+export default tutorial2_steps ;
diff --git a/webapp/redux/reducers/data/tutorial3_steps.js b/webapp/redux/reducers/data/tutorial3_steps.js
new file mode 100644
index 00000000..35655d79
--- /dev/null
+++ b/webapp/redux/reducers/data/tutorial3_steps.js
@@ -0,0 +1,201 @@
+import React from 'react';
+const tutorial3_steps = [
+  // Tutorial template selection
+  {
+    target: 'button[id="Examples"]',
+    title: (
+      <div>Tutorial Template Selection</div>
+    ),
+    content: (
+      <div>
+        <p>Open the tutorial menu.</p>
+      </div>
+    )
+  },
+  {
+    target: 'li[label*="3a:"]',
+    title: (
+      <div>Tutorial Template Selection</div>
+    ),
+    content: (
+      <div>
+        <p>Select the tutorial 3a.</p>
+      </div>
+    )
+  },
+  // Create and Simulate
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: (
+      <div>Creation</div>
+    ),
+    content: (
+      <div>
+        <p>Create/update the network to visualize its 3D representation and associate plots.</p>
+      </div>
+    )
+  },
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: (
+      <div>Simulation</div>
+    ),
+    content: (
+      <div>
+        <p>Simulate the network model.</p>
+        <p>Please note that the simulation takes time and depends on the resources of the host machine.</p>
+      </div>
+    )
+  },
+  // Opening of the Different Plots
+  {
+    target: 'div[aria-disabled=false] img[src*="rasterPlot"]',
+    title: (
+      <div>Opening of the Different Plots</div>
+    ),
+    content: (
+      <div>
+        <p>Open the Raster Plot, the LFP Time Series Plot, the RxD Concentration Plot and the Spike History Plot.</p>
+      </div>
+    )
+  },
+  {
+    target: 'div[aria-disabled=false] img[src*="LFPTimeSeriesPlot"]',
+    title: (
+      <div>Opening of the Different Plots</div>
+    ),
+    content: (
+      <div>
+        <p>LFP Time Series Plot.</p>
+      </div>
+    )
+  },
+  {
+    target: 'div[aria-disabled=false] img[src*="rxdConcentrationPlot"]',
+    title: (
+      <div>Opening of the Different Plots</div>
+    ),
+    content: (
+      <div>
+        <p>RxD Concentration Plot.</p>
+      </div>
+    )
+  },
+  {
+    target: 'div[aria-disabled=false] img[src*="spikePlot"]',
+    title: (
+      <div>Opening of the Different Plots</div>
+    ),
+    content: (
+      <div>
+        <p>Spike History Plot.</p>
+      </div>
+    )
+  },
+  // Go back to edit
+  {
+    target: 'div [class*="SwitchPageButton"] .MuiButton-root',
+    title: (
+      <div>Model and Parameter Modifications</div>
+    ),
+    content: (
+      <div>
+        <p>Go back to the network edition.</p>
+      </div>
+    )
+  },
+  // RxD Configuration Modification
+  {
+    target: 'div[aria-disabled=false] img[src*="rxd.svg"]',
+    title: (
+      <div>RxD Configuration Modification</div>
+    ),
+    content: (
+      <div>
+        <p>Select the RxD Configuration.</p>
+      </div>
+    )
+  },
+  {
+    target: 'button.MuiTab-labelIcon:nth-child(2)',
+    title: (
+      <div>RxD Configuration Modification</div>
+    ),
+    content: (
+      <div>
+        <p>Click on "Species".</p>
+      </div>
+    )
+  },
+  {
+    target: '#ip3',
+    title: (
+      <div>RxD Configuration Modification</div>
+    ),
+    content: (
+      <div>
+        <p>Select IP3 to increate the initial concentration.</p>
+      </div>
+    )
+  },
+  {
+    target: '#netParamsrxdParamsspeciesip3initial',
+    title: (
+      <div>RxD Configuration Modification</div>
+    ),
+    content: (
+      <div>
+        <p>Increase the initial concentration to 0.1.</p>
+      </div>
+    ),
+    waitFor: 'fieldEdition'
+  },
+  // Update the model
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: (
+      <div>Updating</div>
+    ),
+    content: (
+      <div>
+        <p>Update the network model.</p>
+      </div>
+    )
+  },
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: (
+      <div>Simulation</div>
+    ),
+    content: (
+      <div>
+        <p>And simulate the modified network model.</p>
+        <p>Please note that the simulation takes time and depends on the resources of the host machine.</p>
+      </div>
+    )
+  },
+  // Open the plots
+  {
+    target: 'div[aria-disabled=false] img[src*="rasterPlot"]',
+    title: (
+      <div>Plots Display</div>
+    ),
+    content: (
+      <div>
+        <p>Reopen the Raster Plot, the LFP Time Series Plot, the RxD Concentration Plot and the Spike History Plot to see how the plots are impatected by the modification.</p>
+      </div>
+    )
+  },
+]
+export default tutorial3_steps ;
+
+
+// .MuiGrid-item .MuiButton-root:nth-last-child(2)  => CREATE_NETWORK/SIMULATE
+// div [class*='SwitchPageButton'] .MuiButton-root  => BACK TO EDIT
+
+// .flexlayout__layout .flexlayout__tab_button_top:nth-child(2) ??
+
+// li[label*='Tut 3a:'
+
+// div[aria-disabled=false] img[src*='rasterPlot']  => raster plot
+// div[aria-disabled=false] img[src*='rxd']
\ No newline at end of file
diff --git a/webapp/redux/reducers/data/tutorial_steps.js b/webapp/redux/reducers/data/tutorial_steps.js
new file mode 100644
index 00000000..edcdfecc
--- /dev/null
+++ b/webapp/redux/reducers/data/tutorial_steps.js
@@ -0,0 +1,752 @@
+import React from 'react';
+
+const tutorial_steps = [
+  {
+    target: '#selectCellButton',
+    title: 'Simple Cell Model Creation',
+    content: <p>Click on the + above Cell</p>
+  },
+  {
+    target: '#BallStick_HHCellTemplate',
+    title: 'New Cell Addition',
+    content: (
+      <p>Click on the menu item to add one Ball and stick HH cell</p>
+    )
+  },
+  {
+    target: '#CellType0',
+    title: 'Cell Customization',
+    content: (
+      <p>Click on CellType0 and the panel on the right will appear.</p>
+    )
+  },
+  {
+    target: '#cellRuleName',
+    title: 'Cell Customization',
+    content: (
+      <p>Rename the cell type: "pyr" for pyramidal.</p>
+    )
+  },
+  {
+    target: '#newSectionButton',
+    title: 'Check Cell"s Sections',
+    content: (
+      <p>Click on Section to see the sections that make up this imported cell type</p>
+    )
+  },
+  {
+    target: 'input[value*="soma"]',
+    title: 'Check Cell"s Sections',
+    content: (
+      <p>We can check that the name of the section is "soma"</p>
+    )
+  },
+  {
+    target: 'img[src*="popParams.svg"]',
+    title: 'Cell Population Creation',
+    content: (
+      <>
+        <p>Click on the Populations icon.</p>
+        <p>You can also find the each sidebar icons as tab in the top panel</p>
+      </>
+    )
+  },
+  // {
+  //   target: 'div.flexlayout__tabset_tabbar_inner.flexlayout__tabset_tabbar_inner_top > div > div:nth-child(2)',
+  //   title: (
+  //     <div>Populations component</div>
+  //   ),
+  //   content: (
+  //     <div>
+  //       <p>Click on the Populations tab or its icon in the sidebar</p>
+  //     </div>
+  //   ),
+  // },
+  {
+    target: '#newPopulationButton',
+    title: 'Cell Population Creation',
+    content: (
+      <p>Click on the + above Population</p>
+    )
+  },
+  // {
+  //   target: '#Population0',
+  //   content: (
+  //     <div>
+  //       <p>Select the first population</p>
+  //     </div>
+  //   )
+  // },
+  {
+    target: 'div.MuiBox-root.scrollbar.scrollchild > div.MuiBox-root > div',
+    title: 'Cell Population Creation',
+    content: (
+      <p>Change the population name to “E” for excitatory</p>
+    )
+  },
+  {
+    target: 'div[id*="netParamspopParams"][id*="cellType"]',
+    title: 'Cell Population Creation',
+    content: (
+      <p>Set the Cell type to the "pyr" cell we imported earlier</p>
+    )
+  },
+  {
+    target: 'input[id*="numCells"]',
+    title: 'Cell Population Creation',
+    content: (
+      <p>Enter 40 for the number of cells</p>
+    )
+  },
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: 'Network Creation',
+    content: (
+      <p>Once we have a population with cells, we can create our network and visualize it</p>
+    )
+  },
+  {
+    target: 'flexlayout__tab_button flexlayout__tab_button_top flexlayout__tab_button--selected',
+    title: 'Network Visualization',
+    content: (
+      <>
+        <p>You can see the layout of our 40 pyr cells</p>
+        <p>You can rotate, pan, and zoom</p>
+        <p>You can choose colors from the control panel</p>
+        <p>Most analysis plots (sidebar) are useless without having run a simulation</p>
+      </>
+    )
+  },
+  {
+    target: 'material-icons MuiIcon-root',
+    title: '2D Net Plot Panel',
+    content: (
+      <>
+        <p>The 2D net plot shows cell positions</p>
+        <p>No connectivity has been added yet</p>
+        <p>Explore the interactive plot</p>
+        <p>Explore moving and reshaping tabs (drag from the tab title)</p>
+      </>
+    ),
+    collectionIndex: 2
+  },
+  {
+    target: 'MuiButtonBase-root MuiButton-root MuiButton-contained',
+    title: 'Model Modifications',
+    content: (
+      <p>Click on Back To Edit</p>
+    ),
+    collectionIndex: 6
+  },
+  {
+    target: 'img[src*="synMechParams.svg"]',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Click on Synaptic Mechanisms</p>
+    ),
+  },
+  {
+    target: '#newSynapseButton',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Click on + above Synapse </p>
+    )
+  },
+  {
+    target: 'MuiInputBase-input MuiFilledInput-input',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Name the synapse “exc”</p>
+    ),
+    collectionIndex: 2
+  },
+  {
+    target: 'MuiInputBase-input MuiFilledInput-input',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Leave the default mechanism Exp2Syn</p>
+    ),
+    collectionIndex: 3
+  },
+  {
+    target: 'MuiInputBase-input MuiFilledInput-input',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Enter 0.1 in Time constant for exponential 1 </p>
+    ),
+    collectionIndex: 4
+  },
+  {
+    target: 'MuiInputBase-input MuiFilledInput-input',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Enter 1.0 in Time constant for exponential 2</p>
+    ),
+    collectionIndex: 5
+  },
+  {
+    target: 'MuiInputBase-input MuiFilledInput-input',
+    title: 'Synaptic Mechanism Creation',
+    content: (
+      <p>Enter 0 in Reversal potential </p>
+    ),
+    collectionIndex: 6
+  },
+  {
+    target: 'img[src*="connParams.svg"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <p>Click on Connectivity Rules in tabs or sidebar</p>
+    ),
+  },
+  {
+    target: '#newConnectivityRuleButton',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <p>Click on + above Connectivity Rule </p>
+    )
+  },
+  { // ConnectivityName
+    target: '#ConnectivityName',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <p>Name the rule "E-&gt;E" (without spaces)</p>
+    ),
+  },
+  { // netParamsconnParamsConnectivityRule0sec
+    target: 'input[id*="netParamsconnParams"][id*="sec"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Add "dend" as new postsynaptic neuron section</p>
+      </>
+    ),
+  },
+  {
+    target: 'button[id^="netParamsconnParams"][id$="sec-button"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Click on "+" to add the value</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsconnParams"][id*="loc"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Enter 0.5 as new postsynaptic neuron location</p>
+      </>
+    ),
+  },
+  {
+    target: 'button[id^="netParamsconnParams"][id$="loc-button"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Click on "+" to add the value</p>
+      </>
+    ),
+  },
+  {
+    target: 'div[id*="netParamsconnParams"][id*="synMech"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Select "exc" for Synaptic mechanism</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsconnParams"][id*="probability"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Enter 0.1 in Probability of connection</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsconnParams"][id*="weight"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Enter 0.005 in Weight of synaptic connection</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsconnParams"][id*="delay"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Enter 5 in Connection delay</p>
+      </>
+    ),
+  },
+  //
+  // PRE SYNPTIC CELLS CONDITIONS
+  //
+  {
+    target: '#preCondsConnTab > span',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Click on PRE-SYNAPTIC CELLS CONDITIONS</p>
+      </>
+    ),
+  },
+  {
+    target: 'div[id*="netParamsconnParams"][id*="preCondspop"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Select E for the Population</p>
+      </>
+    )
+  },
+  //
+  // POST SYNPTIC CELLS CONDITIONS
+  //
+  {
+    target: '#postCondsConnTab > span',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Click on POST-SYNAPTIC CELLS CONDITIONS</p>
+      </>
+    ),
+  },
+  {
+    target: 'div[id*="netParamsconnParams"][id*="postCondspop"]',
+    title: 'Connectivity Rules Creation',
+    content: (
+      <>
+        <p>Select E for the Population</p>
+      </>
+    )
+  }
+  , {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: 'Network Creation',
+    content: (
+      <>
+        <p>Click on "CREATE NETWORK" (or "UPDATE NETWORK")</p>
+      </>
+    ),
+  }
+  , {
+    target: 'img[src*="d2NetPlot.svg"]',
+    title: 'Plot Display',
+    content: (
+      <>
+        <p>Generate the 2D Net Plot</p>
+      </>
+    ),
+  }
+  , {
+    target: 'div [class*="SwitchPageButton"] .MuiButton-root',
+    title: 'Model Modification',
+    content: (
+      <>
+        <p>Now we can see our connectivity</p>
+        <p>Click "BACK TO EDIT" when you are ready to continue</p>
+      </>
+    ),
+  },
+  {
+    target: 'img[src*="stimSourceParams.svg"]',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Open the Stimulation Sources panel</p>
+      </>
+    ),
+  },
+  {
+    target: '#newStimulationSourceButton',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Click on + above Source</p>
+      </>
+    ),
+  },
+  //
+  // Stimulation input rules
+  //
+  {
+    target: 'div.MuiCardContent-root div.MuiInputBase-formControl > input:not([id])',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Type "IClamp1" in The name of the stimulation source</p>
+      </>
+    ),
+  },
+  {
+    target: '#stimSourceSelect',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Set "IClamp" as the Point process used as stimulator</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id^="netParamsstimSourceParams"][id$="del"]',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Set Current clamp delay to 20</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id^="netParamsstimSourceParams"][id$="dur"]',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Set Current clamp duration to 5</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id^="netParamsstimSourceParams"][id$="amp"]',
+    title: 'Stimulation Sources Creation',
+    content: (
+      <>
+        <p>Set Current clamp amplitude to 0.1 </p>
+      </>
+    ),
+  },
+  //
+  // Simulation targets
+  //
+  {
+    target: 'img[src$="stimTargetParams.svg"]',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Open the on Stimulation Targets</p>
+      </>
+    ),
+  },
+  {
+    target: '#newStimulationTargetButton',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Click on + above Target</p>
+      </>
+    )
+  },
+  {
+    target: 'div.layoutVerticalFitInner div.MuiInputBase-formControl > input:not([id])',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Type “IClamp1-&gt;cell0” in The name of the stimulation target </p>
+      </>
+    ),
+  },
+  {
+    target: 'div[id*="netParamsstimTargetParams"][id*="source"]',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Set Stimulation source to IClamp1</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsstimTargetParams"][id*="sec"]',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Type “dend” in Target section</p>
+      </>
+    ),
+  },
+  {
+    target: 'input[id*="netParamsstimTargetParams"][id*="loc"]',
+    title: 'Stimulation Targets Creation',
+    content: (
+      <>
+        <p>Enter 1 in Target location</p>
+      </>
+    ),
+  },
+  //
+  // Conditions tab
+  //
+  {
+    target: '#stimTargetCondsTab',
+    title: 'Conditions Setup',
+    content: (
+      <>
+        <p>Click on CONDITIONS</p>
+      </>
+    )
+  },
+  {
+    target: 'input[id*="netParamsstimTargetParams"][id*="condscellList"]',
+    title: 'Conditions Setup',
+    content: (
+      <>
+        <p>Enter 0 as new Target cell global indices</p>
+      </>
+    )
+  },
+  {
+    target: 'button[id*="netParamsstimTargetParams"][id*="condscellList-button"]',
+    title: 'Conditions Setup',
+    content: (
+      <>
+        <p>Click the "+" to add the new target cell global indice</p>
+      </>
+    )
+  },
+  //
+  // Configuration panel
+  //
+  {
+    target: 'img[src*="simConfig.svg"]',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Open the configuration panel</p>
+      </>
+    ),
+  },
+  // Simulation configuration
+  {
+    target: '#simConfigduration',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Change the Duration to 200</p>
+      </>
+    )
+  },
+  {
+    target: '#simConfigdt',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Change the Time Step to 0.1</p>
+      </>
+    ),
+  },
+  {
+    target: '#configRecord',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Click on RECORD</p>
+      </>
+    ),
+  },
+  {
+    target: '#simConfigrecordCells',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Enter 0 as new Cells to record traces from</p>
+      </>
+    )
+  },
+  {
+    target: '#simConfigrecordCells-button',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Click the "+" to add the value</p>
+      </>
+    )
+  },
+  {
+    target: '#simConfigrecordTraces',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Type "{"V_dend: {sec: dend, loc: 1.0, var: v}"}"</p>
+      </>
+    )
+  },
+  {
+    target: '#simConfigrecordTraces-button',
+    title: 'Simulation Configuration',
+    content: (
+      <>
+        <p>Click the "+" to add the expression</p>
+      </>
+    )
+  },
+  //
+  // Plot Settings
+  //
+  {
+    target: 'img[src$="analysis.svg"]',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>We want to overlay the voltage traces from soma and dend</p>
+        <p>Go to Plot Settings</p>
+      </>
+    ),
+  }
+  , {
+    target: 'div.MuiAccordionSummary-root div.breadcrumb button.MuiButtonBase-root.MuiFab-root.MuiFab-sizeSmall.MuiFab-primary:not([id])',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Click the "+" to create a new plot</p>
+      </>
+    ),
+  }
+  , {
+    target: 'li[value="iplotTraces"]',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Select Traces Plot</p>
+      </>
+    ),
+  }
+  , {
+    target: 'div.MuiPaper-elevation0 div.MuiBox-root div.MuiFormControl-root input.MuiFilledInput-input:not([id])',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Click on "Cells to include"</p>
+      </>
+    ),
+    waitFor: 'click',
+    collectionIndex: 1
+  },
+  {
+    target: 'li[value="gids"]',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Hover on "gids" then select "cell 0"</p>
+      </>
+    ),
+    waitFor: 'fieldEdition'
+  },
+  {
+    target: 'div.MuiPaper-elevation0 div.MuiBox-root div.MuiFormControl-root input.MuiFilledInput-input:not([id])',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Click again on "Cells to include" to validate the selection</p>
+        <p>Click then on "Next" to continue the tutorial</p>
+      </>
+    ),
+    // waitFor: 'click',
+    collectionIndex: 1
+  },
+  {
+    target: '#simConfiganalysisiplotTracesoverlay',
+    title: 'Plot Settings',
+    content: (
+      <>
+        <p>Check the box next to overlay data</p>
+      </>
+    )
+  },
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: 'Updating',
+    content: (
+      <>
+        <p>Click on UPDATE NETWORK</p>
+      </>
+    ),
+  },
+  //
+  // run simulation
+  //
+  {
+    target: '.MuiGrid-item .MuiButton-root:nth-last-child(2)',
+    title: 'Simulation',
+    content: (
+      <>
+        <p>Click SIMULATE</p>
+        <p>Alternatively, in the menu bar, click Model and then Simulate network</p>
+        <p>Explore the analysis plots</p>
+      </>
+    ),
+  },
+  //
+  // plots
+  //
+  {
+    target: 'img[src*="rasterPlot"]',
+    title: 'Observe the different plots',
+    content: (
+      <>
+        <p>Open the Raster plot panel</p>
+      </>
+    ),
+  },
+  {
+    target: 'img[src$="tracesPlot.svg"]',
+    title: 'Observe the different plots',
+    content: (
+      <>
+        <p>Open the Cell traces panel to see the voltages</p>
+      </>
+    ),
+  },
+  {
+    target: 'img[src*="spikePlot"]',
+    title: 'Observe the different plots',
+    content: (
+      <>
+        <p>Open the Spike histogram panel</p>
+      </>
+    ),
+  },
+  {
+    target: 'img[src$="connectionPlot.svg"]',
+    title: 'Observe the different plots',
+    content: (
+      <>
+        <p>Open the Connectivity panel</p>
+      </>
+    ),
+  },
+  //
+  // Clear the GUI
+  //
+  {
+    target: '#File',
+    title: 'Clear the kernel',
+    content: (
+      <>
+        <p>In the menu bar, select "File"</p>
+      </>
+    )
+  },
+  {
+    target: '#New',
+    title: 'Clear the kernel',
+    content: (
+      <>
+        <p>Then click on "New"</p>
+        <p>This is necessary to clear the kernel when changing models</p>
+      </>
+    )
+  },
+  {
+    target: '#appBarPerformActionButton',
+    title: 'Clear the kernel',
+    content: (
+      <p>Finally, click on "CREATE" to clear the kernel</p>
+    )
+  }
+]
+export default tutorial_steps;
\ No newline at end of file
diff --git a/webapp/redux/reducers/tutorial.js b/webapp/redux/reducers/tutorial.js
new file mode 100644
index 00000000..5be613a6
--- /dev/null
+++ b/webapp/redux/reducers/tutorial.js
@@ -0,0 +1,33 @@
+// import action types
+import tutorial_steps from './data/tutorial_steps';
+import { START_TUTORIAL, STOP_TUTORIAL, INCREMENT_TUTORIAL_STEP, RUN_CONTROLLED_STEP, VALIDATE_TUTORIAL_STEP, CHECK_BUBBLE_RENDER } from '../actions/tutorials';
+
+// Default state for general
+export const TUTORIAL_DEFAULT_STATE = {
+  tourRunning: false,
+  requestedTourStep: 0,
+  lastCheckRender: 0,
+  tourStep: 0,
+  steps: tutorial_steps,
+  renderedSteps: []
+};
+
+// reducer
+export default (state = TUTORIAL_DEFAULT_STATE, action) => {
+  switch (action.type) {
+    case START_TUTORIAL:
+      return {...state, tourRunning: true, requestedTourStep: 1, steps: action.payload }
+    case STOP_TUTORIAL:
+      return {...state, tourRunning: false }
+    case INCREMENT_TUTORIAL_STEP:
+      return {...state, requestedTourStep: state.tourStep + 1 }
+    case RUN_CONTROLLED_STEP:
+      return {...state, tourRunning: true, tourStep: action.payload }
+    case VALIDATE_TUTORIAL_STEP:
+      return {...state, tourStep: action.payload.tourStep }
+    case CHECK_BUBBLE_RENDER:
+      return {...state, lastCheckRender: action.payload.epoch }
+    default:
+      return state
+  }
+}
\ No newline at end of file
diff --git a/webapp/yarn.lock b/webapp/yarn.lock
index 648bf190..173f7c33 100644
--- a/webapp/yarn.lock
+++ b/webapp/yarn.lock
@@ -1222,14 +1222,12 @@
     prop-types "^15.7.2"
     react-is "^16.8.0 || ^17.0.0"
 
-"@metacell/geppetto-meta-client@1.1.0":
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-client/-/geppetto-meta-client-1.1.0.tgz#fa9bc018a47a53dd6f29de07a0a207bc144047b3"
-  integrity sha512-d6AeRcaUeeiDE7Vk3EGHEJ25M/7LS3FCa7Wa0i7W+HggvCrXWV/bzmmvf7Xac07NICsl3BKX6OY15jrciWdzZA==
+"@metacell/geppetto-meta-client@1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-client/-/geppetto-meta-client-1.2.0.tgz#7053bbdc51981eef311eadd68ea959de8ee8a003"
+  integrity sha512-C6PyOOB1PMS5XQB/KKCyMxGDhLE59RJYIfxmPguWElMzm16kS83mDBs5Ysoblq927zauTQopSwY8NIJ8MHG8Fw==
   dependencies:
     "@material-ui/core" "^4.1.3"
-    "@metacell/geppetto-meta-core" "1.1.0"
-    "@metacell/geppetto-meta-ui" "1.1.0"
     pako "^1.0.3"
     react "^17.0.2"
     react-redux "^7.2.3"
@@ -1237,15 +1235,15 @@
     redux "^4.1.0"
     url-join "^4.0.0"
 
-"@metacell/geppetto-meta-core@1.1.0":
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-core/-/geppetto-meta-core-1.1.0.tgz#2c32dc8c1fae0336670a78f0ed0fccbdbd4b4565"
-  integrity sha512-rWspI9eGObTZ4S9+BXsPQNt0QPakMF00/kahp9zhccrajsbnRYGmdRjNWqcV1aQ6su8AR/bkQ5FgEmx9Q/h7dw==
+"@metacell/geppetto-meta-core@1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-core/-/geppetto-meta-core-1.2.0.tgz#52f84f4dec2035e0a2803f44a03043040c2e4e03"
+  integrity sha512-kY8bdXzVqnGnw1kVdPHNlm5jZl9axDKppHZcHGKUtcFFgWaGslNl8PwGxU0cFh+Hr/Lpk0f5tSj/0N40AW7LTg==
 
-"@metacell/geppetto-meta-ui@1.1.0":
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-ui/-/geppetto-meta-ui-1.1.0.tgz#c4e84bd21efbc44238f37ce690e2715774e7a302"
-  integrity sha512-ZfUD9SHQjRkiZDYrlfsgQpEAApv3QwP3C06z7JeCpDyrv2YaNQdLe92w2AjiXEQmrfLK59iNYRjNniGTrkLQ+A==
+"@metacell/geppetto-meta-ui@1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@metacell/geppetto-meta-ui/-/geppetto-meta-ui-1.2.0.tgz#cb685fe6a710fd2d36c8e5b198cdb19f74f19223"
+  integrity sha512-Qkp6iMWJCOozK4gcvVUxwAqDgJ9hXjJD5060bCEloyQmYI4e8cdGpb3u5sD8Ey6J5ERrWhbo5klUEPeMH4885A==
 
 "@nosferatu500/react-dnd-scrollzone@^1.0.14":
   version "1.0.14"
@@ -2408,6 +2406,11 @@ caniuse-lite@^1.0.30001449:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001467.tgz#1afc9c16ed61f50dd87139da87ca43a3e0051c77"
   integrity sha512-cEdN/5e+RPikvl9AHm4uuLXxeCNq8rFsQ+lPHTfe/OtypP3WwnVVbjn+6uBV7PaFL6xUFzTh+sSCOz1rKhcO+Q==
 
+casperjs@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/casperjs/-/casperjs-1.1.4.tgz#eb01f4ed85ac520a8f4d932b4daa74d3e77bc746"
+  integrity sha512-0THjMp6Ku+tev5FydCqqILI0wz0/1Fbp6YHCvMbeu0z4OlrgXUS6+jba2ia38uNgKwJGMXGuazEvQQ3OwXLI0g==
+
 chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 77885b15..7fe77af5 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -58,6 +58,28 @@ jobs:
           npm run Experiment_Manager_test
       env:
           CI: true
+  Control_Panel-test:
+    # The type of runner that the job will run on
+    runs-on: ubuntu-20.04
+    container: lironavon/docker-puppeteer-container:14.16.0
+    env:
+      CI: true
+    steps:
+    - uses: actions/checkout@v1
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+          node-version: ${{ matrix.node-version }}
+          cache-dependency-path: frontend/e2e/tests/package-lock.json
+    - name: Control Panel test using Tut#2
+      run: |
+          cd tests/frontend/e2e
+          #install dependencies
+          npm ci
+          # run Control Panel test
+          npm run Control_Panel_test
+      env:
+          CI: true
   Tutorial_1-SmokeTest:
     # The type of runner that the job will run on
     runs-on: ubuntu-20.04
diff --git a/tests/frontend/e2e/package.json b/tests/frontend/e2e/package.json
index 48be38c3..e357607b 100644
--- a/tests/frontend/e2e/package.json
+++ b/tests/frontend/e2e/package.json
@@ -13,6 +13,7 @@
     "Tutorial_3B_test":"jest --verbose Tut#3b_smoke ",
     "Tutorial_3C_test":"jest --verbose Tut#3c_smoke ",
     "Tutorial_4_test":"jest --verbose Tut#4_smoke ",
+    "Control_Panel_test": "jest --verbose ControlPanel ",
     "lint": "eslint --fix --ext .js,.jsx ."
   },
   "dependencies": {
diff --git a/tests/frontend/e2e/tests/ControlPanel.test.js b/tests/frontend/e2e/tests/ControlPanel.test.js
new file mode 100644
index 00000000..d0b4d081
--- /dev/null
+++ b/tests/frontend/e2e/tests/ControlPanel.test.js
@@ -0,0 +1,313 @@
+//IMPORTS:
+import 'expect-puppeteer';
+import { click } from './utils';
+import { toMatchImageSnapshot } from 'jest-image-snapshot'
+expect.extend({ toMatchImageSnapshot })
+const path = require('path');
+var scriptName = path.basename(__filename, '.js');
+import * as selectors from './selectors'
+
+
+//PAGE INFO:
+const baseURL = process.env.url || 'https://stage.netpyne.metacell.us/'
+const PAGE_WAIT = 3000;
+const TIMEOUT = 60000;
+
+//SNAPSHOT:
+const SNAPSHOT_OPTIONS = {
+    customSnapshotsDir: `./tests/snapshots/Tut#2_smoke.test/`,
+    comparisonMethod: 'ssim',
+    failureThresholdType: 'percent',
+    failureThreshold: 0.25
+};
+
+let r = (Math.random() + 1).toString(36).substring(2);
+
+//USERS:
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
+
+//TESTS:
+
+jest.setTimeout(300000);
+
+
+
+describe('Test for the Control Panel - color picker', () => {
+
+    beforeAll(async () => {
+        await page.goto(baseURL);
+        await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
+        await page.waitForSelector(selectors.USERNAME_SELECTOR)
+        await expect(page)
+            .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
+
+        await page.waitForSelector(selectors.PASSWORD_SELECTOR)
+        await expect(page)
+            .toFill(selectors.PASSWORD_SELECTOR, PASSWORD, { timeout: TIMEOUT });
+
+        await page.click(selectors.LOGIN_BUTTON_SELECTOR)
+
+        await page.waitForFunction(() => {
+            let el = document.querySelector('#loading-spinner');
+            return el == null || el.clientHeight === 0;
+        }, { timeout: TIMEOUT });
+    });
+
+    it('Open new page', async () => {
+
+        console.log('Opening a new NetPyNE page')
+
+        await page.on("dialog", dialog =>
+            dialog.accept());
+
+        await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+        await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.click(selectors.FILE_TAB_SELECTOR)
+        await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.click(selectors.NEW_FILE_SELECTOR)
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.waitForSelector(selectors.CONFIRM_NEW_PAGE_SELECTOR)
+        await page.click(selectors.CONFIRM_NEW_PAGE_SELECTOR)
+        await page.waitForTimeout(PAGE_WAIT * 2)
+
+        await page.waitForFunction(() => {
+            let el = document.querySelector('#loading-spinner');
+            return el == null || el.clientHeight === 0;
+        }, { timeout: TIMEOUT });
+
+        await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
+
+        console.log('Page opened successfully')
+
+    })
+
+    it('Load Tutorial#2', async () => {
+
+        await page.waitForTimeout(PAGE_WAIT * 2)
+        await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+
+        console.log('Loading Tutorial #2')
+
+        await page.click(selectors.TUTORIAL_2_SELECTOR, { timeout: TIMEOUT })
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.waitForSelector(selectors.PYR_2_CELL_SELECTOR)
+        await page.waitForSelector(selectors.INT_CELL_SELECTOR)
+        await page.waitForTimeout(PAGE_WAIT)
+
+        console.log('Tutorial #2 loaded successfully')
+
+    })
+
+
+    it('Create network', async () => {
+
+        await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
+        await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+        await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
+        await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
+        console.log('Create network')
+
+        await page.waitForSelector(selectors.DISABLED_RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 3 })
+
+        console.log('Network created successfully')
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        console.log('... taking snapshot ...');
+        await page.waitForTimeout(PAGE_WAIT);
+        expect(await page.screenshot())
+            .toMatchImageSnapshot({
+                ...SNAPSHOT_OPTIONS,
+                customSnapshotIdentifier: 'Tutorial#2 Network'
+            });
+    })
+
+    it('Open Color Picker Menu', async () => {
+
+        console.log('Opening Control Panel')
+
+        await page.waitForSelector(selectors.CONTROL_PANEL_TAB_SELECTOR)
+        await page.click(selectors.CONTROL_PANEL_TAB_SELECTOR)
+        await page.waitForSelector(selectors.NETWORKS_IN_CONTROL_PANEL_SELECTOR)
+
+        const network_items = (await page.$$(selectors.NETWORK_ITEMS_CONTROL_PANEL_SELECTOR)).length;
+        await expect(network_items).toEqual(3)
+
+        console.log('Control Panel displayed successfully')
+
+    })
+
+    it('Randomize Main Level network color', async () => {
+
+        console.log('Randomize Main Level network color')
+
+        await page.waitForTimeout(PAGE_WAIT * 3)
+        await page.waitForSelector(selectors.CONTROL_PANEL_TABLE_SELECTOR)
+
+        const primary_level_colors = await page.$$eval(selectors.COLOR_RECT_SELECTOR, primary_level_colors => {
+            return primary_level_colors.map(primary_level_color => primary_level_color.outerHTML);
+        });
+
+        expect(primary_level_colors[0]).toContain('fill="#FF7F99"')
+        expect(primary_level_colors[0]).toEqual(primary_level_colors[1])
+        expect(primary_level_colors[1]).toEqual(primary_level_colors[2])
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const rows = await page.$$(selectors.CONTROL_PANEL_NETWORK_ROWS_SELECTOR)
+        for (var i = 0; i < rows.length; i++) {
+            await rows[0].hover()
+        }
+
+        const buttons = await page.$$(selectors.COLOR_CONTROL_BUTTONS_SELECTOR)
+
+        for (var i = 0; i < buttons.length; i++) {
+            await buttons[1].click()
+        }
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const rndm_primary_level_colors = await page.$$eval(selectors.COLOR_RECT_SELECTOR, rndm_primary_level_colors => {
+            return rndm_primary_level_colors.map(rndm_primary_level_color => rndm_primary_level_color.outerHTML);
+        });
+
+        expect(rndm_primary_level_colors[0]).toContain('fill="#989898"')
+        expect(rndm_primary_level_colors[2]).not.toEqual(rndm_primary_level_colors[1])
+
+        console.log('Main Network color randomized successfully')
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+    })
+
+    it('Randomize Sub level E network color', async () => {
+
+        console.log('Randomize Sub Level E network color')
+
+        const rows = await page.$$(selectors.CONTROL_PANEL_NETWORK_ROWS_SELECTOR)
+        for (var i = 0; i < rows.length; i++) {
+            await rows[1].click()
+            await rows[1].hover()
+        }
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const second_level_colors = await page.$$eval(selectors.COLOR_RECT_SELECTOR, second_level_colors => {
+            return second_level_colors.map(second_level_color => second_level_color.outerHTML);
+        });
+
+
+        expect(second_level_colors[1]).toEqual(second_level_colors[2])
+        expect(second_level_colors[2]).toEqual(second_level_colors[3])
+
+
+        const buttons = await page.$$(selectors.COLOR_CONTROL_BUTTONS_SELECTOR)
+
+        for (var i = 0; i < buttons.length; i++) {
+            await buttons[2].click()
+        }
+
+        await page.waitForTimeout(PAGE_WAIT * 2)
+
+        const second_level_colors_after_rndm = await page.$$eval(selectors.COLOR_RECT_SELECTOR, second_level_colors_after_rndm => {
+            return second_level_colors_after_rndm.map(second_level_color_after_rndm => second_level_color_after_rndm.outerHTML);
+        });
+
+        expect(second_level_colors_after_rndm[1]).toContain('fill="#989898"')
+        expect(second_level_colors_after_rndm[2]).not.toEqual(second_level_colors_after_rndm[3])
+        expect(second_level_colors_after_rndm[2]).not.toEqual(second_level_colors_after_rndm[1])
+
+        console.log('E Network color randomized successfully')
+
+        await page.waitForTimeout(PAGE_WAIT * 3)
+
+    })
+
+
+    it('Pick a color for the sublevel I netowrk', async () => {
+
+        console.log('Selecting a color for the I network')
+
+        const rows = await page.$$(selectors.CONTROL_PANEL_NETWORK_ROWS_SELECTOR)
+        for (var i = 0; i < rows.length; i++) {
+            await rows[1].click()
+        }
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const rows_ = await page.$$(selectors.CONTROL_PANEL_NETWORK_ROWS_SELECTOR)
+
+        for (var i = 0; i < rows_.length; i++) {
+            await rows_[2].click()
+        }
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const network_colors = await page.$$eval(selectors.COLOR_RECT_SELECTOR, network_colors => {
+            return network_colors.map(network_color => network_color.outerHTML);
+        });
+
+        expect(network_colors[3]).toEqual(network_colors[4])
+        expect(network_colors[3]).toEqual(network_colors[2])
+
+        await page.waitForTimeout(PAGE_WAIT * 3)
+
+        const buttons = await page.$$(selectors.COLOR_CONTROL_BUTTONS_SELECTOR)
+
+        for (var i = 0; i < buttons.length; i++) {
+            await buttons[4].click()
+        }
+
+        await page.waitForTimeout(PAGE_WAIT)
+
+        const list_bounds = await page.$(selectors.NETWORKS_IN_CONTROL_PANEL_SELECTOR);
+        const rect = await page.evaluate((list_bounds) => {
+            const { top, left, bottom, right } = list_bounds.getBoundingClientRect();
+            return { top, left, bottom, right };
+        }, list_bounds);
+
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.mouse.click(Math.round(rect.right) - 40, Math.round(rect.bottom) + 40)
+        await page.waitForTimeout(PAGE_WAIT * 2)
+
+        const rows_after_colouring_I = await page.$$(selectors.CONTROL_PANEL_NETWORK_ROWS_SELECTOR)
+        for (var i = 0; i < rows_after_colouring_I.length; i++) {
+            await rows_after_colouring_I[2].click()
+        }
+
+        const network_colors_after_colouring_I = await page.$$eval(selectors.COLOR_RECT_SELECTOR, network_colors_after_colouring_I => {
+            return network_colors_after_colouring_I.map(network_color_after_colouring_I => network_color_after_colouring_I.outerHTML);
+        });
+        await page.waitForTimeout(PAGE_WAIT)
+
+        expect(network_colors_after_colouring_I[2]).toEqual(network_colors_after_colouring_I[3])
+        expect(network_colors_after_colouring_I[2]).toEqual(network_colors_after_colouring_I[4])
+
+        console.log('I network color selected successfully')
+
+    })
+
+    it('Filter results from the Control panel', async () => {
+
+        await page.waitForTimeout(PAGE_WAIT)
+        console.log('Filtering results')
+
+        await expect(page).toFill(selectors.CONTROL_PANEL_FILTER_SELECTOR, 'E')
+
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.waitForSelector(selectors.NETWORKS_IN_CONTROL_PANEL_SELECTOR)
+
+        const network_items = (await page.$$(selectors.NETWORK_ITEMS_CONTROL_PANEL_SELECTOR)).length;
+        await expect(network_items).toEqual(3)
+
+        console.log('Results filtered successfully')
+
+    })
+
+
+});
\ No newline at end of file
diff --git a/tests/frontend/e2e/tests/EEG_and_Dipole_Tut#1.test.js b/tests/frontend/e2e/tests/EEG_and_Dipole_Tut#1.test.js
index 0f98e8a3..f206accb 100644
--- a/tests/frontend/e2e/tests/EEG_and_Dipole_Tut#1.test.js
+++ b/tests/frontend/e2e/tests/EEG_and_Dipole_Tut#1.test.js
@@ -26,9 +26,11 @@ const SNAPSHOT_OPTIONS = {
 
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
+
 //USERS:
-const USERNAME = 'EEGDipole_TestUser_'
-const PASSWORD = 'password'
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 
 //TESTS:
@@ -65,15 +67,16 @@ describe('EEG and Dipole Plot Test using Tutorial#1', () => {
         await page.on("dialog", dialog =>
             dialog.accept());
 
-        await page.waitForSelector('#File', { timeout: PAGE_WAIT * 20 })
-        await page.waitForTimeout(PAGE_WAIT * 6)
-        await page.click('#File')
-        await page.waitForSelector('#New', { timeout: PAGE_WAIT * 10 })
+        await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+        await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.click(selectors.FILE_TAB_SELECTOR)
+        await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
         await page.waitForTimeout(PAGE_WAIT)
-        await page.click('#New')
+        await page.click(selectors.NEW_FILE_SELECTOR)
         await page.waitForTimeout(PAGE_WAIT)
-        await page.waitForSelector('#appBarPerformActionButton')
-        await page.click('#appBarPerformActionButton')
+        await page.waitForSelector(selectors.CONFIRM_NEW_PAGE_SELECTOR)
+        await page.click(selectors.CONFIRM_NEW_PAGE_SELECTOR)
         await page.waitForTimeout(PAGE_WAIT * 2)
 
         await page.waitForFunction(() => {
@@ -81,9 +84,10 @@ describe('EEG and Dipole Plot Test using Tutorial#1', () => {
             return el == null || el.clientHeight === 0;
         }, { timeout: TIMEOUT });
 
-
         await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
+        console.log('Page opened successfully')
+
     })
 
 
diff --git a/tests/frontend/e2e/tests/ExperimentManager_Tut#1.test.js b/tests/frontend/e2e/tests/ExperimentManager_Tut#1.test.js
index da986b5d..4c37eb44 100644
--- a/tests/frontend/e2e/tests/ExperimentManager_Tut#1.test.js
+++ b/tests/frontend/e2e/tests/ExperimentManager_Tut#1.test.js
@@ -25,9 +25,10 @@ const SNAPSHOT_OPTIONS = {
 };
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
 
 //USERS:
-const USERNAME = 'Test_User_Experiment_Manager_'
+const USERNAME = `TestUser${r}`
 const PASSWORD = 'testpassword'
 
 
@@ -65,15 +66,16 @@ describe('Experiment Manager test using Tut#1', () => {
         await page.on("dialog", dialog =>
             dialog.accept());
 
-        await page.waitForSelector('#File', { timeout: PAGE_WAIT * 20 })
-        await page.waitForTimeout(PAGE_WAIT * 6)
-        await page.click('#File')
-        await page.waitForSelector('#New', { timeout: PAGE_WAIT * 10 })
+        await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+        await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
         await page.waitForTimeout(PAGE_WAIT)
-        await page.click('#New')
+        await page.click(selectors.FILE_TAB_SELECTOR)
+        await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
         await page.waitForTimeout(PAGE_WAIT)
-        await page.waitForSelector('#appBarPerformActionButton')
-        await page.click('#appBarPerformActionButton')
+        await page.click(selectors.NEW_FILE_SELECTOR)
+        await page.waitForTimeout(PAGE_WAIT)
+        await page.waitForSelector(selectors.CONFIRM_NEW_PAGE_SELECTOR)
+        await page.click(selectors.CONFIRM_NEW_PAGE_SELECTOR)
         await page.waitForTimeout(PAGE_WAIT * 2)
 
         await page.waitForFunction(() => {
@@ -81,10 +83,10 @@ describe('Experiment Manager test using Tut#1', () => {
             return el == null || el.clientHeight === 0;
         }, { timeout: TIMEOUT });
 
-        
-
         await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
+        console.log('Page opened successfully')
+
     })
 
     it('Load Tutorial#1', async () => {
diff --git a/tests/frontend/e2e/tests/Tut#1_smoke.test.js b/tests/frontend/e2e/tests/Tut#1_smoke.test.js
index 53d1adb9..bca24976 100644
--- a/tests/frontend/e2e/tests/Tut#1_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#1_smoke.test.js
@@ -16,18 +16,18 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
 
 //USERS:
-const USERNAME = 'test_user_tut_1'
-const PASSWORD =  'testpassword'
-
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 //TESTS:
 
@@ -42,7 +42,7 @@ describe('Tutorial #1 for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -61,12 +61,13 @@ describe('Tutorial #1 for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 20 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -75,21 +76,21 @@ describe('Tutorial #1 for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #1')
 
@@ -105,9 +106,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
     await click(page, selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
     await click(page, selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+
     console.log('Create network')
-   
+
     await page.waitForTimeout(PAGE_WAIT)
 
     console.log('... taking snapshot ...');
@@ -118,7 +119,7 @@ describe('Tutorial #1 for Smoke Testing', () => {
         customSnapshotIdentifier: 'Tutorial#1 Network'
       });
 
-    await click(page,selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await click(page, selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await click(page, selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
     console.log('Simulate network')
 
@@ -130,10 +131,10 @@ describe('Tutorial #1 for Smoke Testing', () => {
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
     await click(page, selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -147,9 +148,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
+
     await click(page, selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 2);
 
@@ -162,9 +163,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
+
     await click(page, selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -177,9 +178,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
+
     await click(page, selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -192,9 +193,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
+
     await click(page, selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -207,9 +208,9 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('Granger Plot', async () => {
-    
+
     await click(page, selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Granger Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -222,19 +223,19 @@ describe('Tutorial #1 for Smoke Testing', () => {
   });
 
   it('Rate Spectogram Plot', async () => {
-    
+
     await click(page, selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
     await click(page, selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
     await click(page, selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/Tut#2_smoke.test.js b/tests/frontend/e2e/tests/Tut#2_smoke.test.js
index c1f1a9f2..71c47c25 100644
--- a/tests/frontend/e2e/tests/Tut#2_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#2_smoke.test.js
@@ -15,17 +15,17 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
+let r = (Math.random() + 1).toString(36).substring(2);
 
 //USERS:
-const USERNAME = 'test_user_Tut_2'
-const PASSWORD =  'testpassword'
-
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 //TESTS:
 
@@ -40,7 +40,7 @@ describe('Tutorial #2 for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -59,12 +59,13 @@ describe('Tutorial #2 for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 30 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -73,27 +74,27 @@ describe('Tutorial #2 for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #2')
 
     await page.waitForTimeout(PAGE_WAIT)
 
-    await page.click( selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     await page.click(selectors.TUTORIAL_2_SELECTOR, { timeout: TIMEOUT })
     await page.waitForSelector(selectors.PYR_2_CELL_SELECTOR)
@@ -101,13 +102,13 @@ describe('Tutorial #2 for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT)
 
     await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
-    await page.click( selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Create network')
-   
-    await page.waitForTimeout(PAGE_WAIT*3)
+
+    await page.waitForTimeout(PAGE_WAIT * 3)
 
     await page.waitForSelector(selectors.THREE_D_REP_SELECTOR)
 
@@ -119,23 +120,23 @@ describe('Tutorial #2 for Smoke Testing', () => {
         customSnapshotIdentifier: 'Tutorial#2 Network'
       });
 
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
-    await page.click( selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
     console.log('Simulate network')
 
     await page.waitForSelector(selectors.SIMULATION_PAGE_SELECTOR, { timeout: TIMEOUT * 2 });
 
-    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT*3})
+    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 3 })
 
 
   });
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -149,9 +150,9 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
-    await page.click( selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -164,9 +165,9 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
-    await page.click( selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -179,9 +180,9 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
-    await page.click( selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -194,9 +195,9 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
-    await page.click( selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -209,9 +210,9 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('Granger Plot', async () => {
-    
-    await page.click( selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Granger Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -224,19 +225,19 @@ describe('Tutorial #2 for Smoke Testing', () => {
   });
 
   it('Rate Spectogram Plot', async () => {
-    
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/Tut#3a_smoke.test.js b/tests/frontend/e2e/tests/Tut#3a_smoke.test.js
index 21787527..1b2aa6e0 100644
--- a/tests/frontend/e2e/tests/Tut#3a_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#3a_smoke.test.js
@@ -15,16 +15,17 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
+let r = (Math.random() + 1).toString(36).substring(2);
 
 //USERS:
-const USERNAME = 'test_user_tut_3a'
-const PASSWORD =  'testpassword'
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 
 //TESTS:
@@ -40,7 +41,7 @@ describe('Tutorial #3a for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -59,12 +60,13 @@ describe('Tutorial #3a for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 20 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -73,41 +75,41 @@ describe('Tutorial #3a for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #3a')
 
     await page.waitForTimeout(PAGE_WAIT)
 
-    await page.click( selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
-    await page.click( selectors.TUTORIAL_3A_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIAL_3A_SELECTOR, { timeout: TIMEOUT })
     await page.waitForSelector(selectors.E_CELL_TYPE_SELECTOR)
     await page.waitForSelector(selectors.I_CELL_TYPE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
 
     await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
-    await page.click( selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Create network')
-   
-    await page.waitForTimeout(PAGE_WAIT*3)
+
+    await page.waitForTimeout(PAGE_WAIT * 3)
 
     await page.waitForSelector(selectors.THREE_D_REP_SELECTOR)
 
@@ -119,25 +121,25 @@ describe('Tutorial #3a for Smoke Testing', () => {
         customSnapshotIdentifier: 'Tutorial#3a Network'
       });
 
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
-    await page.click( selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
 
-    
     console.log('Simulate network')
 
     await page.waitForSelector(selectors.SIMULATION_PAGE_SELECTOR, { timeout: TIMEOUT * 2 });
 
-    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT*10})
+    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 10 })
 
 
   });
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -151,9 +153,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
-    await page.click( selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -166,9 +168,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
-    await page.click( selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -181,9 +183,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
-    await page.click( selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -196,9 +198,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
-    await page.click( selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -211,9 +213,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('LFP Time Series Plot', async () => {
-    
-    await page.click( selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Time Series Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -226,9 +228,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('LFP PSD Plot', async () => {
-    
-    await page.click( selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP PSD Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -241,9 +243,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('LFP Spectrogram Plot', async () => {
-    
-    await page.click( selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Spectrogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 5);
 
@@ -256,9 +258,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('Granger Plot', async () => {
-    
-    await page.click( selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Granger Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -271,9 +273,9 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('RxD concentration plot', async () => {
-    
-    await page.click( selectors.RXD_CONCENTRATION_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RXD_CONCENTRATION_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View RxD concentration plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -286,19 +288,19 @@ describe('Tutorial #3a for Smoke Testing', () => {
   });
 
   it('Rate Spectogram Plot', async () => {
-    
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/Tut#3b_smoke.test.js b/tests/frontend/e2e/tests/Tut#3b_smoke.test.js
index d3643e80..f9995e32 100644
--- a/tests/frontend/e2e/tests/Tut#3b_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#3b_smoke.test.js
@@ -15,16 +15,18 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
+
 //USERS:
-const USERNAME = 'test_user_tut_3b'
-const PASSWORD =  'testpassword'
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 
 //TESTS:
@@ -40,7 +42,7 @@ describe('Tutorial #3b for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -59,12 +61,13 @@ describe('Tutorial #3b for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 20 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -73,41 +76,41 @@ describe('Tutorial #3b for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #3b')
 
     await page.waitForTimeout(PAGE_WAIT)
 
-    await page.click( selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
-    await page.click( selectors.TUTORIAL_3B_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIAL_3B_SELECTOR, { timeout: TIMEOUT })
     await page.waitForSelector(selectors.E_CELL_TYPE_SELECTOR)
     await page.waitForSelector(selectors.I_CELL_TYPE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
 
     await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
-    await page.click( selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Create network')
-   
-    await page.waitForTimeout(PAGE_WAIT*3)
+
+    await page.waitForTimeout(PAGE_WAIT * 3)
 
     await page.waitForSelector(selectors.THREE_D_REP_SELECTOR)
 
@@ -118,24 +121,24 @@ describe('Tutorial #3b for Smoke Testing', () => {
         ...SNAPSHOT_OPTIONS,
         customSnapshotIdentifier: 'Tutorial#3b Network'
       });
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
-    await page.click( selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
 
     console.log('Simulate network')
 
     await page.waitForSelector(selectors.SIMULATION_PAGE_SELECTOR, { timeout: TIMEOUT * 2 });
 
-    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT*3})
+    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 3 })
 
 
   });
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -149,9 +152,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
-    await page.click( selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -164,9 +167,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
-    await page.click( selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -179,9 +182,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
-    await page.click( selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -194,9 +197,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
-    await page.click( selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -209,9 +212,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('LFP Time Series Plot', async () => {
-    
-    await page.click( selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Time Series Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -224,9 +227,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('LFP PSD Plot', async () => {
-    
-    await page.click( selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP PSD Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 2);
 
@@ -239,9 +242,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('LFP Spectrogram Plot', async () => {
-    
-    await page.click( selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Spectrogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 5);
 
@@ -254,9 +257,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('Granger Plot', async () => {
-    
-    await page.click( selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Granger Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 2);
 
@@ -269,9 +272,9 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('RxD concentration plot', async () => {
-    
-    await page.click( selectors.RXD_CONCENTRATION_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RXD_CONCENTRATION_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View RxD concentration plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -284,19 +287,19 @@ describe('Tutorial #3b for Smoke Testing', () => {
   });
 
   it('Rate Spectogram Plot', async () => {
-    
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/Tut#3c_smoke.test.js b/tests/frontend/e2e/tests/Tut#3c_smoke.test.js
index 51f1935b..24270041 100644
--- a/tests/frontend/e2e/tests/Tut#3c_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#3c_smoke.test.js
@@ -16,16 +16,18 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
+
 //USERS:
-const USERNAME = 'test_user_tut_3c'
-const PASSWORD =  'testpassword'
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 
 //TESTS:
@@ -41,7 +43,7 @@ describe('Tutorial #3c for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -60,12 +62,13 @@ describe('Tutorial #3c for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 20 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -74,41 +77,41 @@ describe('Tutorial #3c for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #3c')
 
     await page.waitForTimeout(PAGE_WAIT)
 
-    await page.click( selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
-    await page.click( selectors.TUTORIAL_3C_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIAL_3C_SELECTOR, { timeout: TIMEOUT })
     await page.waitForSelector(selectors.E_CELL_TYPE_SELECTOR)
     await page.waitForSelector(selectors.I_CELL_TYPE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
 
     await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
-    await page.click( selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Create network')
-   
-    await page.waitForTimeout(PAGE_WAIT*3)
+
+    await page.waitForTimeout(PAGE_WAIT * 3)
 
     await page.waitForSelector(selectors.THREE_D_REP_SELECTOR)
 
@@ -124,23 +127,23 @@ describe('Tutorial #3c for Smoke Testing', () => {
     // await page.click( MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForTimeout(PAGE_WAIT);
     //reason why the tests are using the simulate button on the top right
-    await page.click( selectors.SIMULATE_TOP_RIGHT_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.SIMULATE_TOP_RIGHT_BUTTON_SELECTOR, { timeout: TIMEOUT });
     // await page.click( SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
     console.log('Simulate network')
 
     await page.waitForSelector(selectors.SIMULATION_PAGE_SELECTOR, { timeout: TIMEOUT * 2 });
 
-    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT*3})
+    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 3 })
 
 
   });
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -154,9 +157,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
-    await page.click( selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -169,9 +172,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
-    await page.click( selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -184,9 +187,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
-    await page.click( selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -199,9 +202,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
-    await page.click( selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -214,9 +217,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('LFP Time Series Plot', async () => {
-    
-    await page.click( selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_TS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Time Series Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -229,9 +232,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('LFP PSD Plot', async () => {
-    
-    await page.click( selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_PSD_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP PSD Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -244,9 +247,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('LFP Spectrogram Plot', async () => {
-    
-    await page.click( selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.LFP_SPECTOGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View LFP Spectrogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -259,9 +262,9 @@ describe('Tutorial #3c for Smoke Testing', () => {
   });
 
   it('Granger Plot', async () => {
-    
-    await page.click( selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.GRANGER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Granger Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -275,19 +278,19 @@ describe('Tutorial #3c for Smoke Testing', () => {
 
 
   it('Rate Spectogram Plot', async () => {
-    
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/Tut#4_smoke.test.js b/tests/frontend/e2e/tests/Tut#4_smoke.test.js
index 43142523..a42ba4fd 100644
--- a/tests/frontend/e2e/tests/Tut#4_smoke.test.js
+++ b/tests/frontend/e2e/tests/Tut#4_smoke.test.js
@@ -15,16 +15,18 @@ const TIMEOUT = 60000;
 
 //SNAPSHOT:
 const SNAPSHOT_OPTIONS = {
-  customSnapshotsDir:  `./tests/snapshots/${scriptName}`,
+  customSnapshotsDir: `./tests/snapshots/${scriptName}`,
   comparisonMethod: 'ssim',
   failureThresholdType: 'percent',
   failureThreshold: 0.5
 };
 
 
+let r = (Math.random() + 1).toString(36).substring(2);
+
 //USERS:
-const USERNAME = 'test_user_tut_4'
-const PASSWORD =  'testpassword'
+const USERNAME = `TestUser${r}`
+const PASSWORD = 'testpassword'
 
 
 //TESTS:
@@ -40,7 +42,7 @@ describe('Tutorial #4 for Smoke Testing', () => {
     await page.waitForSelector(selectors.LOGIN_PAGE_SELECTOR);
     await page.waitForSelector(selectors.USERNAME_SELECTOR)
     await expect(page)
-      .toFill(selectors.USERNAME_SELECTOR,USERNAME, { timeout: TIMEOUT });
+      .toFill(selectors.USERNAME_SELECTOR, USERNAME, { timeout: TIMEOUT });
 
     await page.waitForSelector(selectors.PASSWORD_SELECTOR)
     await expect(page)
@@ -59,12 +61,13 @@ describe('Tutorial #4 for Smoke Testing', () => {
     console.log('Opening a new NetPyNE page')
 
     await page.on("dialog", dialog =>
-        dialog.accept());
+      dialog.accept());
 
-    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 20 })
-    await page.waitForTimeout(PAGE_WAIT * 7)
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 6, visible: true })
+    await page.waitForSelector(selectors.FILE_TAB_SELECTOR, { timeout: PAGE_WAIT * 3 })
+    await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.FILE_TAB_SELECTOR)
-    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 10 })
+    await page.waitForSelector(selectors.NEW_FILE_SELECTOR, { timeout: PAGE_WAIT * 3 })
     await page.waitForTimeout(PAGE_WAIT)
     await page.click(selectors.NEW_FILE_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
@@ -73,40 +76,40 @@ describe('Tutorial #4 for Smoke Testing', () => {
     await page.waitForTimeout(PAGE_WAIT * 2)
 
     await page.waitForFunction(() => {
-        let el = document.querySelector('#loading-spinner');
-        return el == null || el.clientHeight === 0;
+      let el = document.querySelector('#loading-spinner');
+      return el == null || el.clientHeight === 0;
     }, { timeout: TIMEOUT });
 
-    
-
     await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT * 10 })
 
-})
+    console.log('Page opened successfully')
+
+  })
 
 
   it('Create and Simulate network', async () => {
 
     await page.waitForTimeout(PAGE_WAIT * 2)
-    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT})
+    await page.waitForSelector(selectors.SELECT_CELL_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     console.log('Tutorial #4')
 
     await page.waitForTimeout(PAGE_WAIT)
 
-    await page.click( selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
+    await page.click(selectors.TUTORIALS_BUTTON_SELECTOR, { timeout: TIMEOUT })
 
     await page.click(selectors.TUTORIAL_4_SELECTOR, { timeout: TIMEOUT })
     await page.waitForSelector(selectors.PYR_2_CELL_SELECTOR)
     await page.waitForTimeout(PAGE_WAIT)
 
     await page.waitForSelector(selectors.MODEL_BUTTON_SELECTOR)
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
     await page.waitForSelector(selectors.CREATE_NETWORK_SELECTOR)
-    await page.click( selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.CREATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Create network')
-   
-    await page.waitForTimeout(PAGE_WAIT*3)
+
+    await page.waitForTimeout(PAGE_WAIT * 3)
 
     await page.waitForSelector(selectors.THREE_D_REP_SELECTOR)
 
@@ -118,24 +121,24 @@ describe('Tutorial #4 for Smoke Testing', () => {
         customSnapshotIdentifier: 'Tutorial#4 Network'
       });
 
-    await page.click( selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
-    await page.click( selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
-    
+    await page.click(selectors.MODEL_BUTTON_SELECTOR, { timeout: TIMEOUT });
+    await page.click(selectors.SIMULATE_NETWORK_SELECTOR, { timeout: TIMEOUT });
+
     console.log('Simulate network')
 
     await page.waitForSelector(selectors.SIMULATION_PAGE_SELECTOR, { timeout: TIMEOUT * 2 });
 
-    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT*3})
+    await page.waitForSelector(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT * 3 })
 
 
   });
 
 
   it('Connections Plot', async () => {
-    
+
     await page.waitForTimeout(PAGE_WAIT * 2);
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Connections Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -149,9 +152,9 @@ describe('Tutorial #4 for Smoke Testing', () => {
   });
 
   it('2D Net Plot', async () => {
-    
-    await page.click( selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.TWO_D_NET_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View 2D Net Plot ...')
     await page.waitForTimeout(PAGE_WAIT * 3);
 
@@ -164,9 +167,9 @@ describe('Tutorial #4 for Smoke Testing', () => {
   });
 
   it('Cell Traces Plot', async () => {
-    
-    await page.click( selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.CELL_TRACES_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Cell Traces Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -179,9 +182,9 @@ describe('Tutorial #4 for Smoke Testing', () => {
   });
 
   it('Raster Plot', async () => {
-    
-    await page.click( selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RASTER_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Raster Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -194,9 +197,9 @@ describe('Tutorial #4 for Smoke Testing', () => {
   });
 
   it('Spike Hist Plot', async () => {
-    
-    await page.click( selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.SPIKE_HIST_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
     console.log('View Spike Hist Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
 
@@ -210,19 +213,19 @@ describe('Tutorial #4 for Smoke Testing', () => {
 
 
   it('Rate Spectogram Plot', async () => {
-    
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     await page.waitForTimeout(PAGE_WAIT);
 
-    await page.click( selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
-    await page.waitForSelector(selectors.CANVAS_SELECTOR,{ timeout: TIMEOUT })
+    await page.click(selectors.RATE_SPECTROGRAM_PLOT_SELECTOR, { timeout: TIMEOUT })
+    await page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
 
     console.log('View Rate Spectogram Plot ...')
     await page.waitForTimeout(PAGE_WAIT);
diff --git a/tests/frontend/e2e/tests/selectors.js b/tests/frontend/e2e/tests/selectors.js
index c2b80a3f..e1cce5c7 100644
--- a/tests/frontend/e2e/tests/selectors.js
+++ b/tests/frontend/e2e/tests/selectors.js
@@ -69,4 +69,12 @@ export const EDIT_EXPERIMENT_BACK_SELECTOR = '.editExperimentBack > svg'
 export const INDIVIDUAL_EXPERIMENT_ROW_SELECTOR = 'tr[class="MuiTableRow-root"]'
 export const FILE_TAB_SELECTOR = '#File'
 export const NEW_FILE_SELECTOR = '#New'
-export const CONFIRM_NEW_PAGE_SELECTOR = '#appBarPerformActionButton'
\ No newline at end of file
+export const CONFIRM_NEW_PAGE_SELECTOR = '#appBarPerformActionButton'
+export const CONTROL_PANEL_TAB_SELECTOR = 'div[title="Control Panel"]'
+export const NETWORKS_IN_CONTROL_PANEL_SELECTOR = 'ul[role="tree"]'
+export const NETWORK_ITEMS_CONTROL_PANEL_SELECTOR = 'li[role="treeitem"]'
+export const COLOR_CONTROL_BUTTONS_SELECTOR = 'button[class="MuiButtonBase-root MuiIconButton-root"]'
+export const COLOR_RECT_SELECTOR = 'rect[rx="5"]'
+export const CONTROL_PANEL_NETWORK_ROWS_SELECTOR = 'div[class = "MuiTypography-root MuiTreeItem-label MuiTypography-body1"]'
+export const CONTROL_PANEL_TABLE_SELECTOR = 'div[class="MuiGrid-root MuiGrid-container MuiGrid-justify-content-xs-space-between"]'
+export const CONTROL_PANEL_FILTER_SELECTOR = 'input[class="MuiInputBase-input MuiOutlinedInput-input"]'
\ No newline at end of file