Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Running it-blocks that require the completion of another it-block

  1. #1

    Default Answered: Running it-blocks that require the completion of another it-block

    Hello there,

    Lets say in my first it-block I test the navigation to a specific component.
    The second it-Block should then test the functionality of this component.

    - How can I make sure that the first it-Block is executed before the second one?

    - Let's say it-Block 3 requires the execution of it-Block 1 but not 2, how would I achieve this behaviour?

    - Is this even a good practice, or should each it-Block be autonomous?

    - Is using standard JS functionalities like async/await, promises and callbacks the proper way to go here?

    A good source or a guide to control the 'code flow' would be appreciated

  2. Normally, each test (each "it" block) should be self contained so that the order in which they run doesn't matter (or if you decide to just run one test, instead of all). However, for end-to-end testing, you're typically testing the flow of the entire application, so it's common to have a series of tests that need to be run in order, with the subsequent test dependent on the actions performed in the previous test.

    When tests are executed, a test won't run until the previous test has completed, so they are always executed in order and won't proceed until the actions and expectations in the previous test have been completed.

  3. #2
    Sencha - Sales Team daniel.gallo's Avatar
    Join Date
    Apr 2009
    Location
    Redwood City, CA
    Posts
    338
    Answers
    55

    Default

    Normally, each test (each "it" block) should be self contained so that the order in which they run doesn't matter (or if you decide to just run one test, instead of all). However, for end-to-end testing, you're typically testing the flow of the entire application, so it's common to have a series of tests that need to be run in order, with the subsequent test dependent on the actions performed in the previous test.

    When tests are executed, a test won't run until the previous test has completed, so they are always executed in order and won't proceed until the actions and expectations in the previous test have been completed.
    Daniel Gallo
    Senior Solutions Architect
    Sencha Inc.

  4. #3

    Default

    Take a look at this example.

    Code:
    describe("Contract Maintenance", function () {
    
    
            var mainPage = { 
                searchButton: function() { return ST.button("@button-1303"); }, //DOM Query as the component query is ambiguous
                rateMaintenance : function() { return ST.component("treelistitem[text=\"Rate Maintenance\"]"); },
                contractMaintenance : function() { return ST.component("treelistitem[text=\"Contract Maintenance\"]"); }
            };
    
    
        it("should be displayed when navigating via the treelist", function () {
            // Navigating to the Contract Maintenance
            mainPage.rateMaintenance().click(); 
            mainPage.contractMaintenance().click();
            
            mainPage['resetSearchButton'] = function() { return ST.button("@button-1304-btnEl"); }; 
            
            
        });
        
        it("performs a search with pre-cleared fields", function () {
                mainPage.resetSearchButton().click();
            mainPage.searchButton().click();
            
        });
        
    });
    The resetSearchButton is only visible after navigating to the contract maintenance menu.
    Therefore it can only be added to the mainPage object dynamically in the first it-Block.

    Before even running the first statements of the firat it-Block ST throws an error because mainPage.resetSearchbutton (which is first called in the second it block) is not a function at object.

    if I place the 2 lines of code from the second it-Block inside the first it block it works perfectly fine

    Code:
    	it("should be displayed when navigating via the treelist", function () {
    		// Navigating to the Contract Maintenance
    		mainPage.rateMaintenance().click(); 
    		mainPage.contractMaintenance().click();
    		
    		mainPage['resetSearchButton'] = function() { return ST.button("@button-1304-btnEl"); }; 
    		mainPage.resetSearchButton().click();
    		mainPage.searchButton().click();
    		
    	});

  5. #4
    Sencha - Sales Team daniel.gallo's Avatar
    Join Date
    Apr 2009
    Location
    Redwood City, CA
    Posts
    338
    Answers
    55

    Default

    You can define "resetSearchButton" within your "mainPage" object upfront, as the contents of that page object aren't executed or evaluated until each one is called. So there's no need to add them later on during a test run - they can be defined in the test suite file, even if the component isn't yet visible.

    I would recommend using a more stable locator though - at the moment, the "id" of the button is being used, and this is auto-generated by the framework at runtime so is likely to change in the future. You can use the Inspect tool in Sencha Test or the Chrome extension to help generate a locator that uses an Ext JS Component Query to reference the button.
    Daniel Gallo
    Senior Solutions Architect
    Sencha Inc.

  6. #5
    Sencha - Sales Team daniel.gallo's Avatar
    Join Date
    Apr 2009
    Location
    Redwood City, CA
    Posts
    338
    Answers
    55

    Default

    Also, when the button does become visible - if there's a slight delay in it being rendered, Sencha Test handles that delay for you automatically as it always waits up to the default timeout (5 seconds) for the component/element to be located before causing the test to fail.
    Daniel Gallo
    Senior Solutions Architect
    Sencha Inc.

  7. #6

    Default

    Code:
    describe("Contract Maintenance", function () {
        
        var mainPage = {
            searchButton: function() { return ST.button("@button-1303"); }, //DOM Query as the component query is ambiguous
            resetSearchButton : function() { return ST.button("@button-1304-btnEl"); },
            rateMaintenance : function() { return ST.component("treelistitem[text=\"Rate Maintenance\"]"); },
            contractMaintenance : function() { return ST.component("treelistitem[text=\"Contract Maintenance\"]"); }
        };
    
    
    
    
        it("should be displayed when navigating via the treelist", function () {
            // Navigating to the Contract Maintenance
            mainPage.rateMaintenance().click(); 
            mainPage.contractMaintenance().click();
            
        });
    
    
        it("performs a search with pre-cleared fields", function () {
            mainPage.resetSearchButton().click();
            mainPage.searchButton().click();
            
        });
    });

    - Running the test this works perfectly fine.
    - Running the Event recorder at the end of the first it-block works fine

    But running the event recorder at the end of the second it-block causes the test to crash before even executing the first it-block with this error message:

    Code:
     Timeout waiting for target (@button-1304-btnEl) to be available for ST.future.Button. Fix the error and try recording again.



    Also I am currently referencing the 2 buttons via their DOM path as the component locator gives me ambigous results for both buttons.
    Do I need to manually specify the locator provided by the chrome extension in order to reference the button?

  8. #7

    Default

    Code:
    describe("Contract Maintenance", function () {
        
        var mainPage = {
            searchButton: function() { return ST.button("@button-1303"); }, //DOM Query as the component query is ambiguous
            resetSearchButton : function() { return ST.button("@button-1304-btnEl"); },
            rateMaintenance : function() { return ST.component("treelistitem[text=\"Rate Maintenance\"]"); },
            contractMaintenance : function() { return ST.component("treelistitem[text=\"Contract Maintenance\"]"); }
        };
    
    
        it("should be displayed when navigating via the treelist", function () {
                // Navigating to the Contract Maintenance
                mainPage.rateMaintenance().click(); 
                mainPage.contractMaintenance().click();
    
    
        });
    
    
        it("performs a search with pre-cleared fields", function () {
            mainPage.resetSearchButton().click();
            mainPage.searchButton().click();
        });
    });
    Running these tests works perfectly fine.
    Also starting the event recorder at the end of the forst it-Block works fine.

    But if I start the event recorder at the end of the second it-block the event recorder crashes before even executing the statements inside the first it-Block with the following message

    Code:
     Timeout waiting for target (@button-1304-btnEl) to be available for ST.future.Button. Fix the error and try recording again.
    Also I am using the regular DOM queries for the buttons as the component locator gives me ambiguous results.
    Do I need to manually specify the selector from the component locator in order to properly reference the buttons?

  9. #8
    Sencha - Sales Team daniel.gallo's Avatar
    Join Date
    Apr 2009
    Location
    Redwood City, CA
    Posts
    338
    Answers
    55

    Default

    It could be failing because the locator of the element ("button-1304-btnEl") has since changed. I'm not sure why that would only happen when just using the Event Recorder, versus running the tests. Switching to a Component Query would help overcome the issue if that is the case.

    The Inspect Tool in Sencha Test and the Chrome extension will list other properties of the component, which you can combine together to make the Component Query-based locator more specific.

    For example, if there are two buttons in your app with the text "Reset", this locator would match both:

    Code:
    button[text="Reset"]
    To make it more specific, other properties can be combined together to make it more specific - maybe it has a unique icon class, or reference, or some other unique properties. Once you figure out the other unique properties, they can be appended to the locator like so:

    Code:
    button[text="Reset"][reference="MenuReset"]
    The following part of the documentation shows how to use the Inspect Wizard to generate more unique locators: https://docs.sencha.com/sencha_test/...inspect_wizard. For the Chrome extension, additional properties are listed under the "Component Config" tab.
    Daniel Gallo
    Senior Solutions Architect
    Sencha Inc.

  10. #9

    Default

    What would you reccomend doing if not even the combination of all available properties (except for the id) make a specific locator? Attachment 58086

  11. #10
    Sencha - Sales Team daniel.gallo's Avatar
    Join Date
    Apr 2009
    Location
    Redwood City, CA
    Posts
    338
    Answers
    55

    Default

    Try and also restrict it based on its parent component, for example:

    Code:
    formBuilder button[text="Search"]
    That will find a component with the "xtype" of "formBuilder", then locate a button within that component where the text equals "Search".

    You can select the parent component by checking the checkbox next to "formBuilder" in the Inspect Wizard. That will then prepend the parent component's xtype to your component locator.
    Daniel Gallo
    Senior Solutions Architect
    Sencha Inc.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •