Debug a web app on iPhone without a Mac

A fun project to get started with web sockets on NodeJS.

If you own an iPhone and you are a developer, most likely, you own a Mac too.
If you need to get back to work, go directly here.
But if you like nerding around, working out your own solution keep reading.

Still with me? Good!

This is my story. At my workplace, I have to test our product on iPhone and iPad. We have Windows 10 workstations and a single Mac just for testing. In addition I’m a hardcore Linux user: I hate OSX user interface and I hate Windows console. So, the testing phase was all a coding, walk-to-the-mac, check the console output and back to the workstation. Even using VNC wasn’t fun as I had to interact with the iPhone while plugged (and 8 meters of USB cable did not seem an intelligent solution).

From here the idea. A very simple and not really original one: hijack the calls on the console methods of the client to a listening web socket running on my machine and display them. Easy, no?

The server

If you don’t have it already, install Node JS.

Create a folder, open a terminal at that path and initiate a new project:
npm init 
Install the websocket library we are going to use:
npm install ws --save 
And create an empty .js file, index.js will do.

The code for the server will be the following:

const WebSocket = require('ws')
const ws = new WebSocket.Server({ host: '0.0.0.0', port: 9999 })
ws.on('connection', socket => {
console.log(' - new connection')
socket.on('message', function(message) {
console.log(message)
})
socket.on('close', error => {
console.log(' - connection closed - ', error)
socket.close()
})
})

Yep. That’s it. We import the library and create a new socket which will be listening to any IP; so that you can reach it from your local net easily. You can put there a specific IP address if you need to.

When the socket gets a connection, it will then wait for incoming messages and simply display them. And will also close the connection when needed.

Ok. Get back to the console and run it: node index.js nothing should happen. If you don’t get any error, then the socket is working and waiting for a connection.

The Client

We need a client to test the socket. This is what we have to do:

  • install a simple HTTP server: npm install http-server -g
  • create a index.html file
  • a web socket client instance connecting to our server

To do that, we assign our method to console.log and we place our code at the very top of the <head> tag:

<script>
(function() {
const hostIP = location.host.split(':')[0]
const ws = new WebSocket('ws://' + hostIP + ':9999')
ws.onopen = function() {
console.info('WS: connected')
}
const localLog = console.log
console.log = function (...message) {
const data = message.join(' ')
ws.send(data)
localLog.apply(console, arguments)
}
})();
</script>

Run the http-server from the folder where you’ve save the index.html and call from a browser one of the ip addresses suggested by the http-server application.

A white webpage should appear (or with whatever you’ve put there). Open the developers tools of the browser, and on the console panel input: console.log('hello world!') — hit enter.

BAM. Your message is displayed by the server. Copy the client script into the page you need to debug, open it from a phone and happy working.

Homeworks

From here you can hack your way by:

  • handle more output functions (f.i. error, warn)
  • use colors on the server output
  • use a polyfill on the client for those phones that do not support ES6 yet (I’m looking at you iOS9)

This is brilliant, but I need to get back to work

You can find a working tool on NPM https://www.npmjs.com/package/mirrorconsole