|
1 |
| -var child_process = require('child_process'), |
2 |
| - q = require('q'), |
3 |
| - net = require('net'); |
| 1 | +const child_process = require('child_process'); |
| 2 | +const net = require('net'); |
4 | 3 |
|
5 |
| -var TIMEOUT = 10000; |
| 4 | +const TIMEOUT = 10000; |
6 | 5 |
|
7 | 6 | // An instance of a protractor debugger server.
|
8 |
| -var Server = function(serverStartCmd, port) { |
| 7 | +class Server { |
| 8 | + constructor(command, port) { |
| 9 | + this.command = command; |
| 10 | + this.port = port; |
| 11 | + } |
9 | 12 | // Start protractor and its debugger server as a child process.
|
10 |
| - this.start = function() { |
11 |
| - var deferred = q.defer(); |
12 |
| - var received = ''; |
13 |
| - |
14 |
| - serverStartCmd += ' --debuggerServerPort ' + port; |
15 |
| - serverStartCmd = serverStartCmd.split(/\s/); |
16 |
| - var test_process = child_process.spawn(serverStartCmd[0], |
17 |
| - serverStartCmd.slice(1)); |
18 |
| - |
19 |
| - var timeoutObj = setTimeout(function() { |
20 |
| - var errMsg = 'Did not start interactive server in ' + TIMEOUT/1000 + 's.'; |
21 |
| - if (received) { |
22 |
| - errMsg += ' Server startup output: ' + received; |
23 |
| - } |
24 |
| - deferred.reject(errMsg); |
25 |
| - }, TIMEOUT); |
26 |
| - |
27 |
| - test_process.stdout.on('data', function(data) { |
28 |
| - received += data; |
29 |
| - if (received.indexOf('Server listening on 127.0.0.1:' + port) >= 0) { |
30 |
| - clearTimeout(timeoutObj); |
31 |
| - // Add a small time for browser to get ready |
32 |
| - setTimeout(deferred.resolve, 2000); |
33 |
| - } |
34 |
| - }); |
| 13 | + start() { |
| 14 | + return new Promise((resolve, reject) => { |
| 15 | + let received = ''; |
| 16 | + |
| 17 | + const commands = `${this.command} --debuggerServerPort ${this.port}`.split(/\s/); |
| 18 | + const command = commands[0]; |
| 19 | + const args = commands.slice(1); |
| 20 | + const test_process = child_process.spawn(command, args); |
| 21 | + |
| 22 | + const timeout = setTimeout(() => { |
| 23 | + let errorMessage = `Did not start interactive server in ${TIMEOUT/1000}s.`; |
| 24 | + if (received) { |
| 25 | + errorMessage += ` Server startup output: ${received}`; |
| 26 | + } |
| 27 | + reject(errorMessage); |
| 28 | + }, TIMEOUT); |
| 29 | + |
| 30 | + test_process.stdout.on('data', (data) => { |
| 31 | + received += data; |
| 32 | + if (received.indexOf(`Server listening on 127.0.0.1:${this.port}`) !== -1) { |
| 33 | + clearTimeout(timeout); |
| 34 | + // Add a small time for browser to get ready |
| 35 | + setTimeout(resolve(), 2000); |
| 36 | + } |
| 37 | + }); |
35 | 38 |
|
36 |
| - test_process.stderr.on('data', function(data) { |
37 |
| - received += data; |
| 39 | + test_process.stderr.on('data', (data) => { |
| 40 | + received += data; |
| 41 | + }); |
38 | 42 | });
|
39 |
| - |
40 |
| - return deferred.promise; |
41 |
| - }; |
42 |
| -}; |
43 |
| - |
44 |
| -// A client to attach to Protractor's debugger server and exchange data. |
45 |
| -var Client = function(port) { |
46 |
| - var socket; |
47 |
| - |
48 |
| - // Connect to the server. |
49 |
| - this.connect = function() { |
50 |
| - var deferred = q.defer(); |
51 |
| - socket = net.connect({port: port}, function() { |
52 |
| - deferred.resolve(); |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +// A client to attach to Protractor's debugger server and exchange data. |
| 47 | +class Client { |
| 48 | + constructor(port) { |
| 49 | + this.port = port; |
| 50 | + this.socket = undefined; |
| 51 | + } |
| 52 | + |
| 53 | + // Connect to the server. |
| 54 | + connect() { |
| 55 | + return new Promise(resolve => { |
| 56 | + this.socket = net.connect({port: this.port}, () => { |
| 57 | + resolve(); |
| 58 | + }); |
53 | 59 | });
|
54 |
| - return deferred.promise; |
55 |
| - }; |
| 60 | + } |
56 | 61 |
|
57 | 62 | // Disconnect from the server.
|
58 |
| - this.disconnect = function() { |
59 |
| - socket.end(); |
60 |
| - }; |
61 |
| - |
62 |
| - // Send a command to the server and wait for a response. Return response as a |
63 |
| - // promise. |
64 |
| - this.sendCommand = function(cmd) { |
65 |
| - var deferred = q.defer(); |
66 |
| - var received = ''; |
67 |
| - var timeoutObj = setTimeout(function() { |
68 |
| - var errMsg = 'Command <' + JSON.stringify(cmd) + |
69 |
| - '> did not receive a response in ' + TIMEOUT/1000 + 's.'; |
70 |
| - if (received) { |
71 |
| - errMsg += ' Received messages so far: ' + received; |
72 |
| - } |
73 |
| - deferred.reject(errMsg); |
74 |
| - }, TIMEOUT); |
75 |
| - |
76 |
| - var ondata = function(data) { |
77 |
| - received += data.toString(); |
78 |
| - var i = received.indexOf('\r\n'); |
79 |
| - if (i >= 0) { |
80 |
| - clearTimeout(timeoutObj); |
81 |
| - var response = received.substring(0, i).trim(); |
82 |
| - deferred.resolve(response); |
83 |
| - } |
84 |
| - }; |
85 |
| - socket.on('data', ondata); |
86 |
| - |
87 |
| - var onerror = function(data) { |
88 |
| - deferred.reject('Received error: ' + data); |
89 |
| - }; |
90 |
| - socket.on('error', onerror); |
91 |
| - |
92 |
| - socket.write(cmd + '\r\n'); |
93 |
| - return deferred.promise.fin(function() { |
94 |
| - clearTimeout(timeoutObj); |
95 |
| - socket.removeListener('data', ondata); |
96 |
| - socket.removeListener('error', onerror); |
| 63 | + disconnect() { |
| 64 | + this.socket.end(); |
| 65 | + } |
| 66 | + |
| 67 | + // Send a command to the server and wait for a response. Return response as a |
| 68 | + // promise. |
| 69 | + sendCommand(command) { |
| 70 | + let timeout; |
| 71 | + let ondata; |
| 72 | + let onerror; |
| 73 | + |
| 74 | + return new Promise((resolve, reject) => { |
| 75 | + let received = ''; |
| 76 | + timeout = setTimeout(() => { |
| 77 | + let errorMessage = `Command ${JSON.stringify(command)} did not receive a response in ${TIMEOUT/1000}s.`; |
| 78 | + if (received) { |
| 79 | + errorMessage += ` Received messages so far: ${received}`; |
| 80 | + } |
| 81 | + reject(errorMessage); |
| 82 | + }, TIMEOUT); |
| 83 | + |
| 84 | + ondata = (data) => { |
| 85 | + received += data.toString(); |
| 86 | + let i = received.indexOf('\r\n'); |
| 87 | + if (i !== -1) { |
| 88 | + clearTimeout(timeout); |
| 89 | + const response = received.substring(0, i).trim(); |
| 90 | + resolve(response); |
| 91 | + } |
| 92 | + }; |
| 93 | + this.socket.on('data', ondata); |
| 94 | + |
| 95 | + onerror = (data) => { |
| 96 | + reject(`Received error: ${data}`); |
| 97 | + }; |
| 98 | + this.socket.on('error', onerror); |
| 99 | + |
| 100 | + this.socket.write(`${command}\r\n`); |
| 101 | + }).finally(() => { |
| 102 | + clearTimeout(timeout); |
| 103 | + this.socket.removeListener('data', ondata); |
| 104 | + this.socket.removeListener('error', onerror); |
97 | 105 | });
|
98 |
| - }; |
99 |
| -}; |
| 106 | + } |
| 107 | +} |
100 | 108 |
|
101 | 109 | /**
|
102 | 110 | * Util for running an interactive Protractor test.
|
103 | 111 | */
|
104 |
| -exports.InteractiveTest = function(interactiveServerStartCmd, port) { |
105 |
| - var expectations = []; |
106 |
| - |
107 |
| - // Adds a command to send as well as the response to verify against. |
| 112 | +module.exports = class InteractiveTest { |
| 113 | + constructor(command, port) { |
| 114 | + this.command = command; |
| 115 | + this.port = port; |
| 116 | + this.expectations = []; |
| 117 | + } |
| 118 | + |
| 119 | + // Adds a command to send as well as the response to verify against. |
108 | 120 | // If opt_expectedResult is undefined, the test will still wait for the server
|
109 | 121 | // to respond after sending the command, but will not verify against it.
|
110 |
| - // Note, this does not actually interact with the server, but simply adds the |
| 122 | + // Note, this does not actually interact with the server, but simply adds the |
111 | 123 | // command to a queue.
|
112 |
| - this.addCommandExpectation = function(command, opt_expectedResult) { |
113 |
| - expectations.push({ |
| 124 | + addCommandExpectation(command, opt_expectedResult) { |
| 125 | + this.expectations.push({ |
114 | 126 | command: command,
|
115 | 127 | expectedResult: opt_expectedResult
|
116 | 128 | });
|
117 |
| - }; |
| 129 | + } |
118 | 130 |
|
119 | 131 | // Execute the interactive test. This will first start Protractor and its
|
120 |
| - // debugger server. Then it will connect to the server. Finally, it will |
| 132 | + // debugger server. Then it will connect to the server. Finally, it will |
121 | 133 | // send the queue of commands against the server sequentially and verify the
|
122 |
| - // response from the server if needed. |
123 |
| - this.run = function() { |
124 |
| - var server = new Server(interactiveServerStartCmd, port); |
125 |
| - return server.start().then(function() { |
126 |
| - var client = new Client(port); |
127 |
| - return client.connect().then(function() { |
128 |
| - var verifyAll = function(i) { |
129 |
| - if (i < expectations.length) { |
130 |
| - var expectedResult = expectations[i].expectedResult; |
131 |
| - var command = expectations[i].command; |
132 |
| - return client.sendCommand(command).then(function(response) { |
133 |
| - if (expectedResult !== undefined && expectedResult !== response) { |
134 |
| - throw ('Command <' + JSON.stringify(command) + '> received: ' + |
135 |
| - response + ', but expects: ' + expectedResult); |
136 |
| - } else { |
137 |
| - return verifyAll(i + 1); |
138 |
| - } |
139 |
| - }); |
140 |
| - } |
141 |
| - }; |
142 |
| - return verifyAll(0); |
143 |
| - }).fin(function() { |
144 |
| - // '^]' This is the term signal. |
145 |
| - client.sendCommand(String.fromCharCode(0x1D)); |
146 |
| - client.disconnect(); |
147 |
| - }); |
148 |
| - }).done(); |
149 |
| - }; |
| 134 | + // response from the server if needed. |
| 135 | + async run() { |
| 136 | + let failed = false; |
| 137 | + let successfulCommands = []; |
| 138 | + let failedCommands = []; |
| 139 | + |
| 140 | + const server = new Server(this.command, this.port); |
| 141 | + await server.start(); |
| 142 | + const client = new Client(this.port); |
| 143 | + await client.connect(); |
| 144 | + for (let expectation of this.expectations) { |
| 145 | + const expectedResult = expectation.expectedResult; |
| 146 | + const command = expectation.command; |
| 147 | + const response = await client.sendCommand(command); |
| 148 | + if (expectedResult !== undefined && expectedResult !== response) { |
| 149 | + failed = true; |
| 150 | + successfulCommands.push( |
| 151 | + `Command ${JSON.stringify(command)} received: ${response}, but expects: ${expectedResult}\n` |
| 152 | + ); |
| 153 | + } else { |
| 154 | + failedCommands.push('Command response as expected\n'); |
| 155 | + } |
| 156 | + } |
| 157 | + console.log('Successful commands: '); |
| 158 | + for (let command of successfulCommands) { |
| 159 | + console.log(command); |
| 160 | + } |
| 161 | + console.log('Failed commands: '); |
| 162 | + for (let command of failedCommands) { |
| 163 | + console.log(command); |
| 164 | + } |
| 165 | + console.log('Summary: ' + (failed ? 'fail' : 'pass')); |
| 166 | + await client.sendCommand(String.fromCharCode(0x1D)); |
| 167 | + await client.disconnect(); |
| 168 | + } |
150 | 169 | };
|
0 commit comments