Hacking Java Script Short
Hacking Java Script Short
Alan Richardson
EvilTester.com
EvilTester.com Hacking JavaScript
Copyright © 2021 Alan Richardson, Compendium Developments Ltd. All rights reserved.
2 Alan Richardson
Contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Hacking JavaScript Apps and Games . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Why? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Played vs Played With . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Microcosm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Practicing Using JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Free Video Discussing This Topic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Some Notes on Bot Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Want to see my XType bot in action? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Example Bot Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Testing Evil Tester Sloganizer From the JavaScript Console . . . . . . . . . . . . . . . . . . 16
JavaScript HTML Element Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
onclick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Look at the source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Interacting with applications from the console . . . . . . . . . . . . . . . . . . . . . . 19
Call functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
for loops and console.log . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Interacting with the sloganizer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Advanced Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
setInterval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Hack the Sloganizer to create your own slogans . . . . . . . . . . . . . . . . . . . . . 24
Using the existing structures: . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Using New Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Practical application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3
EvilTester.com Hacking JavaScript
4 Alan Richardson
Hacking JavaScript EvilTester.com
Alan Richardson 5
EvilTester.com Hacking JavaScript
6 Alan Richardson
Hacking JavaScript EvilTester.com
Introduction
Welcome to this short ebook on using JavaScript from the Browser Dev Tools Console.
• improve my JavaScript
• hack some online games
• manipulate web applications I was testing
Over time my JavaScript has improved to the point that I now write simple applications in JavaScript
and using Google App Script.
This ebook will provide some tutorial information, reference information and links to practice applica-
tions and learning material.
This is a draft ebook and I will expand it in the future to be a proper book.
Both of these tutorials will have you manipulating a browser application from the console and writing
some JavaScript.
If you want a video tutorial then I have a free online course on “Automating in the Browser Using
JavaScript” hosted on Test Automation U
• testautomationu.applitools.com/automating-in-the-browser-using-javascript
• Alan Richardson
And if you are serious about improving as a tester and want exclusive daily posts then join the Evil
Tester Patreon Programme and gain access to exclusive posts, videos and courses:
• https://www.patreon.com/eviltester
Alan Richardson 7
EvilTester.com Hacking JavaScript
Manipulating the game or application to do things it was never designed to do. Or automate it
from the JavaScript console and bypass the programmed GUI.
Why?
‘Hacking’ is a useful concept to trigger our thinking around creative ways to interact or manipulate the
application.
When you Play with the game, you go beyond what the game designer intended, you can add much
more value to your education.
Microcosm
• we enter data
• which goes to the backend
• and is stored in the database
• and we see some visual indication of that
• the system receives more input from more people
• a batch or collation process kicks off
• we see an update from the server with the collation
8 Alan Richardson
Hacking JavaScript EvilTester.com
All the techniques we use for testing, we can use when ‘hacking’ games, and because the feedback is
so fast, we have to:
All the ‘stuff’ we do when we are testing, we have to do when ‘hacking’ the JavaScript game.
Alan Richardson 9
EvilTester.com Hacking JavaScript
One way I practice my Software Testing, improve my JavaScript programming and practice my au-
tomating is by ‘hacking’ JavaScript games.
One of my bots scored 282010 on https://phoboslab.org/xtype/ This ‘bot’ is JavaScript code that runs
from the Browser Dev Tools and plays the game.
To create this I have to learn to use the dev tool to inspect the Dom, and the running memory space,
and read the JavaScript. All of this is modelling the application. A recon step that helps me with my
Software Testing.
As I recon the app I look at the network tab to see what files are loaded and what API calls are issued.
This also informs my model. And makes me think about Injection and Manipulation points.
Perhaps I can use a proxy to trap and amend those requests? Perhaps my proxy can respond with a
different file or data automatically?
These are thought process and skills that I can apply in my testing. I also learn more about HTTP, Dev
tools and Proxies.
When the game is running I have to observe its execution behaviour. I build a model of the software
and its functionality. This informs my Software Testing. I have to build models of the application as I
test and make decisions about what to target.
To ‘hack’ the game, I have to inspect the objects which have been instantiated by the code. I can do
this in the console by typing in the object names.
10 Alan Richardson
Hacking JavaScript EvilTester.com
To learn what these objects are I have to read the game code. This improves my JavaScript because
one of the best ways to learn to write code is to read code and try to understand what it does.
I can use the Snippets view in Chrome Sources to write JavaScript. This is a built in mini JavaScript IDE
in the browser.
Alan Richardson 11
EvilTester.com Hacking JavaScript
I can write simple code here to manipulate the game objects in memory to help me cheat and hack
the game. I don’t need to learn a lot of JavaScript to do this, and most of the JavaScript you need is
already in the game source itself.
To write a ‘bot’... code that executes in its own thread periodically to do something, I use the ‘setInterval’
command. This is the fundamental key to writing JavaScript bots. e.g.
The above line calls a function named infiniteLives every second. That infiniteLives function checks if
my number of lives have decreased, and if so, increase them. e.g.
function infiniteLives(){
if(game.lives<3){
game.lives=3;
}
}
clearInterval(infiniteLivesBot);
I can run that code from the snippets view, or paste it into the console, or convert it into a bookmarklet.
Whatever is more convenient to help me when I want to hack the game. I do the same thing to support
my testing e.g. setup data, delete data etc.
This is a form of ‘tactical’ automating. It won’t scale, it doesn’t go into continuous integration. It
supports me. It does a specific task. It automates part of my work. It is a good start to learning to
automate more strategically.
To automate xtype I had to learn how to trigger mouse events to initiate the firing functionality. I couldn’t
remember how to do this. I copy and pasted a snippet of code from stackoverflow. All professional
programmers do this.
• stackoverflow.com/questions/2381572/how-can-i-trigger-a-javascript-event-click
Part of learning programming is knowing where to find a general answer. Knowing which part of the
answer to isolate. Then having the confidence to bring that into your code and experiment with it.
As I do this, I learn more JavaScript. Which allows me to write scripts in other tools e.g. Postman. And I
can inject code into applications e.g. using WebDriver JavaScriptExecutor. The more I practice, the
12 Alan Richardson
Hacking JavaScript EvilTester.com
I take the knowledge and then write small utilities or applications to help me. I write a lot of small
JavaScript utilities to help me with data extract activities and reformatting of data from Web applica-
tions.
I extended my knowledge by writing JavaScript applications and games which I bundled into:
• github.com/eviltester/TestingApp
• running here eviltester.github.io/TestingApp
If you want to experiment with simple games manipulation and hacking then the games in this app are
designed for that purpose.
Doing this also has a knock on effect on how I view web applications. The GUI is no longer a trusted
client. The GUI can be manipulated by the user. The messages it sends to the server can be manipulated
by the user. The server needs to be robust.
This helps my Software Testing. I have to go deeper when I test. And by practicing I develop the skills
to go deeper when I test. I can recognise when requirements need to be tested more deeply than they
state on the surface.
This helps my programming. I am very aware that the server needs to validate and approach the input
data with caution.
This is one way that I practice my Software Testing, JavaScript programming and automating. The
benefit to me has been enormous. I recommend this, or adapt the ideas and create your own practice
path.
• youtu.be/TpCCEEsW4rA
This was a hard bot to write Xtype is a bullet hell shooter which are challenging to play, let alone
automate - and no, I’m not going to show you the code for the bot.
I like these games because they are all well written, I can read the code to improve my programming,
and they are fun to play.
Alan Richardson 13
EvilTester.com Hacking JavaScript
Many of my bots are not full playing bots like the x-type bot. They are support tools. And when I started
to automate x-type I started with support tools:
• a heads up display so that a map of the screen was rendered on screen as I played showing me
the position of Rex to help me avoid him, and showing me where the exit was
• a trap for Rex, so that if he entered it he couldn’t move
• a chain for Rex so that he never moved from his starting point
• armour so that if Rex caught me, he couldn’t kill me
For many games I try to think how to add extra features to make the game more interesting. I don’t
have the skill or patience to write games like these, but I do have the skill and motivation to ‘augment’
them for my learning.
This is analogous to writing ‘tools’ to support our testing, or making applications more ‘testable’.
Note: my games github.com/eviltester/TestingApp are not well written, but they are very easy to
understand and hack.
• youtu.be/xCN26i0-ees
I have a few gist code snippets which are bots, or used to automate applications from the console. You
can find these online:
• https://gist.github.com/eviltester
• gist.github.com/eviltester/076b8e52a9b3c0bb3868a0ec6150c860
14 Alan Richardson
Hacking JavaScript EvilTester.com
• https://zty.pe/
NOTE: The above code differs from the gist in that it runs every 10 milliseconds, the published gist
uses 100 milliseconds.
The above code is very inefficient because is issues a keystroke every 10 milliseconds without knowing
if that letter is valid or will make a difference. I eventually made it much better to make more use the
in memory variables, but it might be a useful place to start when experimenting with your own bots
later.
I recommend working through the rest of this text, and then revisiting this bot later when you have
developed more JavaScript and DOM Analysis skills.
Alan Richardson 15
EvilTester.com Hacking JavaScript
We will start with the “Evil Tester Sloganizer” as an example to get us used to using JavaScript and
working with the console.
A simple web page with a button which you click, and a new ‘slogan’ appears on screen.
The button has an event handler that deals with the event.
In the case of “Evil Tester Sloganizer” the event is coded into the page so you can see the onclick
handler in the code.
<div class="title">
<button class="title" onclick="changeSlogan()">I Want A Slogan</button
>
</div>
Apps don’t always make it so easy, and sometimes the handlers are added dynamically by JavaScript.
We can also see the event handler by using the browser ‘inspect’ functionality.
In the ‘Event Listeners’ tab. On this tab we can also ‘click through’ to see where in the source code the
event is handled.
onclick
onclick="changeSlogan()"
If I open the JavaScript console and type ‘changeSlogan()’ then the slogan will change.
16 Alan Richardson
Hacking JavaScript EvilTester.com
Instantly we know that we don’t have to automate this application from the GUI any more. We can
write JavaScript code in the console to interact with the app.
Exercise
For this application, all the source code is in the loaded HTML page.
We can see it in the <script>...</script> element at the bottom of the page.
If this is the first time you’ve seen JavaScript then it might look complicated but it is pretty simple.
We basically have:
• some objects
• some functions
We are not going to teach you a lot of JavaScript in this section, you’ll have to to research on your own
if you want to learn JavaScript properly.
The aim here is to learn enough JavaScript to start interacting with applications from the console and
manipulate the running state of the application.
Objects
• an object called phrases which is a set of phrases, and these ‘phrases’ are arrays
• an object called sentences which is an array of string
Both of these objects (phrases, sentences) are accessible from the JavaScript console.
If I type phrases at the console I will see information about that object in the console
Alan Richardson 17
EvilTester.com Hacking JavaScript
And it is an interactive view so I can expand it to see all the ‘keys’ and their values.
If the object has any functions then I’ll see them listed too.
Functions
function randomNumberUpTo(theVal){
return Math.floor(Math.random() * theVal)
}
• This is a function
• called randomNumberUpTo
• it takes a single argument theVal
• it uses the JavaScript Match library
• it returns a random number up to the value of theVal
> randomNumberUpTo(4)
< 1
> randomNumberUpTo(4)
< 2
> randomNumberUpTo(4)
< 0
Every time I enter the function call into the console, the function will be called and it will display the
return value of the function in the console.
Exercise
• Look at the source for the sloganizer and see how much you understand
• type the names of the objects that you see into the console
• explore the output in the console
• run some of the functions that you find
• observe that when you type a function name you have code completion in the console (press
tab to autocomplete a function name)
• if you press the cursor up and down then you can select items from the console history - use this
to re-enter commands
18 Alan Richardson
Hacking JavaScript EvilTester.com
You can learn more about the console in the Chrome developer tools help:
• https://developers.google.com/web/tools/chrome-devtools/debug/console/?hl=en
• Call functions
• Change variables
Call functions
The hardest part about interacting with the application from the console is knowing which functions
to call.
• randomNumberUpTo
• removeExtraSpaces
• removeSpacesAtStart
• capitalizeFirstLetter
• removeSpacesBeforePunctuation
• getRandomValueFromArray
• changeSlogan
• random_sentence
• process_sentence
• expand_text
• getSentence
The reason I have split these into ‘application’ and ‘low level’ is because the ‘low level’ functions
basically just take JavaScript primitives and return values. They could be found in pretty much any
application.
• changeSlogan calls other functions to generate a random slogan and makes it appear on the
GUI
• random_sentence returns a random sentence filled with random values
Alan Richardson 19
EvilTester.com Hacking JavaScript
• process_sentence given a sentence template it will fill it with values then call all the utility
functions to process the string.
• expand_text does the work of expanding a template
• getSentence calls the utility function to choose a random sentence template
For example, suppose we wanted to make sure that the randomNumberUpTo method really did work,
but we can’t really check that from the GUI.
Since we can call randomNumberUpTo from the console we could run some tests:
Because this is ‘random’ we would have to keep typing the text in every time we want to run it.
Two very important JavaScript commands we will use when interacting from the console are:
• console.log
• for
console.log("hello world");
Would print
for A for loop allows us to run code multiple times. We can use this to run a function multiple
times.
20 Alan Richardson
Hacking JavaScript EvilTester.com
hello 1
hello 2
...
hello 99
The ... represents the other 96 lines of output .e.g. hello 3, hello 4, etc.
• start x at 1
• while x is less than 100
• write “hello” and the value of x to the console
• increment x (x++ means add 1 to x)
When you type the for loop into the console, you need to enter all the lines at the same time otherwise
you’ll see a syntax error:
> for(var=1;x<100;x++){
x Uncaught SyntaxError: Unexpected token =
Or, write it in a text editor and then paste it into the console.
I could run the randomNumberUpTo function several times and make sure the output was correct.
After running the above, it should call randomNumberUpTo 99 times and I should only see the num-
bers 0,1,2 in the console, giving me more confidence that the randomNumberUpTo function works as
expected.
Note:
• You might see numbers in icons to the left of the output e.g. (2)0 this means that 0 appeared
Alan Richardson 21
EvilTester.com Hacking JavaScript
in the console log twice in sequence but was only displayed once.
• This helps cut down on ‘noise’ if a JavaScript error is constantly being written to the console
Arrays
See w3schools.com/js/js_arrays.asp
• sentences[0] = "bob" would change the first sentence in the array to ‘bob’
Note:
If you do change anything in the objects you can always refresh the web page to return them to
normal.
Objects
Objects in JavaScript are a bit like arrays, but instead of number indexes, they are “name:value”
properties and you can use the name as an index.
See w3schools.com/js/js_objects.asp
We now have enough JavaScript knowledge to do a lot of interaction with the sloganizer.
function random_sentence(){
var sentence = getSentence();
return process_sentence(sentence);
}
22 Alan Richardson
Hacking JavaScript EvilTester.com
This basically returns a random sentence template and calls process_sentence to generate a random
version of that template.
The var creates a ‘variable’ called sentence which stores the string value returned by getSentence
.
Instead of calling getSentence to generate a random sentence, we could choose one of the sentences
from the array and call process_sentence directly:
• process_sentence(sentences[0])
This would allow us to test the first sentence template and make sure it worked.
By calling JavaScript functions directly we can interact with the JavaScript application at whatever
functions the application exposes.
Exercise:
Advanced Techniques
setInterval
There is another more advanced way of creating loops with our JavaScript code.
Instead of a loop, I’m going to create a ‘thread’ where a function is run at a time interval I decide.
Alan Richardson 23
EvilTester.com Hacking JavaScript
This basically says, create a ‘thread’ which runs every 1000 milliseconds, and it runs the function which
executes the code changeSlogan().
The code in the function(){...} can be as complicated as you like and can use any function or
object accessible in the global scope.
But, by assigning it to a variable it gives me the ability to stop the bot or ‘thread’ from running.
clearInterval(sloganbot)
• simulate more ‘user oriented’ type actions e.g. create a todo every 3 seconds.
• ‘do things’ while you use the application, e.g. create todos in the background while you use the
GUI
Also you can have multiple functions controlled by setInterval so I could also have.
And every 5 seconds fixedbot will set the slogan to "Hello World"
This is incredibly flexible I just recommend that you assign the return value from setInterval to a
variable so that you can stop it, when you want to with clearInterval.
The values in the String are keys into the phrases map.
We could override the existing data in the phrases with our own phrases by entering the following code
into the console.
phrases['o_just']=["Since when did I", "But you always", "He will rudely"
];
phrases['just_because'] = ["kick a football", "smoke bananas", "sing on
the phone"];
24 Alan Richardson
Hacking JavaScript EvilTester.com
The Sloganizer takes each value in the template, and expands it. If it finds multiple phrases associated
with each key then it randomly picks one.
Running the code that follows would create 100 slogans in the console based on the above phrases.
for(x=0;x<100;x++){
console.log(process_sentence(sentences[8]));
}
e.g.
We can add this design to the sloganizer by running the code below (Implementation):
sentences.push(
"#i_do_like #i_do_like_doing #i_like_doing_with");
phrases['i_do_like']=
Alan Richardson 25
EvilTester.com Hacking JavaScript
["I like", "I hate", "I despise", "I loathe", "I love"];
phrases['i_do_like_doing']=
["eating", "smashing", "feeding", "teasing",
"tickling", "destroying", "making", "teaching"];
phrases['i_like_doing_with']=
["cats", "dogs", "mice", "peers", "Systems",
"Managers", "Testers", "Developers", "code",
"beliefs", "memories", "attitudes"];
Since the sentence will be added to the end of the sentences array I can use the last sentence:
sentences.length-1
The code below generates 100 phrases using the template we just added.
for(x=0;x<100;x++){
console.log(process_sentence(sentences[sentences.length-1]));
}
Practical application
If you want to research more about this then search for “Generative Grammar”.
And you may find additional academic on the application to software testing by searching for “Genera-
tive Grammar test data software testing”.
process_sentence(sentences[0]);
console.log(process_sentence(sentences[0]));
26 Alan Richardson
Hacking JavaScript EvilTester.com
for(x=0;x<100;x++){
console.log(process_sentence(sentences[0]));
}
for(x=0;x<1000;x++){
console.log(random_sentence());
}
Alan Richardson 27
EvilTester.com Hacking JavaScript
TLDR; A simple link checker running from a snippet or console has some secondary advantages like
jumping to the links and showing CSP and CORB errors
To experiment with more with JavaScript and working more from the console, I wanted to write more
code and try and write simple tooling from the console. This section explains the basics of a simple
Link Checker.
• Total Validator
External crawlers are important for finding the status of pages e.g. 404, 200
As a quick experiment I wanted to see how much of a link checker I could build in JavaScript and run it
from snippets.
• https://gist.github.com/eviltester/8a27ca23f7475d6b47fc99fc11ad3198
28 Alan Richardson
Hacking JavaScript EvilTester.com
When it finishes it uses the console.table functionality to output all the objects.
...if anything caught your eye in the table, say it was link 70 in the table, then you could, in the
console...
linkReport[70].element.scrollIntoView()
linkReport[70].element.style.backgroundColor = "red"
Checking Links
I knew this wouldn’t work for all links because the browser would block some of the requests due to
cross site scripting concerns.
Extensions like Check My Links will use Chrome APIs to avoid the XSS issues.
http.onreadystatechange = (function(line,xhttp) {
return function(){
if (xhttp.readyState == xhttp.DONE) {
line.status = xhttp.status;
line.message = xhttp.responseText + xhttp.statusText;
Alan Richardson 29
EvilTester.com Hacking JavaScript
linksChecked++;
console.table(xhttp);
}
}
})(reportLine, http);
http.send();
Because this is callback based, if I output the table after the loop it would not have all the request
status so I maintain a count of links checked linksChecked++; and added a polling mechanism after
the loop:
This way the final console.table report is only shown when the number of links check matches the
number of links in the array.
http.open('HEAD', reportLine.url);
linkReport.push(reportLine);
http.onreadystatechange = (function(line,xhttp) {
return function(){
if (xhttp.readyState == xhttp.DONE) {
line.status = xhttp.status;
linksChecked++;
line.message = xhttp.responseText + xhttp.statusText;
console.table(xhttp);
}
30 Alan Richardson
Hacking JavaScript EvilTester.com
}
})(reportLine, http);
http.send();
});
var finishReport = setInterval(
function(){
if(linksChecked>=linkReport.length){
console.table(linkReport);
clearInterval(finishReport);
}
}
, 3000);
One of the issues I have with Check My Links is that when a link fails it can be hard to find it on screen
sometimes. This way I can use JavaScript in the console to jump to it.
Using Fetch
I thought I’d try with Fetch and see how different the output was:
fetch(reportLine.url, {
method: 'HEAD'
})
.then(function(response) {
linksChecked++;
reportLine.status=response.status;
reportLine.message= response.statusText + " | " +
response.type + " | " +
(response.message || "") + " | " +
(response.redirected ? "redirected | " : "") +
JSON.stringify(response.headers) ;
console.table(response);
}
)
.catch(function(error){
reportLine.message = error;
console.table(error);
linksChecked++;
});
This was a little easier to use and the response had more useful information so I crudely concatenated
the response fields I was interested into the message property of the report line.
Alan Richardson 31
EvilTester.com Hacking JavaScript
Errors
When the link checker runs it shows me all the CSP errors in the console:
VM14:1 Refused to connect to 'https://help.github.com/'because it
violates the document's Content Security Policy.
This was a useful side-effect. The table report shows me a status of 0, but I can look in the console for
the other errors.
This is a useful side-effect because I don’t see these warnings with external link checkers, but it is
important to be able to check that the various XSS policies are in place, or have been deliberately eased
up on for some servers as appropriate.
I don’t think I have any other tools which provide me with this information easily.
In order to try add even more information I thought I’d see if I could check the status for anything that
was throwing errors in the initial log.
Image tags are often used for XSS to pass information to another site, but I wanted to see if that could
give me any status information.
function imgreport(links){
links.forEach(function(link){
if(link.status==0){
// trigger error messages with status
// to the console for status of 0
var img = new Image();
img.src = link.url;
}
}
);
}
The above function creates a new image and sets the url to one of the links that failed to work with the
fetch.
32 Alan Richardson
Hacking JavaScript EvilTester.com
It did.
I had a look at the fetch documentation and saw that it could follow the redirects for me:
fetch(reportLine.url, {
method: 'HEAD',
mode: 'cors',
redirect: 'follow'
})
if(response.redirected){
reportLine.redirectedTo = response.url;
}
My final code
The final code for my linkchecker used the ‘fetch’ version as it had more actionable and useful informa-
tion.
Alan Richardson 33
EvilTester.com Hacking JavaScript
fetch(reportLine.url, {
method: 'HEAD',
mode: 'cors',
//mode: 'no-cors',
redirect: 'follow'
})
.then(function(response) {
linksChecked++;
reportLine.status=response.status;
reportLine.message= response.statusText + " | " +
response.type + " | " +
(response.message || "") + " | " +
JSON.stringify(response.headers) ;
if(response.redirected){
reportLine.redirectedTo = response.url;
}
console.table(response);
}
)
.catch(function(error){
reportLine.message = error;
console.table(error);
linksChecked++;
});
});
function imgreport(links){
links.forEach(function(link){
if(link.status==0){
// trigger error messages with status
// to the console for status of 0
var img = new Image();
img.src = link.url;
}
}
);
}
34 Alan Richardson
Hacking JavaScript EvilTester.com
The link checker report is useful to me because it does reveal issues on the page that were hinted at by
icons in Chrome, but very visible in the fetch error messages.
Using the console.table allows me to sort the ‘report’ in the console to make the investigation useful,
and I learned a bit more about fetch
All the code is easy to copy and paste to experiment with from this gist
• gist.github.com/eviltester/8a27ca23f7475d6b47fc99fc11ad3198
Alan Richardson 35
EvilTester.com Hacking JavaScript
A Cellular Automata is a simple system where the next state of a cell in the system depends on the
environment which the cell currently finds itself in.
In the Game of Life a cell in the system is alive or dead in the next state, based on the number of
neighbours it has surrounding it.
The Game of Life is useful because it is a very visual demonstration of Cellular Automata.
You can learn more about John Horton Conway’s Game of Life here:
• https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
• http://conwaylife.com/
This section will use the Game of Life Cellular Automata that I created to encourage JavaScript Hack-
ing.
• eviltester.github.io/TestingApp/games/ca/v1/ca.html
• Golly
– http://golly.sourceforge.net/
– Also available on IPad and Android
• https://bitstorm.org/gameoflife/
• https://eviltester.github.io/TestingApp/games/ca/v1/ca.html
36 Alan Richardson
Hacking JavaScript EvilTester.com
Related References:
• http://www.math.com/students/wonders/life/life.html
• http://www.ibiblio.org/lifepatterns/
– http://www.ibiblio.org/lifepatterns/october1970.html
Wolfram description
• http://mathworld.wolfram.com/GameofLife.html
• http://web.stanford.edu/class/sts145/
• http://web.stanford.edu/class/sts145/html/library.htm
Recommended Books
This game of life differs from other Games of life in that this one never ends.
• eviltester.github.io/TestingApp/games/ca/v1/ca.html
This world is an Open System and has an ongoing invasion. Where a new lifeform is randomly added
every 100 milliseconds.
Alan Richardson 37
EvilTester.com Hacking JavaScript
An Invasion Challenge
We can use the existing startInvasion function to help us figure out what to do. It basically picks a
random function from addLifeForms which adds a new lifeform to the world population.
We can do that.
Fortunately that’s easy because someone has written the code to do that.
stopInvasion();
startInvasion(100);
Where 100 is the amount of milliseconds before the next lifeform is added.
Create a Glider
One of the functions in addLifeForm is glider so I can use that to create a glider, and there are
examples of how to use that in the source code:
addLifeForms.glider(world,10,0);
But they are created so fast they collide into each other.
38 Alan Richardson
Hacking JavaScript EvilTester.com
clearInterval(gliderInvasion)
• refresh page
• quickly stopInvasion()
https://youtu.be/CeOzcn7pBQY
Alan Richardson 39
EvilTester.com Hacking JavaScript
The simplest thing we can do to this game of life is to change the colour.
https://eviltester.github.io/TestingApp/games/ca/v1/ca.html
I could use any six values from 0-9, A-F to make an HTML colour code
e.g. http://htmlcolorcodes.com
I set a break point on the line where the colour is set in the sources view.
• Line 153
• this.entityColour = "#FF0000";
this.entityColour = "#111111";
40 Alan Richardson
Hacking JavaScript EvilTester.com
If I inspect element and find where World is instantiated with new. i.e. ctrl+F and search for new
World.
world.entityColour = "#111111";
https://youtu.be/gWnvKQOb2yc
One of the suggested challenges listed in the source for the Cellular Automata game is to cycle through
the colours randomly.
world.entityColour = "#111111";
So all I have to do is have a bot to change colour every set time interval - say 1000 milliseconds.
The challenge is that I need to use a hex value to do that. So let’s figure that out first.
In JavaScript:
var myNum=255;
myNum.toString(2);
myNum.toString(16);
• I need to get a 6 character string, even if my hex value is only FF and I can do that by creating a
string and using the last 6 characters e.g.
Alan Richardson 41
EvilTester.com Hacking JavaScript
"EvilTester".substr(-6)
• And I want my string to be "0" padded at the front so I’ll just add "000000" at the front of any
string:
("000000" + "FF").substr(-6)
If I put all that together I can get a hex code for any number variable:
var myNum=3;
"#" + (("000000" + myNum.toString(16)).substr(-6))
I really want a random number - and if I look in the code for the game I can see it already has a random
number generator, so I’ll use that.
getRandomInt(0, 0xFFFFFF);
I’ll create a bot to use what we’ve just experimented with to change the colour every 1000 millisec-
onds.
I’ll edit and run this from the Snippets tab in Sources
clearInterval(colourChangeBot);
42 Alan Richardson
Hacking JavaScript EvilTester.com
And if I change the value 1000, then I can make it faster, or slower:
This is a bit slower, but a bit more sedate, you might want to put some classical music on for this.
var currColour = 0;
var colourChangeBot = setInterval(function() {
world.entityColour = "#" + ("000000" + currColour.toString(16)).substr
(-6);
currColour++;
if (currColour >= 0xFFFFFF) {
currColour = 0;
}
}, 1)
https://youtu.be/hfE99d4Slck
References
• http://www.w3schools.com/jsref/jsref_tostring_number.asp
• http://www.w3schools.com/jsref/jsref_substr.asp
• Chambers Brothers - Time has come today - “My Soul has been psychedelicized”
• https://www.youtube.com/watch?v=AQSjV4DZ-Gg
One of the challenges in the Cellular Automata game is changing the world size.
https://eviltester.github.io/TestingApp/games/ca/v1/ca.html
Alan Richardson 43
EvilTester.com Hacking JavaScript
There is a clue in the game code, because we know that it does some resizing when we change the
window size.
And if we look in that section of the code for hints we can see:
worldSizes.calculateScales();
And lower in the code we can see that worldSizes is used to create the world.
Make is smaller
worldSizes.myWorldWidth=100;
worldSizes.myWorldHeight=100;
worldSizes.calculateScales();
Make it bigger
worldSizes.myWorldWidth=1000;
worldSizes.myWorldHeight=1000;
worldSizes.calculateScales();
worldSizes.myWorldWidth=1000;
worldSizes.myWorldHeight=1000;
world.xSize=1000; world.ySize=1000;
worldSizes.calculateScales();
That worked - and its a little slower now, because thats 1000 x 1000 grid, which is 1,000,000 (1 million)
cells!
I hope you have enough memory in your machine if you try this.
An easier way to experiment is to only have the literal 1000 on one line and use the worldSizes to
change the world.
worldSizes.myWorldWidth=200; worldSizes.myWorldHeight=200;
world.xSize=worldSizes.myWorldWidth; world.ySize=worldSizes.myWorldHeight;
worldSizes.calculateScales();
44 Alan Richardson
Hacking JavaScript EvilTester.com
The ZX-81 had a resolution of 64x48, and it was black and white, so let’s simulate that.
worldSizes.myWorldWidth=64; worldSizes.myWorldHeight=48;
world.xSize=worldSizes.myWorldWidth; world.ySize=worldSizes.myWorldHeight;
world.entityColour="#000000";
worldSizes.calculateScales();
stopInvasion();
stopGame();
startGame(1000);
startInvasion(3000);
That’s probably more realistically what a ZX-81 could do (if I was programming it)
And now we can change the size of the world and control the game.
https://youtu.be/lLnyNP33S_Q
• start game
– startGame(5)
• stop game
– stopGame()
• stop invasion
– stopInvasion()
Alan Richardson 45
EvilTester.com Hacking JavaScript
stopGame();
stopInvasion();
world.nukeEmAll();
That did work, but we’ll only see the results if we start the game again:
startGame(5);
stopGame();
You can’t see it because the game isn’t running, but if I have a look at:
world.population
If I want to reset the population to make it easier to see then I could do that:
world.population = [];
46 Alan Richardson
Hacking JavaScript EvilTester.com
startGame(5);
100 might not actually be big enough, depending on the size of the world, to create more for a viable
population for survival.
And the easiest way to clean the board when the game is running is to clear the population:
world.population = [];
Experiment with different loop sizes to see what works for your world - remember its a harsh world out
there for these cells so sometimes you need to start with a lot of them.
https://youtu.be/uZv2s5QjPps
Alan Richardson 47
EvilTester.com Hacking JavaScript
Bookmarklets
e.g.
document.title=window.prompt("","hello");
(function(){document.title=window.prompt("","hello");})()
javascript:(function(){document.title=window.prompt("","hello");})()
I could paste the above into a bookmark manager and then execute.
Starting
When I first started messing about with bookmarklets I used the following code to create them.
I would type the above into the console, or run from a snippet, paste my JavaScript code into the
prompt then copy and paste from the console into the bookmark manager.
48 Alan Richardson
Hacking JavaScript EvilTester.com
• https://github.com/eviltester/bookmarklet
• https://eviltester.github.io/TestingApp/apps/bookmarklet/version/1/bookmarklets.html
Resources:
• https://adrianroselli.com/2015/01/css-bookmarklets-for-testing-and-fixing.html
• http://www.squarefree.com/userstyles/make-bookmarklet.html
• https://lisacrispin.com/2016/07/24/step-comfort-zone/
• https://www.smashingmagazine.com/2010/05/make-your-own-bookmarklets-with-jquery/
• https://eviltester.github.io/TestingApp/apps/bookmarklet/version/1/bookmarklets.html
• https://ted.mielczarek.org/code/mozilla/bookmarklet.html
• http://www.brainjar.com/js/crunch/demo.html
It is possible to use the knowledge of JavaScript you have gained to write Chrome Extensions, and it
might be worth learning more about Extensions to practice in the future.
• https://www.youtube.com/watch?v=Olz4wo-ILwI
Working with Chrome extensions gives you access to a few more APIs to avoid some of the constraints
of cross site scripting.
I have a series of blog posts with videos showing how t create a Chrome Extension:
• eviltester.com/categories/chrome-extension
The tutorial posts above show how to create a Chrome Extension which generates CounterStrings, and
goes through the full process of creating a prototype, building an extension, and releasing it to the
Chrome Store.
Alan Richardson 49
EvilTester.com Hacking JavaScript
Also
I’ve found all of these to be useful ways to learn more, and improve my JavaScript.
50 Alan Richardson
Hacking JavaScript EvilTester.com
Appendices
The sections that follow contain, primarily reference information and links.
Alan Richardson 51
EvilTester.com Hacking JavaScript
I have written a lot of applications which you can use to practice your JavaScript Hacking skills.
Testing Apps
https://eviltester.github.io/TestingApp/
– Console Driver
– Canvas Driver
– The Coloured Square Game
– Number Hover Text Game
– The Coloured Square Changing Game
– The Random Walker Game
– The Grid Walker Game
– The Protect The Square Game
• simple apps
– 7 CharVal
– CounterString Generator
– Bookmarklet Generator
– e-Primer
– iframe Search
– Responsive Test Tool
– Sloganizer
Todo App
This is a simple todo list application created to support my LinkedIn Training course WebDriver Page
Objects and Abstractions.
• Todo App
• https://www.eviltester.com/page/tools/thetodoapp/
See what you can do with it. I recommend trying to automate the creation of test data from the
JavaScript Console.
52 Alan Richardson
Hacking JavaScript EvilTester.com
TLDR; A lot of good resources for learning JavaScript exist. And you do not need to install an IDE, you can
learn JavaScript in the console.
– I can nudge the client side into different states by executing ad-hoc JavaScript through the
console
Learning JavaScript increases the Surface Area of the System that we can pull information from
(i.e. model it), and potentially observe, interrogate and manipulate in more dimensions.
It increases our options, and therefore our ability to handle an increased variety of applications and
technologies.
• My ability to use the JavaScript calls has improved so I don’t have as much trouble with web
sites that don’t play nice
• My CSS selector skills have improved
Clearly for most Selenium automation purposes, we don’t need a large grasp of JavaScript, we mainly
do quick DOM access scripts, the kind of thing you would do through the console for debugging.
Alan Richardson 53
EvilTester.com Hacking JavaScript
https://testautomationu.applitools.com/automating-in-the-browser-using-javascript/
• a free course
• explains how to use the browser dev tools for automating
• https://eloquentjavascript.net/
• Code Sandbox - https://eloquentjavascript.net/code/
Good for understanding the language. And Code Sandbox good for seeing code running.
• https://frontendmasters.com/books/javascript-enlightenment/
• http://speakingjs.com/
54 Alan Richardson
Hacking JavaScript EvilTester.com
• http://domenlightenment.com/
Understand and manipulate the DOM in depth. We will do this a lot when automating from the
browser.
• https://addyosmani.com/resources/essentialjsdesignpatterns/book/
Much of the use of JavaScript will be tactical unless being used as the main language for coding
automating or writing apps. This is important to learn when you start writing more code, especially if
you have to maintain it. And can be useful for helping understand structure of other peoples code.
The support page for my Test Automation U Course (has even more links):
• https://www.eviltester.com/page/onlinetraining/testautomationujs/
• https://gomakethings.com/articles
Alan Richardson 55
EvilTester.com Hacking JavaScript
• https://github.com/eviltester/usefuljssnippetextension
And the benefit is, each time you run a command you see the JS in the console.
Have a look at “JavaScript for Cats”. A tutorial web page, where all the examples and coding take place
in the dev tools. And it has some additional resources for future reading.
• http://jsforcats.com/
This provides a good summary of posts around the web related to JavaScript.
56 Alan Richardson
Hacking JavaScript EvilTester.com
youtu.be/TBQIrqTyT3I
Alan Richardson 57
EvilTester.com Hacking JavaScript
This section will provide a short reference to JavaScript. Not all of JavaScript you understand, just
enough to be dangerous!
All of the code here has been used in the various hacks and testing code samples. So I cover, just
enough to help you understand and implement the various hacks needed.
Console
Click on the ‘Console’ tab and you can start writing JavaScript.
Variables
var debugMode=true;
Operators
-+/*
• ++ to increment a variable
• -- to decrement a variable
58 Alan Richardson
Hacking JavaScript EvilTester.com
Strings
– .split(",")
• parseInt("10") - takes a string and returns an integer, whitespace is ignored, NaN returned if
not a convertable String
– developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/parseInt
Integers
Hex
Math library/Object
• Math.random()
w3schools.com/js/js_math.asp
Alan Richardson 59
EvilTester.com Hacking JavaScript
e.g.
• console.log('Hello');
• console.log(debugMode);
alert("Hello");
But this stops other JavaScript from running until the alert has been dismissed.
Functions
Functions let us create code that we can call at any time we want.
function randomNumberUpTo(theVal){
return Math.floor(Math.random() * theVal)
}
randomNumberUpTo(10);
• This is a function
• called randomNumberUpTo
• it takes a single argument theVal‘
• it uses the JavaScript Match library
• it returns a random number up to the value of theVal
60 Alan Richardson
Hacking JavaScript EvilTester.com
Iteration
for Loops
for(x=0;x<100;x++){
console.log("line " + x);
}
– log to the console "line " with x appended e.g. ‘line 0’, ‘line 1’
Arrays
Position Index
– colours.length===5
– colours[colours.length-1]==="black"
Alan Richardson 61
EvilTester.com Hacking JavaScript
Key Indexed
• Objects {}
• Arrays []
if statements
var debugMode=true;
if(debugMode===true){
console.log("debug mode is on");
}else{
console.log("debug mode is not on");
}
62 Alan Richardson
Hacking JavaScript EvilTester.com
clearInterval(sloganbot)
Finding Elements
• getElementById
• getElementsByClassName
• getElementsByName
• getElementsByTagName
• querySelector
• querySelectorAll
document.getElementById("theSquare").style.backgroundColor = "red";
Hiding an element:
document.getElementById("theSquare").style.display="none"
Alan Richardson 63
EvilTester.com Hacking JavaScript
document.getElementsByClassName("title")[0].
setAttribute("style","display:none");
document.getElementsByClassName("title")[0].
getAttribute("style");
elem.innerHTML = "Hello";
<div class="title">
<button class="title" onclick="changeSlogan()">I Want A Slogan</button
>
</div>
onclick="changeSlogan()"
var theButton=document.getElementsByClassName("title")[2];
theButton.onclick = function() {
alert('hello');
};
var theButton=document.getElementsByClassName("title")[2];
theButton.onclick = null;
theButton.addEventListener("click", function(){
alert('from adding event');
}, false);
• false is for ‘useCapture’ - true for capturing phase, false (default) for bubbling phase
• ‘useCapture’ is optional
var theButton=document.getElementsByClassName("title")[2];
theButton.onclick = null;
64 Alan Richardson
Hacking JavaScript EvilTester.com
Tutorials
• w3schools.com/js
• Mozilla Developer Network Javascript
• htmldog.com/guides/javascript
• learn-js.org
References
• w3schools.com/jsref
Alan Richardson 65
EvilTester.com Hacking JavaScript
General Tips
• Enter Immediate JavaScript commands by typing a function name followed by () to call the
function
– if the function takes arguments then add them between () e.g. (arg1, arg2)
• Typing a function name at the console without () will tell you information about the function
but will not call it
• Add code to the running application by creating variables or functions from the console - don’t
use the same names as the existing app, unless you want to overwrite the app code
• Console can be used in any of the Dev tools tabs by pressing esc
• when you get the developer console up, sometimes you’ll have to refresh the page, when the
console is up, to have access to the game objects
• code completion in the console can help identify functions on objects
• type object names into the console for a tree view of the variables and methods
• always assign setInterval to a variable so you can switch it off when you need to
• use jsbeautifier.org when writing code
• use jscompress.com to make it a one liner
• use jslint.com to help identify errors
66 Alan Richardson
Hacking JavaScript EvilTester.com
Alan Richardson has more than twenty years of professional IT experience, working as a Programmer,
in Marketing and Developer Relations and at every level of the testing hierarchy from Tester through to
Head of Testing.
Author of the books “Dear Evil Tester”, “Automating and Testing a REST API”, “Java For Testers” and “Se-
lenium Simplified”. Alan also has created online training courses to help people learn Java, JavaScript,
Technical Web Testing and Selenium WebDriver with Java.
• EvilTester.com,
• CompendiumDev.co.uk.
• Linkedin - linkedin.com/in/eviltester
• Twitter - twitter.com/eviltester
• Github - github.com/eviltester
• Youtube - youtube.com/c/eviltester
• Instagram - instagram.com/eviltester
• Facebook - facebook.com/eviltester
• Pinterest - pinterest.com/eviltester
• https://www.eviltester.com/page/emaillist
And if you are serious about improving your craft and want exclusive daily posts then join the Evil Tester
Patreon Programme and gain access to exclusive posts, videos and courses:
• https://www.patreon.com/eviltester
Alan Richardson 67