Welcome to the Hexo documentation. If you encounter any problems when using Hexo, have a look at the troubleshooting guide, raise an issue on GitHub or start a topic on the Google Group.
How to Prepare Environment For Bluestone
- Install Nodejs LTS from website: https://nodejs.org/en/
- Install GitHub from from: https://git-scm.com/downloads
- Install Bluestone from cmd command prompt:
npm install bluestone@latest -g
- Launch cmd as administrator and run following command
bluestone install
- Close administrator cmd
- Clone Sample Project from Git:
git clone https://github.com/3wweiweiwu/sample-bluestone-project.git
- Install prerequisite for automation code. Go to sample project in command line prompt and install prerequisite:
npm install
- Launch bluestone server by running command in command prompt:
bluestone start .
- You are ready to go!
What is Typical Process of recording workflow
Overall Step
Create UI automation is easy, here is general breakdown
- Launch Bluestone
- Record Steps and Add Validation
- Correlate Locator when recording is done
- Test Run your script
- Output Script
Launch bluestone.
Launch Bluestone Service
- In a command prompt, run command:
bluestone start "path to your automation project"
- In a command prompt, run command:
Start recording
- In a seperate command prompt, run command
bluestone record "your url"
- In a seperate command prompt, run command
Status Check
- if there is purple rectangle when you hover your mouse over different elements. You may refresh web browser. Bluestone shall load automatically.
Record Your Step and add validation
Run your workflow.
- For complicated web page, I would recommend to do so at rate of 1 operation/second
Add a validation (Pause Record)
- Press Alt+q combo key to call bluestone tab
- In spot (1), select your intention. In this case, select “verify”
- In spot (2), select specific step you would like to take. In this case, select “element exists”
- In spot (3), type in waiting time, please make sure it is greater than 1s
- In spot (4), run step to verify you work
- If everything looks good, click spot(5) to add this to the workflow steps
- If you want to resume your recording, click spot (6)
\
Correlate Locator when recording is done
Press Alt+q combo key to call bluestone tab
Go to workflow panel. In the panel, choose workflow (spot 1)
Specify test suite name and test case name.
- Please note that, testcase name will be used as file name as well. PLease make sure it does not contain illegal characters (spot 2 and 3)
Correlate Locator by clicking “Resolve Pending Issue” button (spot 4)
You expect to see message in the note bar(spot 5) about your action item. Most likely, you will be asked to correlate locator
Go to particular step and click “Edit Locator” Button
In the Locator Definer view, enter locator name (spot 1) and locator (spot 2). bluestone support both selector and xpath. Otherwise, you can click “Revert” button to use default locator. You can click on “Confirm” button once you are done
- On the right side, you expect to see the view where this particular step is taken. Html is incorrect, you can use Previous html or Next html button to navigate through
- If you want to override existing locator with what you provide, you can use “force override” button
Repeat 4,5,6,7 until you correlate all locators. You expect to see text like
- Please note that Bluestone will automatically correlate existing locator in its library
At this point, you can click on “Run Workflow Button” to test run your script.
Output script. Click “Create Testcase Button” to output your script
How to Run and debug Puppeter Scripts
Run all script via command line
- Launch command prompt
- go to automation project root folder
- Run following command:
npm start
Run particular testcase via commnd line
- Launch command prompt
- go to automation project root folder
- Run following command:
node ./node_modules/mocha/bin/_mocha ./script/*.js --exit true --grep "^test1 test2$" --timeout 60000s
- –timeout the maximum timeout for each test case execution
- ^test1 test2$, the test suite and test case name. It supports regular expression
Configure Runtime in vscode
Install Vscode Extension: “Mocha sidebar”
Go to setting menu
In setting, search keyword “mocha”
Go to Mocha>Files: Glob.
Change pattern to “test/**/*.js”
Go to testing tab in vscode and click refresh key, it should find your script autoamtically
Go to any test file, you can debug the testcase
Depends on the length of your test, you may need to update timeout
Locator Function Introduction
If you have worked with Bluestone, you will be familiar with the button “Revert Selector”, this button helps us to automatically generate the locator for a Web Element that we selected previously
The functionality of “Revert Selector” button is provided by “bluestone-selector-gen.js” class and this class is made up for “Locator Functions”
Each Locator Function is created for a specific web-element, the objective is identifying some HTML elements in a specific structure that appear only in this web-element and then with these same HTML elements Bluestone is going to create the locator
Structure of bluestone-selector-gen.js
The main function is “getLocator” this function call to the rest of the locators functions, in the first line of “getLocator” you can see the const “functionList” in this list are the locators function, once the “getLocator” function is called Bluestone is going to execute the first locator function in the list, if this first locator function doesn’t generate a locator that we can use Bluestone is going to call the next function, if any locator function works the “getLocator” is going to return an object with null elements
Creating a Locator Function
First, we need to create manually a Locator, please see Create-locator-generator manual, this locator manually created is going to give us a reference of what we want to generate
All the locator functions have one and only one parameter and this parameter represent the web-element which we are working (the web-element that we selected when we press ctrl+q in the Bluestone UI), in this example we are calling the parameter like element
Now you must ask if the web-element has the specific properties that identify it as the element for which the function was created
For example, you can ask if the element has a specific tag
Also, you can ask if the element has a specific attribute and if this attribute is equal to a value or a set of values
Please see the previous two examples and analyze what happened when the element does not have the tag or the attribute that we are searching for
How you can see when the tag or the attribute do not match, we return the function createOutput without arguments, when the functions return that the code go to the next locator function
Use parentElement method
Sometimes we also need to know the properties of parent’s element for that we have the method parentElement
Its syntaxis is
parent = element.parentElement
The result of this is that the variable parent is going to be the web-element which child is the element
Use getParentNode function
In some cases, we need find a specific parent of an element, for that we have the getParentNode
The following example can read like “Give me the first element’s parent which has tag like TR, if there is not any parent with that specification (if the result of *getParentNode is null) return the function createOutput without arguments”
Use childNodes method
The childNodes method is the opposite of parentElement method, its function is getting all the element’s sons
Its sintaxis is
let childs = element.childNodes
The result of this is that the variable childs is going to be an array, and each element of the array will be a web-element which parent is the element
Use getElementByXpath function
Ok, now we know how to get all the elements that we need to create our locator but how do you know that the locator works and not only that, if works, how can we know if the locator only works for our specific web-element and no other. For this we have the getElementByXpath function
Its sintaxis is
let elements = getElementByXpath(locator)
The result of this is that the variable elements is going to be an array, and each element of the array will be a web-element that match with our locator
, once we have the result of the getElementByXpath function only need to ask how many elements have the array, if number of elements are 0 then the locator does not work, if number of elements are more than 1 then the locator works for several web-elements, therefore the locator only works if the length of the array is equal to 1
A final locator function looks like that
Please note that in the final line we return the createOutput with element and locator like parameters
What is customized function and why do we need that
In several cases we need to prepare the environment before of reproduce a test cases, for example, assume that in the test case we need to create an element so we use Bluestone to automate the creation of this element, if we don’t prepare the environment each time that the script run is going to try to create the same element with the same name and properties this could be a problem because in the most cases the site don’t allow have two elements with the same name, so before of create a new element we need to delete the old one
To help the final user to prepare the environment we can create a customized function, so before of start to recording the user will be able to call the function to delete the element with the same name and this function will be recorded already in the script
How to add customized function
To create a new customized function, we need to open a new terminal initialize bluestone with the command:
bluestone start .\
In another terminal we run the command:
bluestone function . FunctionName
Replacing FuntionName for the name of the function
Bluestone should automatically add the line FunctionName: new FunctionName.FunctionName() to the bluestone-func.js file and create the FunctionName.js file, this file is going to be the template where we are going to create our function
We can say taht the FunctionName.js file is divided into three parts the constructor, the async function and the API functions
Constructor
In the constructor we can specify the locators that indicate to Bluestone when can display the customized function, for this we have to specify all the relevant locators in its respective area
Async Function
To get a better understanding we are going to call this function as Main Async Function, in this area we put the code that we want Bluestone execute when we call the function also we specify the parameters that Bluestone ask to the final user, for example, in the previous case where we need to clean the work space deleting some elements Bluestone use API requests and since all the sites have some level of security we need to request the user that indicate the user name and password for access to the site, also since the URL could change the time in time we will need the basic URL of the requests, probably also need to indicate the element’s name that bluestone is going to delete
When we create the template of the function the Async Function looks like this
If we must implement the previous example, we need to change the default variables for the variables that we need (URL, username, password, and element’s name), please note that the change is in two parts (See the elements marked in yellow), after of the declaration of variables we put a little description that the user can read (See the elements marked in pink)
Also, in the top of all configurations we put a name of the function that the user can recognize (See the elements marked in red)
With the previous configuration the user should see this in th UI:
How you can see all that you define in the code is going to be reflected in the UI
Sample Customized Function to Prepare Environment via RestApi
The next step is creating the instructions that we want Bluestone to do when the function is called
For “best practice” we are going to create API Functions outside of our Customized Function and those functions are going to be called in the Main Async Function, is very important that we call API Functions inside of the try of the Main Async Function, something like this:
How you can see, we called two API Functions “getAllCatchReports” and “deleteCatchReportForId”, we called API Functions because they are created using the API requests. The first is called to get some ids and the other is used to delete the elements that correspond to those ids
Creating an API Function using requests
Ok, now you know how the Customized Function is structured but…. What is inside of the API Functions?
Before answering that we need to understand some basic concepts
- API Calls or Requests
Is the process of a client application submitting a request to an API and that API retrieving the requested data from the external server or program and delivering it back to the client
Each time that the client require get information of the API or need that the API modify something use an API Call and when the API receive and API Call the API is going to send a Request to the client
- Request Method
A method indicates what is the basic purpose of the request. There are 4 types of methods: GET, POST, PUT and DELETE, in this moment we do not need to understand what the difference between them is, we only need know that each request has one
- URL’s request
Is the most essential element in the request, the URL’s request indicates to the API which are the actions needed to execute the request
- Header
In the header we can see a lot of information but the most important is the URL’s request and the method
- Payload
It is the crucial information that the client submits to the API when the client are making an API request, normally is sending with methods POST or PUT
- API key or access token
The API needs to know if the request is being sent to an authorized user
There are 2 ways to do it the first is sending the credentials (user, password and sometimes domain) and the second is with the access token, to get the access token we need to send a request with the credentials and then the API should respond us with an access token, this access token is going to be send it with the request
- Response
When the API receives a request, it is going to send a response, the response is sent in JASON format and has information of success or failure and in some cases also has information that the client needs to show the information
Obtain the request needed
To get the requests that the client sends to the API please follow the next steps
Open a web browser in incognito view
In any part of the window press right click and select “Inspect”
Go to “Network” and select the checkboxes “Preserve log” and “Disable cache” the window should look like this
Now all the requests that the client send its going to be recording after some actions in the web server the windows is going to looks like this
Select any of the requests and the web browser is going to display the information of this request
There is not an easy way to identify the request that we need but you can see the following suggestions
Before of make the action in the web browser you can clear the recording, if you do that when you make the action the only request that is going to display are those which are relates with the actions, for example supposed that when you press a button the web browser display a list of elements so before of press the button you can clear the recording and then press the button, so when you look for the request which response has the information that you need is going to be easier
When you look for a request that asks for information start with the request which method is a GET or POST
It is difficult to read a response because it is in JASON format so you can use a JSON Viewer like this tool, we can copy/paste the response in the text area and the tool will show us the information in an uncomplicated way to understand, plese see the images below
If we need a request to delete elements, the request has the method DELETE
Identify the access
As we saw earlier there are two ways to demonstrate to sever that we are authorized people
The first way with Access Token, when the request has an Authorization section like the image below means that the request uses an Access Token otherwise the request needs to send the user’s name and password
Create our API Function
Create our API Function using the Token
- We need to create a function that use the request to access to the site, for example when we want to access a site and the site ask us a user and password the request to access is going to be sending when we press the button of login, we can identify this request because its response should include the Access Token like this:
In this case we do not need use the JASON Viewer tool because in FireFox the response is already converted in a straightforward way to see
Once we identify the request of Login, we can extract the URL and create the authenticate function. Please note that the user, password, and part of the URL are sending like parameters because the final user is going to indicated
Now we are going to create our API Function taking the URL’s request, please remember that part of the URL is indicated for the final user, so we are going to get like a parameter
After creating the URL’s request we are going to get the Access Token with our Authenticate Function
With the URL’s request and the Access Token we are going to create the variable res and store the response of the request that uses the URL and the Access Token
Finally we are going to manipulate the information of the response to get the element/s that we need
Create our API Function using API Access
Now we are going to create our API Function taking the URL’s request, please remember that part of the URL is indicated for the final user, so we are going to get like a parameter
Specify the method
Specify the data, in the data we are going to indicate the information of the Payload
We include in the beginning of function the variable credentials with the user and password, this is because the request of the example does not use an Access Token
Finally we are going to manipulate the information of the response to get the element/s that we need
How to update customized function
Sometimes there is a product change and with this the request taht we use could also change
In that case first we need to identify where the problem is
To identify it we can put Debugger Points in the API Functions specifically in the catch areas and then run manually a test case which is calling the Customized Function, with this we can know in which API Function is the problem
Once we identify which is the API Function that we need to fix we are going to record again the request that the site uses to make the action and we will compare, if there is something different, we only need no replace it