Testing AngularJS with Selenium

后端 未结 12 724
梦毁少年i
梦毁少年i 2020-11-27 04:56

I have a SPA application on stack ASP MVC + AngularJS and I\'d like to test the UI. For now I\'m trying Selenium with PhantomJS and WebKit drivers.

This is a sample

12条回答
  •  情深已故
    2020-11-27 05:27

    We have had a similar issue where our in house framework is being used to test multiple sites, some of these are using JQuery and some are using AngularJS (and 1 even has a mixture!). Our framework is written in C# so it was important that any JScript being executed was done in minimal chunks (for debugging purposes). It actually took a lot of the above answers and mashed them together (so credit where credit is due @npjohns). Below is an explanation of what we did:

    The following returns a true / false if the HTML DOM has loaded:

            public bool DomHasLoaded(IJavaScriptExecutor jsExecutor, int timeout = 5)
        {
    
            var hasThePageLoaded = jsExecutor.ExecuteScript("return document.readyState");
            while (hasThePageLoaded == null || ((string)hasThePageLoaded != "complete" && timeout > 0))
            {
                Thread.Sleep(100);
                timeout--;
                hasThePageLoaded = jsExecutor.ExecuteScript("return document.readyState");
                if (timeout != 0) continue;
                Console.WriteLine("The page has not loaded successfully in the time provided.");
                return false;
            }
            return true;
        }
    

    Then we check whether JQuery is being used:

    public bool IsJqueryBeingUsed(IJavaScriptExecutor jsExecutor)
        {
            var isTheSiteUsingJQuery = jsExecutor.ExecuteScript("return window.jQuery != undefined");
            return (bool)isTheSiteUsingJQuery;
        }
    

    If JQuery is being used we then check that it's loaded:

    public bool JqueryHasLoaded(IJavaScriptExecutor jsExecutor, int timeout = 5)
            {
                    var hasTheJQueryLoaded = jsExecutor.ExecuteScript("jQuery.active === 0");
                    while (hasTheJQueryLoaded == null || (!(bool) hasTheJQueryLoaded && timeout > 0))
                    {
                        Thread.Sleep(100);
                    timeout--;
                        hasTheJQueryLoaded = jsExecutor.ExecuteScript("jQuery.active === 0");
                        if (timeout != 0) continue;
                        Console.WriteLine(
                            "JQuery is being used by the site but has failed to successfully load.");
                        return false;
                    }
                    return (bool) hasTheJQueryLoaded;
            }
    

    We then do the same for AngularJS:

        public bool AngularIsBeingUsed(IJavaScriptExecutor jsExecutor)
        {
            string UsingAngular = @"if (window.angular){
            return true;
            }";            
            var isTheSiteUsingAngular = jsExecutor.ExecuteScript(UsingAngular);
            return (bool) isTheSiteUsingAngular;
        }
    

    If it is being used then we check that it has loaded:

    public bool AngularHasLoaded(IJavaScriptExecutor jsExecutor, int timeout = 5)
            {
        string HasAngularLoaded =
            @"return (window.angular !== undefined) && (angular.element(document.body).injector() !== undefined) && (angular.element(document.body).injector().get('$http').pendingRequests.length === 0)";            
        var hasTheAngularLoaded = jsExecutor.ExecuteScript(HasAngularLoaded);
                    while (hasTheAngularLoaded == null || (!(bool)hasTheAngularLoaded && timeout > 0))
                    {
                        Thread.Sleep(100);
                        timeout--;
                        hasTheAngularLoaded = jsExecutor.ExecuteScript(HasAngularLoaded);
                        if (timeout != 0) continue;
                        Console.WriteLine(
                            "Angular is being used by the site but has failed to successfully load.");
                        return false;
    
                    }
                    return (bool)hasTheAngularLoaded;
            }
    

    After we check that the DOM has successfully loaded, you can then use these bool values to do custom waits:

        var jquery = !IsJqueryBeingUsed(javascript) || wait.Until(x => JQueryHasLoaded(javascript));
        var angular = !AngularIsBeingUsed(javascript) || wait.Until(x => AngularHasLoaded(javascript));
    

提交回复
热议问题