def test_use_theirs_merge_conflict_project(driver: selenium.webdriver, *args,
                                           **kwargs):
    """
    Test a merge conflict in a cloud project in which the owner resolves it with 'Use Theirs.'
    """
    # Prepare merge conflict
    username, project_title, collaborator = prep_merge_conflict(driver)
    # Owner uploads file, syncs, and resolves the merge conflict with 'Use Theirs'
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.merge_conflict_use_theirs_button.wait(30).click()
    timeout = time.time() + 30
    while cloud_project_elts.sync_cloud_project_message.find(
    ).text != "Sync complete":
        cloud_project_elts.sync_cloud_project_message.wait(3)
        if time.time() > timeout:
            break
    # Check that merge conflict resolves to 'Use Theirs'
    file_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                             'labbooks', project_title, 'input',
                             'sample-upload.txt')
    with open(file_path, "r") as resolve_merge_conflict_file:
        resolve_merge_conflict_file = resolve_merge_conflict_file.read()

    assert resolve_merge_conflict_file == "Collaborator", \
        f"Merge did not resolve to 'Use Theirs' expected to see 'Collaborator' in file, " \
        f"but instead got {resolve_merge_conflict_file}"
def test_abort_merge_conflict_project(driver: selenium.webdriver, *args,
                                      **kwargs):
    """
    Test a merge conflict in a cloud project in which the owner resolves it with 'Abort.'
    """
    # Prepare merge conflict
    username, project_title, collaborator = prep_merge_conflict(driver)
    # Owner uploads file, syncs, and resolves the merge conflict with 'Abort'
    cloud_project_elts = testutils.CloudProjectElements(driver)
    project_path = os.path.join(os.environ['GIGANTUM_HOME'], username,
                                username, 'labbooks', project_title)
    git_get_log_command_1 = Popen(['git', 'log', '--pretty=format%H'],
                                  cwd=project_path,
                                  stdout=PIPE,
                                  stderr=PIPE)
    before_merge_conflict_resolve_stdout = git_get_log_command_1.stdout.readline(
    ).decode('utf-8').strip()
    cloud_project_elts.merge_conflict_abort_button.wait(30).click()
    time.sleep(2)
    # Check that merge conflict resolves to 'Abort'
    git_get_log_command_2 = Popen(['git', 'log', '--pretty=format%H'],
                                  cwd=project_path,
                                  stdout=PIPE,
                                  stderr=PIPE)
    after_merge_conflict_resolve_stdout = git_get_log_command_2.stdout.readline(
    ).decode('utf-8').strip()

    assert before_merge_conflict_resolve_stdout == after_merge_conflict_resolve_stdout, \
        f"Merge did not resolve to 'Abort' expected to see {before_merge_conflict_resolve_stdout}, " \
        f"but instead got {after_merge_conflict_resolve_stdout}"
def test_use_mine_merge_conflict_project(driver: selenium.webdriver, *args,
                                         **kwargs):
    """
    Test a merge conflict in a cloud project in which the owner resolves it with 'Use Mine.'
    """
    # Prepare merge conflict
    username, project_title, collaborator = prep_merge_conflict(driver)
    # Owner resolves the merge conflict with 'Use Mine'
    cloud_project_elts = testutils.CloudProjectElements(driver)
    cloud_project_elts.merge_conflict_use_mine_button.wait(30).click()
    timeout = time.time() + 30

    while timeout > time.time():
        try:
            assert (cloud_project_elts.sync_cloud_project_message.find().text
                    == "Sync complete")
            break
        except AssertionError:
            time.sleep(1)
            logging.warning("Error finding Sync complete notification")

    # Check that merge conflict resolves to 'Use Mine'
    file_path = os.path.join(os.environ['GIGANTUM_HOME'], username, username,
                             'labbooks', project_title, 'input',
                             'sample-upload.txt')
    with open(file_path, "r") as resolve_merge_conflict_file:
        resolve_merge_conflict_file = resolve_merge_conflict_file.read()

    assert resolve_merge_conflict_file == "Owner", \
        f"Merge did not resolve to 'Use Mine' expected to see 'Owner' in file, " \
        f"but instead got {resolve_merge_conflict_file}"
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)
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}"