#!/usr/bin/python3

# checkpoint:
# 1. page navigate and package filter
# 2. selected package sorting
# 3. redo, undo, and commit
# 4. discard all changes

import composerlib
import testlib


@testlib.nondestructive
class TestPackage(composerlib.ComposerCase):

    def testNavigate(self):
        b = self.browser

        self.login_and_go("/composer", superuser=True)
        b.wait_visible("#main")

        # go to edit package page
        b.click("li[data-blueprint=httpd-server] a:contains('Edit packages')")
        with b.wait_timeout(120):
            b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")

        # do navigate with > and < button
        b.click("button[aria-label='Go to next page']")
        b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")
        b.click("button[aria-label='Go to previous page']")
        b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")
        # filter on avaliable components
        b.set_input_text("#cmpsr-blueprint-input-filter", "cockpit-bridge", blur=False)
        b.key_press("\r")
        with b.wait_timeout(120):
            b.wait_text("#cockpit-bridge-input", "cockpit-bridge")
        b.wait_visible(".toolbar-pf-results .label-info > span")
        # click Clear All Filters link
        b.click("span:contains('Clear all filters')")
        b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")
        b.wait_not_present(".toolbar-pf-results .label-info span")
        b.wait_not_present("#cockpit-bridge-input")

        # filter on blueprints component
        # filter by name
        b.set_input_text("#filter-blueprints", "tmux", blur=False)
        b.key_press("\r")
        b.wait_text("ul[data-list=components] li:nth-child(1) #tmux", "tmux")
        b.click(".cmpsr-panel__body--main .toolbar-pf-results button:contains('Clear all filters')")
        b.wait_text("ul[data-list=components] li:nth-child(1) #httpd", "httpd")
        # filter by version
        b.click("#filterFieldTypeMenu")
        b.wait_attr("#filterFieldTypeMenu", "aria-expanded", "true")
        b.click("a:contains('Version')")
        b.wait_in_text("#filterFieldTypeMenu", "Version")
        # input version is dynamic according to different OS release
        version = b.text("li[data-component=tmux] .cc-component__version strong")
        b.set_input_text("#filter-blueprints", version, blur=False)
        b.key_press("\r")
        b.wait_text("ul[data-list=components] li:nth-child(1) #tmux", "tmux")
        b.click(".cmpsr-panel__body--main .toolbar-pf-results .pficon-close")
        b.wait_text("ul[data-list=components] li:nth-child(1) #httpd", "httpd")
        # filter by release
        b.click("#filterFieldTypeMenu")
        b.wait_attr("#filterFieldTypeMenu", "aria-expanded", "true")
        b.click("a:contains('Release')")
        b.wait_in_text("#filterFieldTypeMenu", "Release")
        # input release is dynamic according to different OS release
        release = b.text("li[data-component=tmux] .cc-component__release strong")
        b.set_input_text("#filter-blueprints", release, blur=False)
        b.key_press("\r")
        b.wait_text("ul[data-list=components] li:nth-child(1) .cc-component__release strong",
                    release)
        b.click(".cmpsr-panel__body--main .toolbar-pf-results .pficon-close")
        b.wait_text("ul[data-list=components] li:nth-child(1) #httpd", "httpd")

        # collect code coverage result
        self.check_coverage()

    def testSort(self):
        b = self.browser

        self.login_and_go("/composer", superuser=True)
        b.wait_visible("#main")

        # go to edit package page
        b.click("li[data-blueprint=httpd-server] a:contains('Edit packages')")
        with b.wait_timeout(120):
            b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")

        blueprint_list = [
            "httpd",
            "tmux",
            "vim-enhanced"
        ]
        # sort from Z-A
        b.wait_visible("ul[aria-label='Selected components']")
        b.click(".fa-sort-alpha-asc")
        b.wait_visible(".fa-sort-alpha-desc")
        for i, v in enumerate(sorted(blueprint_list, reverse=True)):
            b.wait_text("ul[aria-label='Selected components'] li:nth-child({}) "
                        "a strong".format(i + 1), v)

        # sort from A-Z
        b.click(".fa-sort-alpha-desc")
        b.wait_visible(".fa-sort-alpha-asc")
        for i, v in enumerate(sorted(blueprint_list)):
            b.wait_text("ul[aria-label='Selected components'] li:nth-child({}) "
                        "a strong".format(i + 1), v)

        # collect code coverage result
        self.check_coverage()

    def testRedoUndoCommit(self):
        b = self.browser

        self.login_and_go("/composer", superuser=True)
        b.wait_visible("#main")

        # go to edit package page
        b.click("li[data-blueprint=openssh-server] a:contains('Edit packages')")
        with b.wait_timeout(120):
            b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")

        # search for openssh-server pacakge
        b.set_input_text("#cmpsr-blueprint-input-filter", "cockpit-bridge", blur=False)
        b.key_press("\r")
        with b.wait_timeout(120):
            b.wait_text("#cockpit-bridge-input", "cockpit-bridge")
        # add it to blueprint
        b.click("li[data-input=cockpit-bridge] .fa-plus")
        # wait for package added
        b.wait_visible("li[data-component=cockpit-bridge]")
        # + becomes -
        b.wait_visible("li[data-input=cockpit-bridge] .fa-minus")
        # bordered icon
        b.wait_visible("li[data-input=cockpit-bridge] .list-pf-icon-bordered")
        # redo button should be disabled
        b.wait_attr_contains("button[data-button=redo]", "class", "disabled")

        # undo
        b.click("button[data-button=undo]")
        b.wait_not_present("li[data-component=cockpit-bridge]")
        b.wait_attr_contains("button[data-button=undo]", "class", "disabled")
        # - becomes +
        b.wait_visible("li[data-input=cockpit-bridge] .fa-plus")
        # no bordered icon
        b.wait_not_present("li[data-input=cockpit-bridge] .list-pf-icon-bordered")

        # redo
        b.click("button[data-button=redo]")
        b.wait_visible("li[data-component=cockpit-bridge]")
        # undo button should be disabled
        b.wait_attr_contains("button[data-button=redo]", "class", "disabled")

        # pending commit
        b.click("a:contains('1 Pending Change')")
        # show Added cockpit-bridge
        b.wait_visible("#cmpsr-modal-pending-changes ul li:nth-child(1) .row:contains('Added')")
        b.wait_visible("#cmpsr-modal-pending-changes ul li:nth-child(1) "
                       ".row:contains('cockpit-bridge-*')")
        b.click("#cmpsr-modal-pending-changes button:contains('Close')")
        b.wait_not_present("#cmpsr-modal-pending-changes")

        # logout and login, still in edit blueprint page
        with b.wait_timeout(300):
            b.relogin("/composer", superuser=True)
        b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")

        # "1 Pending Change" still there
        b.wait_visible("a:contains('1 Pending Change')")
        b.click("#cockpit-bridge-kebab")
        b.wait_attr("#cockpit-bridge-kebab", "aria-expanded", "true")
        b.click("ul[aria-labelledby=cockpit-bridge-kebab] a:contains('Remove')")
        b.wait_not_present("li[data-component=cockpit-bridge]")
        # "2 Pending Change" now
        b.wait_visible("a:contains('2 Pending Change')")
        # commit
        b.click("button:contains('Commit')")
        b.wait_visible("#cmpsr-modal-pending-changes .form-horizontal p + div ul "
                       "li:nth-child(1) .row:contains('Removed')")
        b.wait_visible("#cmpsr-modal-pending-changes .form-horizontal p + div ul "
                       "li:nth-child(1) .row:contains('cockpit-bridge-*')")
        b.wait_in_text("#cmpsr-modal-pending-changes .form-horizontal p + div + div > strong",
                       "Changes made in a previous session")
        b.wait_visible("#cmpsr-modal-pending-changes .form-horizontal p + div + div ul "
                       "li:nth-child(1) .row:contains('Added')")
        b.wait_visible("#cmpsr-modal-pending-changes .form-horizontal p + div + div ul "
                       "li:nth-child(1) .row:contains('cockpit-bridge-*')")
        b.click("#cmpsr-modal-pending-changes .modal-footer button:contains('Commit')")
        b.wait_visible("#alertBlueprintCommitSucceeded")
        b.click("#alertBlueprintCommitSucceeded .pf-c-alert__action button")
        b.wait_not_present("#alertBlueprintCommitSucceeded")

        # collect code coverage result
        self.check_coverage()

    def testDiscard(self):
        b = self.browser

        self.login_and_go("/composer", superuser=True)
        b.wait_visible("#main")

        # go to edit package page
        b.click("li[data-blueprint=openssh-server] a:contains('Edit packages')")
        with b.wait_timeout(240):
            b.wait_visible("ul[aria-label='Available components'] li:nth-child(1)")

        # search for openssh-server pacakge
        b.set_input_text("#cmpsr-blueprint-input-filter", "cockpit-composer", blur=False)
        b.key_press("\r")
        with b.wait_timeout(120):
            b.wait_text("#cockpit-composer-input", "cockpit-composer")
        # add it to blueprint
        b.click("li[data-input=cockpit-composer] .fa-plus")
        # wait for package added
        b.wait_visible("li[data-component=cockpit-composer]")
        # click discard changes button
        b.click("button:contains('Discard changes')")
        b.wait_not_present("li[data-component=cockpit-composer]")

        # collect code coverage result
        self.check_coverage()


if __name__ == '__main__':
    testlib.test_main()
