TestStack / TestStack.Seleno

Seleno helps you write automated UI tests in the right way by implementing Page Objects and Page Components and by reading from and writing to web pages using strongly typed view models.
http://teststack.github.com/TestStack.Seleno/
MIT License
180 stars 60 forks source link

Validation of the download links: recommendation #208

Closed sirj77 closed 9 years ago

sirj77 commented 9 years ago

Hi guys,

Is there a way how to validate (check) the download links on the page using Seleno? After a click on the download link there will be a Download window open (in case if the url is valid). How to test it in a simple way? I Don't need to download the files in terms of automation, just need to be sure that link is valid and user can download any file.

I'm using Seleno + BDDfy, c#.

Thank you for the suggestions!

robdmoore commented 9 years ago

You could pull out the value of the href attribute and do a HEAD request to that URL and check for a 200 response using HttpClient?

sirj77 commented 9 years ago

robdmoore, yes, it makes sense. I've found some solution for that, but it is not working as expected and I cannot understand what Im doing wrong.

Here a piece of code inside my page object:

        public bool DoesTheFileExistRemotely()
        {
            var request = (HttpWebRequest)WebRequest.Create(UriToImage);
            request.Method = "HEAD";

            try
            {
                using (var response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        return true;
                    }
                    return false;
                }
            }
            catch (WebException) { return false; }
            catch
            {
                return false;
            }
        }

        public string UriToImage
        {
            get
            {
                return Find.Element(By.XPath(DownloadLinkXpath)).GetAttribute("href");
            }
        }

        private const string DownloadLinkXpath = "(//*[@class='media-download'])[1]";

Here my test:

....
       public void Then_I_will_be_able_to_download_the_file()
        {
            _varOfMyPage.DoesTheFileExistRemotely();
        }

The problem is that a test is passed no matter what I'm putting inside the DoesTheFileExistRemotely() method, and I need to check not only the HttpStatusCode.OK, but also that the URL will not be http://my.site/system/notfound404 (because if the url in my case is not correct the response will be with StatusCode = OK, but I'll get the page notfound404) How I can write it correctly?

robdmoore commented 9 years ago

The doesTheFileExistRemotely method returns a Boolean. If you want the test to fail you need to assert it returns true.

Presumably your 404 page either has a return code of 404 in which case your code will already work, or it will have a redirect to your 404 page in which case you can check the Location header on the response.

sirj77 commented 9 years ago

Ohh, you are definitely right, it's my fault, I just called the method instead of having Assert :)

Assert.That(_varOfMyPag.DoesTheFileExistRemotely().Equals(true));

I'm a bit stuck, because I don't know what exactly I can use in case of redirecting to the 404 page (it returns response.StatusCode == HttpStatusCode.OK). Do you know how to check the Location header on the response in my DoesTheFileExistRemotely() method?

robdmoore commented 9 years ago

try looking for response.Headers["Location"]

sirj77 commented 9 years ago

Unfortunately, it returns in both cases (for a valid link and link that redirects to the 404 notfound page) false:

public bool DoesTheFileExistRemotely()
        {
            var request = (HttpWebRequest)WebRequest.Create(UriToImage);
            request.Method = "HEAD";

            try
            {
                using (var response = (HttpWebResponse)request.GetResponse())
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        if (response.Headers["Location"].Contains("not found"))
                        {
                            return false;
                        }
                        return true;
                    }
                    return false;
                }
            }
            catch (WebException) { return false; }
            catch
            {
                return false;
            }
        }

Did I do something wrong in my code?

robdmoore commented 9 years ago

If you set a breakpoint and manually inspect what's in response.Headers["Location"] is there a difference for 404 vs not 404?

sirj77 commented 9 years ago

I've inspected it and, as I understood right, there is no difference for 404 and not 404 (in both cases a parameter Location = null under Headers, see screenshot). I've also picked out the difference in some retrieved parameters for a response. I assume that can create a condition with a check on ContentLenghth (or ContentType) to have a test failed in case of redirection to the 404 not found page?

2015-07-07_11-05-44

robdmoore commented 9 years ago

Right, so in that case your logic to return a 404 page might need to be changed to return a 404 rather than a 200. That's the most semantic way of telling if it's a Not Found page.

If you can't for some reason then maybe in this instance you can look for the text/html Content Type, although that's a bit of a hack.

sirj77 commented 9 years ago

Yep, thanks for your support :+1: I've tried and it seems that's good for me so far, I just checked with this condition:

if (response.ContentType.Contains("html")) {
return false; }
return true;

Because, if the url is not correct and redirects to the 404 not found page, the value of ContentType is "text/html" in my case