Blob Blame History Raw
#!/usr/bin/python3

# checkpoint:
# 1. create blueprint
# 2. blueprint filter
# 3. blueprint sort

import re

import composerlib
import testlib


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

    def testCreate(self):
        b = self.browser

        self.login_and_go("/composer", authorized=True)
        b.wait_present("#main")

        # create blueprint
        b.click(".toolbar-pf-action-right #cmpsr-btn-crt-blueprint")
        b.wait_present("div[role=dialog] #cmpsr-modal-crt-blueprint")
        # empty name blueprint
        b.set_input_text("#textInput-modal-markup", "")
        b.set_input_text("#textInput2-modal-markup", "test")
        # should have error message and disable Create button
        b.wait_text("#cmpsr-modal-crt-blueprint .help-block", "A blueprint name is required.")
        b.wait_attr("#create-blueprint-modal-create-button", "disabled", "")
        b.click("#cmpsr-modal-crt-blueprint button:contains('Cancel')")
        b.wait_not_present("div[role=dialog] #cmpsr-modal-crt-blueprint")

        # invalid characters for blueprint name
        invalid_chars = {
            " ": "spaces.",
            "$": "the character: $",
            "/*": "the characters: / *",
            "= ": "spaces or the character: =",
            " ! '": "spaces or the characters: ! '"
        }
        for c in invalid_chars.keys():
            b.click(".toolbar-pf-action-right #cmpsr-btn-crt-blueprint")
            b.wait_present("div[role=dialog] #cmpsr-modal-crt-blueprint")
            # empty name blueprint
            b.set_input_text("#textInput-modal-markup", "-_.{}".format(c))
            b.wait_text("#cmpsr-modal-crt-blueprint .help-block",
                        "Blueprint names cannot contain {}".format(invalid_chars[c]))
        b.click("#cmpsr-modal-crt-blueprint .modal-header .close")
        b.wait_not_present("div[role=dialog] #cmpsr-modal-crt-blueprint")

        # duplicate name
        # wait until the openssh-server blueprint is there
        b.wait_in_text("ul[aria-label=Blueprints]", "openssh-server")
        b.click(".toolbar-pf-action-right #cmpsr-btn-crt-blueprint")
        b.wait_present("div[role=dialog] #cmpsr-modal-crt-blueprint")
        # empty name blueprint
        b.set_input_text("#textInput-modal-markup", "openssh-server")
        b.set_input_text("#textInput2-modal-markup", "openssh server image")
        b.wait_text("#cmpsr-modal-crt-blueprint .help-block",
                    "The name openssh-server already exists.")
        b.click("#cmpsr-modal-crt-blueprint button:contains('Cancel')")
        b.wait_not_present("div[role=dialog] #cmpsr-modal-crt-blueprint")

        # duplicate name (by pressing enter)
        # wait until the openssh-server blueprint is there
        b.wait_in_text("ul[aria-label=Blueprints]", "openssh-server")
        b.click(".toolbar-pf-action-right #cmpsr-btn-crt-blueprint")
        b.wait_present("div[role=dialog] #cmpsr-modal-crt-blueprint")
        # empty name blueprint
        b.set_input_text("#textInput-modal-markup", "openssh-server")
        b.key_press("\r")
        b.wait_text("#cmpsr-modal-crt-blueprint .alert-danger", "Specify a new blueprint name.")
        b.click("#cmpsr-modal-crt-blueprint button:contains('Cancel')")
        b.wait_not_present("div[role=dialog] #cmpsr-modal-crt-blueprint")

        # collect code coverage result
        self.check_coverage()

    def testFilter(self):
        b = self.browser

        self.login_and_go("/composer", authorized=True)
        b.wait_present("#main")

        # filter "openssh-server" blueprint
        b.set_input_text("#filter-blueprints", "openssh")
        b.key_press("\r")
        b.wait_in_text(".filter-pf-active-label + .list-inline .label", "Name: openssh")
        b.wait_present("#openssh-server-name")
        b.wait_not_present("#httpd-server-name")
        # clear filter
        b.click(".filter-pf-active-label + .list-inline .pficon-close")
        b.wait_not_present("p:contains('Active Filters:')")

        # filter "httpd" will show three matched blueprints
        b.set_input_text("#filter-blueprints", "httpd")
        b.key_press("\r")
        b.wait_in_text(".filter-pf-active-label + .list-inline .label", "Name: httpd")
        b.wait_not_present("#openssh-server-name")
        b.wait_present("#httpd-server-name")
        b.wait_present("#httpd-server-with-hostname-name")
        b.wait_present("#httpd-server-with-user-name")
        # clear filter
        b.click("button:contains('Clear All Filters')")
        b.wait_not_present("p:contains('Active Filters:')")

        # collect code coverage result
        self.check_coverage()

    def testSort(self):
        b = self.browser

        self.login_and_go("/composer", authorized=True)
        b.wait_present("#main")

        blueprint_list = [
            "httpd-server",
            "httpd-server-with-hostname",
            "httpd-server-with-user",
            "openssh-server"
        ]
        # sort from Z-A
        b.wait_present("ul[aria-label=Blueprints]")
        b.click(".fa-sort-alpha-asc")
        b.wait_present(".fa-sort-alpha-desc")
        for i, v in enumerate(sorted(blueprint_list, reverse=True)):
            b.wait_text("ul[aria-label=Blueprints] li:nth-child({}) a strong".format(i + 1), v)

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

        # collect code coverage result
        self.check_coverage()

    def testExport(self):
        b = self.browser
        m = self.machine

        self.login_and_go("/composer", authorized=True)
        b.wait_present("#main")

        # export package list
        actions_drop_down_sel = "#openssh-server-kebab"
        b.click(actions_drop_down_sel)
        b.wait_attr(actions_drop_down_sel, "aria-expanded", "true")
        b.click("li[data-blueprint=openssh-server] a:contains('Export')")
        b.wait_present("#cmpsr-modal-export")
        with b.wait_timeout(300):
            b.wait_in_text("#textInput2-modal-markup", "openssh-server")
        packages_list = b.text("#textInput2-modal-markup")
        b.click("#cmpsr-modal-export button[data-btn=copy-export]")
        b.click("#cmpsr-modal-export button[data-btn=close-export]")
        b.wait_not_present("#cmpsr-modal-export")

        list_from_backend = m.execute("""
            composer-cli blueprints depsolve openssh-server | tail -n +2
            """).split()
        # remove tailing ".x86_64" or ".noarch"(6 chars) or ".aarch64"(7 chars)
        # and "*:" in libpcap-14:1.9.1-2.fc31.x86_64
        regex = re.compile("-[0-9]*:")

        def remove(x):
            if x.endswith("aarch64"):
                return regex.sub("-", x[:-8])
            else:
                return regex.sub("-", x[:-7])
        format_list = map(remove, list_from_backend)

        self.assertEqual(packages_list, "\n".join(format_list))

        # collect code coverage result
        self.check_coverage()


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