Cross-page testing.
==================

Modern RIA applications rarely require a full page refresh, but sometimes you may still need to write such a test.
For example when testing a login form submit. This guide describes the specifics of writing such tests.

Please note, that this functionality is available only in the <a href="https://bryntum.com/store/siesta">Standard Package</a>.


Contexts
---------

To be able to test the page refresh/redirect, the *test script* (`*.t.js file`) should reside in a different context from the *test page*.
This can be achieved with the {@link Siesta.Project.Browser#enablePageRedirect enablePageRedirect} option:

    project.plan(
        '010_normal_test.t.js',
        {
            enablePageRedirect  : true,
            url                 : '020_page_redirect.t.js'
        }
    )
    
Please note, that any preload files you have will still be loaded in the context of the test page and not the context of the script.

Since contexts are separated, inside the test script, one need to use `t.global` to reach any global objects of the test page. 

    StartTest(t => {
        // BAD - the "MyApp" global is loaded into different page
        let store = new MyApp.MyStoreClass();
        
        // GOOD - pick the "MyApp" global from the test page
        let store = new t.global.MyApp.MyStoreClass();
        
        // BEST - save all required globals upfront, in variables
        const MyApp   = t.global.MyApp;
    }) 


When you need to perform a page redirect or refresh use {@link Siesta.Test.Browser#waitForPageLoad waitForPageLoad} method. 
It accepts a callback which will receive the `window` object of the new page (same as `t.global`).   

    t.waitForPageLoad(window => {
        // new reference to `MyApp`
        const MyApp   = window.MyApp;
    })

As a summary - tests with {@link Siesta.Project.Browser#enablePageRedirect enablePageRedirect} will "survive" page update / refresh.


Testing X-Domain Websites With Siesta in Chrome
=====================================

The cross-page tests, described above, are still limited to the same origin policy though, as any other web pages. The recommended approach
is to place your tests, right in one of the root folders of your deploy. In this way, your tests suite and your application will share
the same origin and it will be possible to use cross-page communication.

However, in Chrome, we can also just disable the same-origin security check, which is sometimes very useful when 
using <a href="#!/guide/event_recorder">Events recorder</a>.

We need to do two things to be able to test a site on another domain.

1. Disabling Web Security in Chrome
------------

Let’s say you wanted to run a test targeting `https://www.google.com` from your own localhost. A simple project setup would look like this:

    var project = Siesta.Project.Browser
     
    project.configure({
        enablePageRedirect : true
    })
     
    project.plan(
        {
            pageUrl     : '//google.com',
            url         : 'x-domain.t.js'
        }
    )
    
    project.start()

Note that we set {@link Siesta.Project.Browser#enablePageRedirect enablePageRedirect} to true since the test will navigate between different pages. 
To allow Siesta to access an iframe pointing to a remote site, you can launch Chrome with a special command line switch.

On Linux, it will look like:
    
    google-chrome --disable-web-security --user-data-dir=~/new_chrome_profile

If you have a Mac:

    open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir=~/new_chrome_profile

For Windows:

    c:\Program Files (x86)\Google\Chrome\Application>chrome.exe --disable-web-security --user-data-dir=c:\new_chrome_profile

The `--disable-web-security` flag tells Chrome to not enforce the Same Origin Policy. For more information about Chrome command line switches, please see 
[this resource](http://peter.sh/experiments/chromium-command-line-switches/). 
Note, that you need to specify a valid directory for the `–user-data-dir` switch, pointing to some empty, but existing, directory - a new Chrome profile will be 
created in it.

2. Disabling X-Frame-Options in Chrome
----------------------

After opening Chrome with the `--disable-web-security` flag, running the test will still produce the following warning.

{@img images/xframe-error.png}

This error is a result of Google setting the `X-Frame-Options` response header to `SAMEORIGIN`. This means “The page can only be displayed in a 
frame on the same origin as the page itself”, and you can read more about this setting [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options). 
To bypass this security feature, we simply install 
the [Ignore X-Frame Headers](https://chrome.google.com/webstore/detail/ignore-x-frame-headers/gleekbfjekiniecknbkamfmkohkpodhe) extension for Chrome. 

Note, that the extension should be installed inside the `new_chrome_profile` Chrome profile.  

Now we can run the test again, and the full Google page displays normally in the Siesta iframe. 



Note about `setTimeout`
---------

The `setTimeout` function in browsers is not synchronized across different contexts. Thus if you will call `setTimeout` inside of the *test page* with lets say 100ms delay,
and then you call `setTimeout` from the *test script* with 150ms delay, there's no guarantee that the 1st function will actually be called first. 

Because of that, it's recommended to always use the `setTimeout` from the scope of the *test page*: `t.global.setTimeout`. 
Siesta provides a simple shortcut for that: {@link Siesta.Test.Browser#setTimeout t.setTimeout()} / {@link Siesta.Test.Browser#clearTimeout t.clearTimeout()}

    // pick the `MyApp` from the scope of test page
    let MyApp       = t.global.MyApp
    
    // call the method, involving the deferred calls
    MyApp.defer(function () {}, 100ms)

    // BAD: this `setTimeout` is not synchronized with the `setTimeout` of the application
    let timeoutId = setTimeout(function () {}, 150)
    
    clearTimeout(timeoutId)


    // GOOD: using `setTimeout` from the scope of test page
    let timeoutId = t.setTimeout(function () {}, 150)
    
    t.clearTimeout(timeoutId)
  

Example
---------

See the "/examples/100-standardpkg-page-redirect"


Buy this product
---------

Visit our store: <https://bryntum.com/store/siesta>


Support
---------

Ask a question in our community forum: <https://www.bryntum.com/forum/viewforum.php?f=20>

Subscribers can post expedited questions in Premium Forum: <https://www.bryntum.com/forum/viewforum.php?f=21>

Please report any bugs through the web interface at <https://www.assembla.com/spaces/bryntum/support/tickets>


See also
---------

Siesta web-page: <https://bryntum.com/products/siesta>

Other Bryntum products: <https://bryntum.com/products>



Attribution
---------

This software contains icons from the following icon packs (licensed under Creative Common 2.5/3.0 Attribution licenses)

- <http://www.famfamfam.com/lab/icons/silk/>
- <http://led24.de/iconset/>
- <http://p.yusukekamiyamane.com/>
- <http://rrze-icon-set.berlios.de/index.html>
- <http://www.smashingmagazine.com/2009/05/20/flavour-extended-the-ultimate-icon-set-for-web-designers/>
- <http://www.doublejdesign.co.uk/products-page/icons/super-mono-icons/>
- <http://pixel-mixer.com/>

Thanks a lot to the authors of the respective icons packs.


COPYRIGHT AND LICENSE
---------

Copyright (c) 2009-2018, Bryntum & Nickolay Platonov

All rights reserved.