#!/usr/bin/python3 # checkpoint: # 1. create supported image import os import unittest import composerlib import testlib @testlib.nondestructive @testlib.timeout(2400) class TestImage(composerlib.ComposerCase): def testBasic(self): b = self.browser self.login_and_go("/composer", authorized=True) b.wait_present("#main") # create image wizard (no upload support) b.click("li[data-blueprint=httpd-server] #create-image-button") b.wait_text("#create-image-upload-wizard #blueprint-name", "httpd-server") # check ? (Process length help) button b.click("button[aria-label='Process length help']") b.wait_attr("button[aria-label='Process length help']", "aria-expanded", "true") b.wait_text(".pf-c-popover__body", "This process can take a while. " "Images are built in the order they are started.") b.click(".pf-c-popover__content button") b.wait_attr("button[aria-label='Process length help']", "aria-expanded", "false") # check ? (image size help) button b.click("button[aria-label='Image size help']") b.wait_attr("button[aria-label='Image size help']", "aria-expanded", "true") b.wait_text(".pf-c-popover__body", "Set the size that you want the image to be when instantiated. The total " "package size and target destination of your image should be considered when " "setting the image size.") b.click(".pf-c-popover__content button") b.wait_attr("button[aria-label='Image size help']", "aria-expanded", "false") # check non upload image action (Create only) # group actions for select from dropdown menu b.wait_visible("#image-type") test_selector = "#image-type option[value='qcow2']" b.wait_present(test_selector) value_id = b.attr(test_selector, "value") b.set_val("#image-type", value_id) b.wait_val("#image-type", value_id) # groups action done b.wait_text("#continue-button", "Create") # close wizard by clicking X button b.click(".pf-c-wizard__close") b.wait_not_present("#create-image-upload-wizard") # go to wizard again (upload support) b.click("li[data-blueprint=httpd-server] #create-image-button") # check upload image action (wizard) # group actions for select from dropdown menu b.wait_visible("#image-type") test_selector = "#image-type option[value='ami']" b.wait_present(test_selector) value_id = b.attr(test_selector, "value") b.set_val("#image-type", value_id) b.wait_val("#image-type", value_id) # groups action done # still keep Create if upload image not selected b.wait_text("#continue-button", "Create") # default size = 6GB for ami image b.wait_val("#create-image-size", 6) # change to 1GB = error b.focus("#create-image-size") # delete 6 and input 1 b.key_press("\b") b.key_press("1") b.wait_attr("#create-image-upload-wizard button:contains('Create')", "disabled", "") b.wait_attr_contains("#help-text-simple-form-name-helper", "class", "pf-m-error") # delete 1 and input 2001 b.key_press("\b") b.key_press("2001") b.wait_in_text("#help-text-simple-form-name-helper", "The size specified is large. We recommend that you check whether your " "target destination has any restrictions on image size.") # delete 2001 and input 6 b.key_press("\b\b\b\b") b.key_press("6") # b.set_val("#create-image-size", 6) # change to Next if upload image selected b.click("#aws-checkbox") b.click("button:contains('Next')") # Back button is click-able and back to last page b.click("button:contains('Back')") b.wait_text("#create-image-upload-wizard #blueprint-name", "httpd-server") # go to each setion by clicking link directly b.click("a:contains('Authentication')") b.click("a:contains('Destination')") b.click("a:contains('Review')") b.wait_in_text(".pf-c-alert__title", "There are one or more fields that require your attention.") b.wait_attr("#continue-button", "disabled", "") b.click("button:contains('Cancel')") b.wait_not_present("#create-image-upload-wizard") # collect code coverage result self.check_coverage() def testOpenStack(self): b = self.browser m = self.machine self.login_and_go("/composer", authorized=True) b.wait_present("#main") # create image wizard b.click("li[data-blueprint=httpd-server] #create-image-button") b.wait_text("#create-image-upload-wizard #blueprint-name", "httpd-server") # group actions for select from dropdown menu b.wait_visible("#image-type") test_selector = "#image-type option[value='openstack']" b.wait_present(test_selector) value_id = b.attr(test_selector, "value") b.set_val("#image-type", value_id) b.wait_val("#image-type", value_id) # group actions end b.focus("#create-image-size") # delete 2 and input 4 b.key_press("\b") b.key_press("4") b.click("#continue-button") b.wait_not_present("#create-image-upload-wizard") # toast notification b.wait_present("#cmpsr-toast-imageWaiting .pficon-info") b.click("#cmpsr-toast-imageWaiting .pficon-close") b.wait_not_present("#cmpsr-toast-imageWaiting .pficon-info") # got to images tab b.click("#httpd-server-name") # correct image name and type with b.wait_timeout(300): b.click("#blueprint-tabs-tab-images") b.wait_present("ul[data-list=images]") # get uuid as part of css selector uuid = m.execute(""" composer-cli compose list | grep httpd-server | awk '{print $1}' | head -1 """).rstrip() selector = "{}-compose-name".format(uuid) # NOTE work around a bug in osbuild-composer-11, which got the # capitalization wrong. This can be changed to `openstack` once we # depend on a newer version of osbuild-composer. image_type = b.attr("li[aria-labelledby={}] [data-image-type]".format(selector), "data-image-type") self.assertEqual(image_type.lower(), "openstack") # image building needs more time with b.wait_timeout(1800): b.wait_text("li[aria-labelledby={}] [data-status=true]".format(selector), "Image build complete") # image size should be 4GB b.wait_in_text("li[aria-labelledby={}] ".format(selector), "4 GB") # get image size from backend image_size = m.execute( "composer-cli compose info {} | head -1 | awk '{{print $6}}'".format(uuid) ).rstrip() self.assertEqual(int(image_size), 4 * 1024 * 1024 * 1024) # log should contains rpm, hostname, users stages and tar assembler b.click("button:contains('Logs')") b.wait_in_text("#{}-logs".format(uuid), "Stage org.osbuild.rpm") b.wait_in_text("#{}-logs".format(uuid), "Stage: org.osbuild.hostname") b.wait_in_text("#{}-logs".format(uuid), "Stage: org.osbuild.users") b.wait_in_text("#{}-logs".format(uuid), "Assembler org.osbuild.qemu") # close logs b.click("button:contains('Logs')") # download image b.click("#{}-actions".format(uuid)) b.click("a:contains('Download')") # delete image cancel first always b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Delete')".format(selector)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "false") b.click("#cmpsr-modal-delete button:contains('Cancel')") b.wait_not_present("#cmpsr-modal-delete") # delete here b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Delete')".format(selector)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "false") b.click("#cmpsr-modal-delete button:contains('Delete Image')") b.wait_not_present("#{}".format(selector)) # collect code coverage result self.check_coverage() @unittest.skipIf(os.environ.get("TEST_OS") == "fedora-31", "Does not support ostree image") def testOSTree(self): b = self.browser m = self.machine if (os.environ.get("TEST_OS") == "fedora-32"): image_type_ostree = "fedora-iot-commit" elif (os.environ.get("TEST_OS") == "rhel-8-3"): image_type_ostree = "rhel-edge-commit" self.login_and_go("/composer", authorized=True) b.wait_present("#main") # create image wizard b.click("li[data-blueprint=httpd-server] #create-image-button") b.wait_text("#create-image-upload-wizard #blueprint-name", "httpd-server") # group actions for select from dropdown menu b.wait_visible("#image-type") test_selector = "#image-type option[value='{image_type}']".format( image_type=image_type_ostree) b.wait_present(test_selector) value_id = b.attr(test_selector, "value") b.set_val("#image-type", value_id) b.wait_val("#image-type", value_id) b.click("#continue-button") b.wait_not_present("#create-image-upload-wizard") # toast notification b.wait_present("#cmpsr-toast-imageWaiting .pficon-info") b.click("#cmpsr-toast-imageWaiting .pficon-close") b.wait_not_present("#cmpsr-toast-imageWaiting .pficon-info") # got to images tab b.click("#httpd-server-name") # correct image name and type with b.wait_timeout(300): b.click("#blueprint-tabs-tab-images") b.wait_present("ul[data-list=images]") # get uuid as part of css selector uuid = m.execute(""" composer-cli compose list | grep httpd-server | awk '{print $1}' | head -1 """).rstrip() selector = "{}-compose-name".format(uuid) image_type = b.attr("li[aria-labelledby={}] [data-image-type]".format(selector), "data-image-type") self.assertEqual(image_type, image_type_ostree) # image building needs more time with b.wait_timeout(1800): b.wait_text("li[aria-labelledby={}] [data-status=true]".format(selector), "Image build complete") # log should contains rpm, hostname, users stages and tar assembler b.click("button:contains('Logs')") b.wait_in_text("#{}-logs".format(uuid), "Stage org.osbuild.rpm") b.wait_in_text("#{}-logs".format(uuid), "Stage: org.osbuild.rpm-ostree") b.wait_in_text("#{}-logs".format(uuid), "Assembler org.osbuild.ostree.commit") # close logs b.click("button:contains('Logs')") # download image b.click("#{}-actions".format(uuid)) b.click("a:contains('Download')") # delete image cancel first always b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Delete')".format(selector)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "false") b.click("#cmpsr-modal-delete button:contains('Cancel')") b.wait_not_present("#cmpsr-modal-delete") # delete here b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Delete')".format(selector)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "false") b.click("#cmpsr-modal-delete button:contains('Delete Image')") b.wait_not_present("#{}".format(selector)) self.allow_journal_messages(".*avc: denied.*", ".*audit: .*seresult=denied .*") # collect code coverage result self.check_coverage() def testCancel(self): b = self.browser m = self.machine self.login_and_go("/composer", authorized=True) b.wait_present("#main") # create image wizard b.click("li[data-blueprint=httpd-server] #create-image-button") b.wait_text("#create-image-upload-wizard #blueprint-name", "httpd-server") # group actions for select from dropdown menu b.wait_visible("#image-type") test_selector = "#image-type option[value='openstack']" b.wait_present(test_selector) value_id = b.attr(test_selector, "value") b.set_val("#image-type", value_id) b.wait_val("#image-type", value_id) # group actions end b.click("#continue-button") b.wait_not_present("#create-image-upload-wizard") # toast notification b.wait_present("#cmpsr-toast-imageWaiting .pficon-info") b.click("#cmpsr-toast-imageWaiting .pficon-close") b.wait_not_present("#cmpsr-toast-imageWaiting .pficon-info") # got to images tab b.click("#httpd-server-name") # correct image name and type with b.wait_timeout(300): b.click("#blueprint-tabs-tab-images") b.wait_present("ul[data-list=images]") # get uuid as part of css selector uuid = m.execute(""" composer-cli compose list | grep httpd-server | awk '{print $1}' | head -1 """).rstrip() selector = "{}-compose-name".format(uuid) # stop image build b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Stop')".format(selector)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "false") b.click("#cmpsr-modal-delete button:contains('Stop Build')") b.wait_not_present("#cmpsr-modal-delete") # delete canceled image build b.click("#{}-actions".format(uuid)) b.wait_attr("#{}-actions".format(uuid), "aria-expanded", "true") b.click("li[aria-labelledby={}] a:contains('Remove')".format(selector)) b.wait_not_present("#{}".format(selector)) # collect code coverage result self.check_coverage() if __name__ == '__main__': testlib.test_main()