Auto generate screenshots for user manual
=========================================

[Github Issue Page](https://github.com/learningequality/ka-lite/issues/2237)


## General Approaches

These screenshots will be used for the user manual.  A screenshot may be used directly, sliced, cropped, merged, or annotated.  It can also be used more than once on the manual.  So the most viable solution is to have a list of screenshots to be generated by the script.

We create a management command to be ran as `python manage.py screenshots` and use Selenium to take screenshot of the web browser: [Take a screenshot with Selenium WebDriver](http://stackoverflow.com/a/6282203/845481).  It uses the `firefox` webdriver by default.

This command uses a Screenshot class which takes "orders" from a `screenshots.json` on what, how, and when to do the screenshots.

The `screenshots.json` data file "drives" the Screenshot class.  Each entry has a starting url and can optionally have actions that can be done when the Selenium browser loads the page.  Actions include filling-in form fields, submitting the form, or taking a screenshot in between the actions.  So an entry therefore may have one or more screenshots:
    
    1. based on the `slug` key;
    2. based on each `<slug>` key of the `inputs` array.  It is an array to make sure that the actions are parsed and sorted.

The screenshot filename value is taken from the value of the above-mentioned keys which must be unique.

The command creates a new sqlite3 database for this purpose and deletes it afterward and is specified as `SCREENSHOTS_DATABASE_NAME` on `/kalite/distributed/settings.py` among with other settings for the command.


## Requirements
1. Location to save the screenshots which is `/data/screenshots/` folder by default.
1. Browser to use for the Selenium webdriver, dimensions, and versions?  Defaults to Firefox v31.0 with 1024x68 window size
1. Operating systems and versions?
1. Some functions require Internet connectivity like device registration.


## The `screenshots.json`

Here are sample entries for the `/kalite/distributed/data/screenshots.json` file.

    [
        {
            "users": ["guest"],
            "slug": "login",
            "start_url": "/securesync/login/",
            "inputs": [],
            "pages": [5],
            "notes": ""
        },
        {
            "users": ["guest"],
            "slug": "",
            "start_url": "/securesync/login/",
            "inputs": [
                {"<slug>": "login-form"},
                {"#id_username": "username"},
                {"": "password"},
                {"<slug>": "login-form-filled"},
                {"<submit>": ""},
                {"<slug>": "login-form-saved"}
            ],
            "pages": [5],
            "notes": ""
        }
    ]
    
    users == ["guest", "admin", "student", "coach", "hub-guest", "hub-user"]
    slug ==  if has value, must be unique and will be appended `.png` to become the filename of the screenshot
    start_url == where the browser will start to do the inputs 
    inputs == array of key-value objects as inputs (selector, text, special codes, etc), to do to show the page as per url.  Possible values for object keys in order of precedence are:
        "<slug>" == take a screenshot here and the value, which must be a unique slug, is used as filename
        "<submit>" == submit the page by sending the Enter key to the browser
        "selector": "value" == If the first character is "#" or "." tries to find an element by id or class, respectively. Otherwise tries to find the element by name. Then it activates the element by clicking it. If the value is nonempty, then it will send the value with `send_keys`.
        "": "value" == Finally if the key is empty but there is a value, then value will be sent to the active browser's active element (as from `browser.switch_to_active_element()`) with `send_keys`. This is meant to be used as part of a sequence of actions, where an element has been previously selected.
    pages == page numbers from user guide where the screenshot can be used (for reference)
    notes == notes for the screenshot


## Steps

1. Just ran `python manage.py screenshots`.
1. Note that the running instance of ka-lite is from `DJANGO_LIVE_TEST_SERVER_ADDRESS` which defaults to `http://localhost:8081` - no need to have a running instance of the project.
1. Note that Firefox v31.0 must be installed and set as default to be used by Selenium (see Selenium issue with Firefox below).
1. Check the generated .png files at `/data/screenshots/` folder.


## References
* [KA-Lite Latest User Guides](https://learningequality.org/ka-lite/user-guides/latest)
* Use Selenium to take screenshot of web browser: [Take a screenshot with Selenium WebDriver](http://stackoverflow.com/a/6282203/845481)
1. [For Selenium issue with Mozilla Firefox](http://stackoverflow.com/a/25645344)
    * [Multiple Firefox profiles](https://developer.mozilla.org/en-US/docs/Mozilla/Multiple_Firefox_Profiles)
    * [Profile Manager](https://developer.mozilla.org/en-US/docs/Profile_Manager)


## Other considerations:

1. Was planning to hook up with tests.  So if we have a test suite for student registration where the test case is 
to go thru the steps, do the inputs, validations, etc - then we can call a method within the test to 
generate the screenshots, passing the output filename for each call.  Dropped this to create a Screenshot class which takes "orders" from a screenshots.json on what, how, and when to do the screenshots so we can customize the data and flow without relying on the test suites.


## TODO:

1. Hub browsing, device registration, form filling, login, etc at [KA-Lite Hub](https://hub.learningequality.org/).
