def test_delete_file_local_branch(driver: selenium.webdriver, *args, **kwargs):
    """
    Test that a file created on the master branch, deleted in a local branch, and then merged back into the
    master branch does not appear in the master branch.
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    logging.info(f"Navigating to Input Data")
    driver.get(
        f"{os.environ['GIGANTUM_HOST']}/projects/{username}/{project_title}/inputData"
    )
    time.sleep(2)
    logging.info(
        f"Adding a file to the master branch of project {project_title}")
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.drag_drop_file_in_drop_zone()
    time.sleep(4)
    branch_elts = testutils.BranchElements(driver)
    branch_elts.create_local_branch("test-branch")
    time.sleep(8)
    logging.info(f"Deleting file in test-branch")
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.check_file_check_box.find().click()
    file_browser_elts.delete_file_button.wait().click()
    file_browser_elts.confirm_delete_file_button.wait().click()
    time.sleep(2)
    branch_elts.switch_to_alternate_branch()
    branch_elts.merge_alternate_branch()
    logging.info(
        f"Checking that file deleted in test-branch does not appear in master branch"
    )

    assert file_browser_elts.file_browser_empty.find(), \
        "Expected sample-upload.txt to not appear in master branch"
def test_linked_published_dataset_then_publish(driver: selenium.webdriver, *args, **kwargs):
    """
    1. create and publish a dataset
    2. create a project and link the dataset
    3. publish the project
    """
    # create a dataset
    # dataset set up
    testutils.log_in(driver)
    testutils.GuideElements(driver).remove_guide()

    ds_elements = testutils.DatasetElements(driver)
    # create and publish datset
    dataset_title_local = ds_elements.create_dataset(testutils.unique_dataset_name())
    ds_elements.publish_dataset()

    driver.get(os.environ['GIGANTUM_HOST'])
    r = testutils.prep_py3_minimal_base(driver, skip_login=True)
    username, project_name = r.username, r.project_name

    filebrowser_elts = testutils.ProjectFileBrowserElements(driver)
    filebrowser_elts.link_dataset('a', 'b')

    time.sleep(4)

    pp = testutils.PublishProjectElements(driver)
    pp.publish_project()
    time.sleep(4)
def test_create_local_branch(driver: selenium.webdriver, *args, **kwargs):
    """
    Test the creation of a local branch.
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    branch_elts = testutils.BranchElements(driver)
    branch_elts.create_local_branch("test-branch")
    time.sleep(8)
    logging.info(
        "Checking that you are on the new branch and that the new branch is local only"
    )

    assert branch_elts.upper_left_branch_name.find().text == "test-branch", \
        "Expected to be on test-branch, upper left"
    assert branch_elts.upper_left_branch_local_only.find(
    ), "Expected test-branch to be local only, upper left"

    branch_elts.manage_branches_button.wait().click()
    time.sleep(2)

    assert branch_elts.manage_branches_branch_name.find().text == "test-branch", \
        "Expected to be on test-branch, manage branches"
    assert branch_elts.manage_branches_local_only.find(
    ), "Expected test-branch to be local only, manage branches"
def test_project_file_browser(driver: selenium.webdriver, *args, **kwargs):
    """
    Test that a file can be dragged and dropped into code, input data,
    and output data in a project.

    Args:
        driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    logging.info(f"Navigating to Code for project: {project_title}")
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.code_tab.wait().click()
    time.sleep(2)
    logging.info(f"Dragging and dropping file into code for project: {project_title}")
    file_browser_elts.drag_drop_file_in_drop_zone()

    assert file_browser_elts.file_information.find().text == 'sample-upload.txt', \
        "Expected sample-upload.txt to be the first file in Code"

    logging.info(f"Navigating to Input Data for project: {project_title}")
    file_browser_elts.input_data_tab.wait().click()
    time.sleep(2)
    logging.info(f"Dragging and dropping file into Input Data for project: {project_title}")
    file_browser_elts.drag_drop_file_in_drop_zone()

    assert file_browser_elts.file_information.find().text == 'sample-upload.txt', \
        "Expected sample-upload.txt to be the first file in Input Data"
示例#5
0
def test_invalid_custom_docker(driver: selenium.webdriver, *args, **kwargs):
    """
    Test invalid custom Docker instructions.

    Args:
        driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name
    # add an invalid custom docker instruction
    logging.info("Adding invalid custom Docker")
    environment = testutils.EnvironmentElements(driver)
    environment.environment_tab_button.click()
    time.sleep(1)
    driver.execute_script("window.scrollBy(0, 600);")
    environment.custom_docker_edit_button.click()
    time.sleep(1)
    environment.custom_docker_text_input.send_keys("RUN /bin/false")
    time.sleep(1)
    driver.execute_script("window.scrollBy(0, 300);")
    environment.custom_docker_save_button.click()
    # wait until container status is stopped
    wait = selenium.webdriver.support.ui.WebDriverWait(driver, 200)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Rebuild")))
    time.sleep(2)
    # assert container status is stopped and 'Successfully tagged' is in footer
    envelts = testutils.elements.EnvironmentElements(driver)
    assert driver.find_element_by_css_selector(".flex>.Rebuild").is_displayed(), "Expected rebuild container status"
    assert "Project failed to build" in driver.find_element_by_css_selector(".Footer__message-title").text, \
        "Expected 'Project failed to build' in footer"
示例#6
0
def test_valid_custom_docker(driver: selenium.webdriver, *args, **kwargs):
    """
    Test valid custom Docker instructions.

    Args:
        driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name
    wait = selenium.webdriver.support.ui.WebDriverWait(driver, 200)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))
    logging.info("Adding valid custom Docker")
    environment = testutils.EnvironmentElements(driver)
    environment.environment_tab_button.click()
    driver.execute_script("window.scrollBy(0, 600);")
    environment.custom_docker_edit_button.click()
    environment.custom_docker_text_input.send_keys("RUN cd /tmp && "
                                                   "git clone https://github.com/gigantum/confhttpproxy && "
                                                   "cd /tmp/confhttpproxy && pip install -e.")
    time.sleep(1)
    driver.execute_script("window.scrollBy(0, 300);")
    environment.custom_docker_save_button.click()
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))
    # assert container status is stopped and 'Successfully tagged' is in footer
    time.sleep(15)
    assert driver.find_element_by_css_selector(".flex>.Stopped").is_displayed(), "Expected stopped container"
示例#7
0
def test_delete_project(driver: selenium.webdriver, *args, **kwargs):
    """
        Test that deleting a project in Gigantum deletes it from the file system.

        Args:
            driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name

    # Check that project path exists on file system
    logging.info("Checking that the project exists in the file system")
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username,
                                username, 'labbooks', project_name)
    assert os.path.exists(project_path), \
        f"Project {project_name} should exist at {project_path}"
    logging.info("Finding project Docker image")
    dc = docker.from_env()
    project_img = []
    for img in dc.images.list():
        for t in img.tags:
            if 'gmlb-' in t and project_name in t:
                logging.info(f"Found Docker image {t} for {project_name}")
                project_img.append(img)
    assert len(project_img) == 1, f"Must be one docker tag for {project_name}"

    # Navigate to the "Delete Project" button and click it
    logging.info("Navigating to 'Delete Project' and delete the project")
    driver.find_element_by_css_selector(".ActionsMenu__btn").click()
    time.sleep(3)
    driver.find_element_by_css_selector(".ActionsMenu__item--delete").click()
    time.sleep(3)
    driver.find_element_by_css_selector("#deleteInput").send_keys(
        project_name.lstrip())
    driver.find_element_by_css_selector(".DeleteLabbook .ButtonLoader").click()
    time.sleep(5)

    # Check all post conditions for delete:
    # 1. Does not exist in filesystem, and
    # 2. Docker image no longer exists
    logging.info(
        "Checking that project path and project Docker image no longer exist")
    assert not os.path.exists(
        project_path), f"Project at {project_path} not deleted"
    project_img = []
    for img in dc.images.list():
        for t in img.tags:
            if 'gmlb-' in t and project_name in t:
                logging.error(
                    f'Docker tag {t} still exists for deleted project {project_name}'
                )
                project_img.append(img)
    assert len(project_img) == 0, \
        f"Docker image for {project_path}: {project_img[0]} still exists"
示例#8
0
def test_pip_packages(driver: selenium.webdriver, *args, **kwargs):
    """
    Test that pip packages install successfully.

    Args:
        driver
    """
    # Create project
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    # Add pip packages
    env_elts = testutils.EnvironmentElements(driver)
    env_elts.add_pip_packages("pandas", "numpy", "matplotlib")
    # Get environment package versions
    logging.info("Extracting package versions from environment")
    environment_package_versions = env_elts.get_all_versions()

    #Open JupyterLab and create Jupyter notebook
    project_control = testutils.ProjectControlElements(driver)
    project_control.container_status_stopped.wait(120)
    project_control.launch_devtool('JupyterLab')
    jupyterlab_elts = testutils.JupyterLabElements(driver)
    # TODO DC This seems unnecessary given the wait below
    time.sleep(5)
    jupyterlab_elts.jupyter_notebook_button.wait().click()
    time.sleep(5)
    logging.info(
        "Running script to import packages and print package versions")
    package_script = "import pandas\nimport numpy\nimport matplotlib\n" \
                     "print(pandas.__version__,numpy.__version__,matplotlib.__version__)"
    actions = ActionChains(driver)
    actions.move_to_element(jupyterlab_elts.code_input.find()) \
        .click(jupyterlab_elts.code_input.find()) \
        .send_keys(package_script) \
        .key_down(Keys.SHIFT).send_keys(Keys.ENTER).key_up(Keys.SHIFT).key_up(Keys.CONTROL) \
        .perform()

    time.sleep(3)

    # Get JupyterLab package versions
    logging.info("Extracting package versions from JupyterLab")
    jupyterlab_package_output = jupyterlab_elts.code_output.find().text.split(
        " ")
    jupyterlab_package_versions = jupyterlab_package_output
    logging.info(
        f"Environment package version {environment_package_versions} \n "
        f"JupyterLab package version {jupyterlab_package_versions}")

    assert environment_package_versions == jupyterlab_package_versions,\
        "Environment and JupyterLab package versions do not match"
示例#9
0
def test_valid_custom_docker(driver: selenium.webdriver, *args, **kwargs):
    """
    Test valid custom Docker instructions.

    Args:
        driver
    """
    # Create project
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name
    env_elts = testutils.EnvironmentElements(driver)
    env_elts.add_custom_docker_instructions(
        "RUN cd /tmp && "
        "git clone https://github.com/gigantum/confhttpproxy && "
        "cd /tmp/confhttpproxy && pip install -e.")
    time.sleep(3)
    proj_elements = testutils.ProjectControlElements(driver)
    proj_elements.container_status_stopped.wait(60)

    container_status = proj_elements.container_status_stopped.is_displayed()
    assert container_status, "Expected stopped container status"
def test_linked_published_dataset_then_publish(driver: selenium.webdriver,
                                               *args, **kwargs):
    """
    Test that a dataset can be created, published,
    linked to a project and published with the project.
    """
    testutils.log_in(driver)
    testutils.GuideElements(driver).remove_guide()
    ds_elts = testutils.DatasetElements(driver)
    # Create and publish dataset
    ds_elts.create_dataset(testutils.unique_dataset_name())
    ds_elts.publish_dataset()
    # Create a project, link dataset, and publish project
    driver.get(os.environ['GIGANTUM_HOST'])
    r = testutils.prep_py3_minimal_base(driver, skip_login=True)
    username, project_title = r.username, r.project_name
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.link_dataset('a', 'b')
    time.sleep(4)
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.publish_private_project(project_title)
    time.sleep(4)
示例#11
0
def test_invalid_custom_docker(driver: selenium.webdriver, *args, **kwargs):
    """
    Test invalid custom Docker instructions.

    Args:
        driver
    """
    # Create project
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name
    env_elts = testutils.EnvironmentElements(driver)
    env_elts.add_custom_docker_instructions("RUN /bin/false")
    time.sleep(3)
    wait = WebDriverWait(driver, 90)
    wait.until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Rebuild")))

    container_status = driver.find_element_by_css_selector(
        ".flex>.Rebuild").is_displayed()
    assert container_status, "Expected rebuild container status"

    footer_message_text = driver.find_element_by_css_selector(
        ".Footer__message-title").text
    assert "Project failed to build" in footer_message_text, "Expected 'Project failed to build' in footer message"
def prep_merge_conflict(driver: selenium.webdriver, *args, **kwargs):
    """
    Prepare a merge conflict in a cloud project.
    """
    # Owner creates a project, publishes it, adds a collaborator, and logs out
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.publish_private_project(project_title)
    collaborator = cloud_project_elts.add_collaborator_with_permissions(
        project_title, permissions="admin")
    side_bar_elts = testutils.SideBarElements(driver)
    side_bar_elts.do_logout(username)

    # Collaborator logs in and imports the cloud project
    logging.info(f"Logging in as {collaborator}")
    testutils.log_in(driver, user_index=1)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    logging.info(f"Navigating to {collaborator}'s Cloud tab")
    driver.get(f"{os.environ['GIGANTUM_HOST']}/projects/cloud")
    time.sleep(2)
    cloud_project_elts.first_cloud_project.wait(30)
    cloud_project_elts.import_first_cloud_project_button.find().click()
    project_control = testutils.ProjectControlElements(driver)
    project_control.container_status_stopped.wait(30)

    # Collaborator adds a file, syncs, and logs out
    logging.info(f"Navigating to {collaborator}'s Input Data tab")
    driver.get(
        f'{os.environ["GIGANTUM_HOST"]}/projects/{username}/{project_title}/inputData'
    )
    time.sleep(2)
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.drag_drop_file_in_drop_zone(file_content="Collaborator")
    cloud_project_elts.sync_cloud_project(project_title)
    side_bar_elts.do_logout(collaborator)

    # Owner logs in and navigates to Input Data
    logging.info(f"Logging in as {username}")
    testutils.log_in(driver)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    logging.info(f"Navigating to {username}'s Input Data tab")
    driver.get(
        f'{os.environ["GIGANTUM_HOST"]}/projects/{username}/{project_title}/inputData'
    )
    time.sleep(2)
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.drag_drop_file_in_drop_zone(file_content="Owner")
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.sync_cloud_project(project_title)
    return username, project_title, collaborator
def test_publish_collaborator(driver: selenium.webdriver, *args, ** kwargs):
    """
    Test that a project in Gigantum can be published, shared with a collaborator, and imported by the collaborator.
    """
    # Owner creates and publishes project
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.publish_private_project(project_title)
    # Owner adds collaborator and logs out
    collaborator = cloud_project_elts.add_collaborator_with_permissions(project_title)
    side_bar_elts = testutils.SideBarElements(driver)
    side_bar_elts.do_logout(username)

    # Collaborator logs in, imports cloud project, and logs out
    logging.info(f"Logging in as {collaborator}")
    testutils.log_in(driver, user_index=1)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    logging.info(f"Navigating to {collaborator}'s Cloud tab")
    driver.get(f"{os.environ['GIGANTUM_HOST']}/projects/cloud")
    cloud_project_elts.first_cloud_project.wait()
    first_cloud_project = cloud_project_elts.first_cloud_project.find().text

    assert project_title == first_cloud_project, \
        f"Expected {project_title} to be the first cloud project in {collaborator}'s Cloud tab, " \
        f"but instead got {first_cloud_project}"

    cloud_project_elts.import_first_cloud_project_button.find().click()
    project_control = testutils.ProjectControlElements(driver)
    project_control.container_status_stopped.wait(30)
    shared_project_title = cloud_project_elts.project_overview_project_title.find().text

    assert project_title in shared_project_title, \
        f"After import, expected project {project_title} to open to project overview page"

    side_bar_elts.do_logout(collaborator)

    # Owner logs in and deletes cloud project
    logging.info(f"Logging in as {username}")
    testutils.log_in(driver)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    cloud_project_elts.delete_cloud_project(project_title)

    # Assert cloud project does not exist remotely (via GraphQL)
    remote_projects = graphql_helpers.list_remote_projects()

    assert (username, project_title) not in remote_projects

    # Assert that cloud project does not have remote Git repo (use Git 2.20+)
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                                'labbooks', project_title)
    git_get_remote_command_2 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    del_cloud_project_stderr = git_get_remote_command_2.stderr.readline().decode('utf-8').strip()

    assert "fatal" in del_cloud_project_stderr, f"Expected to not see a remote set for project {project_title}, " \
                                                f"but got {del_cloud_project_stderr}"
def test_publish_sync_delete_project(driver: selenium.webdriver, *args, **kwargs):
    """
    Test that a project in Gigantum can be published, synced, and deleted.
    """
    # Create and publish project
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.publish_private_project(project_title)
    logging.info(f"Navigating to {username}'s Cloud tab")
    driver.get(f"{os.environ['GIGANTUM_HOST']}/projects/cloud")

    logging.info(f"Checking if a remote is set for project {project_title}")
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                                'labbooks', project_title)
    git_get_remote_command_1 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    cloud_project_stdout = git_get_remote_command_1.stdout.readline().decode('utf-8').strip()

    assert "https://" in cloud_project_stdout, f"Expected to see a remote set for project {project_title}, " \
                                               f"but got {cloud_project_stdout}"

    logging.info(f"Checking if project {project_title} appears in {username}'s Cloud tab")
    cloud_project_elts.first_cloud_project.wait()
    first_cloud_project = cloud_project_elts.first_cloud_project.find().text
    logging.info(f"Found first cloud project {first_cloud_project}")

    assert project_title == first_cloud_project, \
        f"Expected {project_title} to be the first cloud project in {username}'s Cloud tab, " \
        f"but instead got {first_cloud_project}"

    # Add a file and sync cloud project
    driver.get(f'{os.environ["GIGANTUM_HOST"]}/projects/{username}/{project_title}/inputData')
    time.sleep(6)
    file_browser_elts = testutils.FileBrowserElements(driver)
    file_browser_elts.drag_drop_file_in_drop_zone()
    cloud_project_elts.sync_cloud_project(project_title)

    assert "Sync complete" in cloud_project_elts.sync_cloud_project_message.find().text, \
        "Expected 'Sync complete' in footer"

    # Delete cloud project
    cloud_project_elts.delete_cloud_project(project_title)

    # Assert project does not exist remotely (via GraphQL)
    remote_projects = graphql_helpers.list_remote_projects()

    assert (username, project_title) not in remote_projects

    # Assert that project does not have remote Git repo (use Git 2.20+)
    git_get_remote_command_2 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    del_cloud_project_stderr = git_get_remote_command_2.stderr.readline().decode('utf-8').strip()

    assert "fatal" in del_cloud_project_stderr, f"Expected to not see a remote set for project {project_title}, " \
                                                f"but got {del_cloud_project_stderr}"

    # Assert project does not exist in cloud tab
    first_cloud_project = cloud_project_elts.first_cloud_project.find().text

    assert project_title != first_cloud_project, \
        f"Expected {project_title} to not be the first cloud project in {username}'s Cloud tab, " \
        f"but instead got {first_cloud_project}"
示例#15
0
def test_pip_packages(driver: selenium.webdriver, *args, **kwargs):
    """
    Test that pip packages install successfully.

    Args:
        driver
    """
    return
    # project set up
    r = testutils.prep_py3_minimal_base(driver)
    username, project_name = r.username, r.project_name

    testutils.add_pip_package(driver)
    time.sleep(5)
    # wait until container status is stopped
    wait = selenium.webdriver.support.ui.WebDriverWait(driver, 30)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex > .Stopped")))
    assert testutils.is_container_stopped(driver), "Expected stopped container"

    # check package versions from environment
    package_info = driver.find_element_by_css_selector(".PackageDependencies__table").text
    # parse the string to a list and extract information of package names and versions
    package_list = package_info.split("\n")[1::3]
    package_parse = [x.split(" ") for x in package_list]
    # convert to dictionary with package names as key and versions as values
    package_environment = {x[0]: x[1] for x in package_parse if len(x) > 1}
    logging.info("Getting package versions from environment")

    # check pip packages version from jupyterlab
    driver.find_element_by_css_selector(".Btn--text").click()
    time.sleep(10)
    window_handles = driver.window_handles
    driver.switch_to.window(window_handles[1])
    logging.info("Switching to jupyter lab")
    # wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "[title = code]")))
    time.sleep(3)
    driver.find_element_by_css_selector(".jp-LauncherCard-label").click()
    logging.info("Launching jupyter notebook")
    # wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".CodeMirror-line")))
    time.sleep(3)
    el = driver.find_element_by_css_selector(".CodeMirror-line")
    actions = ActionChains(driver)
    logging.info("Importing packages")
    # implement script the import packages and print the versions.
    package_script = "import pandas\nimport numpy\nimport matplotlib\n" \
                     "print('pandas', pandas.__version__," \
                     " 'numpy',numpy.__version__," \
                     " 'matplotlib', matplotlib.__version__)"
    actions.move_to_element(el).click(el).send_keys(package_script).perform()
    driver.find_element_by_css_selector(".jp-RunIcon").click()
    # extract the output of package versions as string and parse to a list.
    logging.info("Extracting package versions from jupyter")
    # wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".jp-mod-active")))
    time.sleep(3)
    package_output = driver.find_element_by_css_selector(".jp-OutputArea-output > pre").text.split(" ")
    # convert to dictionary with package names as key and versions as values.
    package_jupyter = dict(zip(package_output[::2], package_output[1::2]))
    logging.info("Getting package versions from jupyterlab")
    # check if package versions from environment and from jupyter notebook are same.
    logging.info(f"package_environment {package_environment} \n package_jupyter {package_jupyter}")
    assert package_environment == package_jupyter, "Package versions do not match"


    '''
def test_publish_collaborator(driver: selenium.webdriver, *args, ** kwargs):
    """
        Test that a project in Gigantum can be published, shared with a collaborator, and imported by the collaborator.

        Args:
            driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name

    # Publish project, then wait until its rebuilt
    logging.info(f"Publishing private project {project_title}")
    publish_elts = testutils.PublishProjectElements(driver)
    publish_elts.publish_project_button.wait().click()
    time.sleep(1)
    publish_elts.publish_confirm_button.wait().click()
    time.sleep(5)
    wait = WebDriverWait(driver, 15)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))
    time.sleep(5)

    # Add collaborator
    logging.info(f"Adding a collaborator to private project {project_title}")
    publish_elts.collaborators_button.click()
    time.sleep(2)
    username2 = testutils.load_credentials(user_index=1)[0].rstrip()
    publish_elts.collaborators_input.send_keys(username2)
    publish_elts.add_collaborators_button.click()
    time.sleep(2)
    publish_elts.close_collaborators_button.click()
    testutils.log_out(driver)

    # Collaborator checks that the project is in the cloud tab and that the project imports successfully
    logging.info(f"Logging in as {username2}")
    testutils.log_in(driver, user_index=1)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    publish_elts.cloud_tab.click()
    time.sleep(2)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".RemoteLabbooks__panel-title")))

    # Test that shared cloud project is in cloud tab
    cloud_tab_first_project_title_delete = driver.find_element_by_css_selector(
        ".RemoteLabbooks__panel-title:first-child span span").text
    assert cloud_tab_first_project_title_delete == project_title, \
        f"Expected shared cloud project {project_title} in cloud tab"

    publish_elts.import_first_cloud_project_button.click()
    time.sleep(2)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))

    # Test that after import, the shared project opens to overview page
    shared_project_title = publish_elts.owner_title
    assert project_title in shared_project_title, \
        f"After import, expected shared project {project_title} to open to overview page"

    testutils.log_out(driver)

    # Delete cloud project
    logging.info(f"Logging in as {username}")
    testutils.log_in(driver)
    time.sleep(2)
    try:
        testutils.GuideElements.remove_guide(driver)
    except:
        pass
    time.sleep(2)
    testutils.delete_project_cloud(driver, project_title)

    # Assert project does not exist remotely (Via GraphQL).
    # TODO - Put back in check for the UI in addition to this check.
    remote_projects = graphql.list_remote_projects()
    assert (username, project_title) not in remote_projects

    # Check that the actual Git repo in the project had the remote removed successfully
    # Note! Use Git 2.20+
    logging.info("Testing git remotes to check if set...")
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                                'labbooks', project_title)
    git_get_remote_command_2 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    del_stderr = git_get_remote_command_2.stderr.readline().decode('utf-8').strip()

    assert "fatal" in del_stderr, f"Expected to not see a remote set for {project_title}, but got {del_stderr}"
def test_publish_sync_delete_project(driver: selenium.webdriver, *args, **kwargs):
    """
        Test that a project in Gigantum can be published, synced, and deleted.

        Args:
            driver
    """
    r = testutils.prep_py3_minimal_base(driver)
    username, project_title = r.username, r.project_name
    # Publish project
    logging.info(f"Publishing private project {project_title}")
    publish_elts = testutils.PublishProjectElements(driver)
    publish_elts.publish_project_button.wait().click()
    time.sleep(1)
    publish_elts.publish_confirm_button.wait().click()
    time.sleep(5)
    wait = WebDriverWait(driver, 15)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))
    time.sleep(5)

    # Navigate to cloud tab
    logging.info(f"Navigating to {username}'s' cloud view")
    driver.get(f'{os.environ["GIGANTUM_HOST"]}/projects/cloud')

    sel = 'div[data-selenium-id="RemoteLabbookPanel"]:first-child'
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, sel)))
    time.sleep(2)


    ssel = f'{sel} span'
    cloud_tab_first_project_title_publish = driver.find_element_by_css_selector(ssel).text
    logging.info(f"!!!!! {cloud_tab_first_project_title_publish}")

    assert cloud_tab_first_project_title_publish == project_title, \
        f"Expected {project_title} to be the first project in the cloud tab"


    logging.info("Testing git remotes to check if set...")
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                                'labbooks', project_title)
    git_get_remote_command_1 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    pub_stdout = git_get_remote_command_1.stdout.readline().decode('utf-8').strip()
    assert "https://" in pub_stdout, f"Expected to see a remote set for private project " \
                                     f"{project_title}, but got {pub_stdout}"

    publish_elts.local_tab.click()
    driver.get(f'{os.environ["GIGANTUM_HOST"]}/projects/{username}/{project_title}')
    time.sleep(3)

    # Add file to input data and sync project
    logging.info("Adding a file to the project")
    with open('/tmp/sample-upload.txt', 'w') as example_file:
        example_file.write('Sample Text')
    input_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username, 'labbooks', project_title,
                              'input')
    shutil.copy(example_file.name, input_path)
    logging.info(f"Syncing {project_title}")
    publish_elts.sync_project_button.click()
    time.sleep(5)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".flex>.Stopped")))

    sync_message = driver.find_element_by_css_selector(".Footer__message-item > p").text
    assert "Sync complete" in sync_message, "Expected 'Sync complete' in footer"

    testutils.delete_project_cloud(driver, project_title)

    # Assert project does not exist remotely (Via GraphQL).
    # TODO - Put back in check for the UI in addition to this check.
    remote_projects = graphql.list_remote_projects()
    assert (username, project_title) not in remote_projects

    # Check that the actual Git repo in the project had the remote removed successfully
    # Note! Use Git 2.20+
    git_get_remote_command_2 = Popen(['git', 'remote', 'get-url', 'origin'],
                                     cwd=project_path, stdout=PIPE, stderr=PIPE)
    del_stderr = git_get_remote_command_2.stderr.readline().decode('utf-8').strip()

    assert "fatal" in del_stderr, f"Expected to not see a remote set for {project_title}, but got {del_stderr}"