mirror of
https://github.com/ZwareBear/awx.git
synced 2026-04-18 22:11:49 -05:00
Adds network UI test framework
This adds a test framework to drive UI tests from the client instead of injecting events from the websocket. Tests consist of a pair of snapshots (before and after the test) and a list of UI events to process. Tests are run using a FSM in the client that controls the resetting of state to the snapshot, injecting the events into the UI, recording test coverage, and reporting tests to the server. * Adds design for event trace table * Adds design for a coverage tracking table * Adds models for EventTrace and Coverage * Adds trace_id to recording messages * Adds design for TopologySnapshot table * Adds order to TopologySnapshot table * Adds TopologySnapshot table * Adds Snapshot message when recordings are started and stoppped * Adds models for tracking test cases and test results * Adds designs for a test runner FSM * Updates test management commands with new schema * Adds download recording button * Adds models to track tests * Adds ui test runner * Adds id and client to TestResult design * Adds id and client to TestResult * Update message types * Stores test results and code coverage from the test runner * Adds tool to generate a test coverage report * Adds APIs for tests and code coverage * Adds per-test-case coverage reports * Breaks out coverage for loading the modules from the tests * Re-raises server-side errors * Captures errors during tests * Adds defaults for host name and host type * Disables test FSM trace storage * Adds support for sending server error message to the client * Resets the UI flags, history, and toolbox contents between tests * Adds istanbul instrumentation to network-ui
This commit is contained in:
@@ -15,6 +15,7 @@ var stream_fsm = require('./stream.fsm.js');
|
||||
var group = require('./group.js');
|
||||
var buttons = require('./buttons.js');
|
||||
var time = require('./time.js');
|
||||
var test_fsm = require('./test.fsm.js');
|
||||
var util = require('./util.js');
|
||||
var models = require('./models.js');
|
||||
var messages = require('./messages.js');
|
||||
@@ -22,7 +23,7 @@ var svg_crowbar = require('./svg-crowbar.js');
|
||||
var ReconnectingWebSocket = require('reconnectingwebsocket');
|
||||
|
||||
var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$q, $state, ProcessErrors) {
|
||||
$q, $state, ProcessErrors, ConfigService) {
|
||||
|
||||
window.scope = $scope;
|
||||
var i = 0;
|
||||
@@ -96,6 +97,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.group_id_seq = util.natural_numbers(0);
|
||||
$scope.message_id_seq = util.natural_numbers(0);
|
||||
$scope.stream_id_seq = util.natural_numbers(0);
|
||||
$scope.test_result_id_seq = util.natural_numbers(0);
|
||||
$scope.overall_toolbox_collapsed = false;
|
||||
$scope.time_pointer = -1;
|
||||
$scope.frame = 0;
|
||||
@@ -108,6 +110,14 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.groups = [];
|
||||
$scope.processes = [];
|
||||
$scope.configurations = [];
|
||||
$scope.tests = [];
|
||||
$scope.current_tests = [];
|
||||
$scope.current_test = null;
|
||||
$scope.testing = false;
|
||||
$scope.version = null;
|
||||
$scope.test_events = [];
|
||||
$scope.test_results = [];
|
||||
$scope.test_errors = [];
|
||||
$scope.streams = [];
|
||||
$scope.view_port = {'x': 0,
|
||||
'y': 0,
|
||||
@@ -118,7 +128,9 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.trace_id = $scope.trace_id_seq();
|
||||
|
||||
$scope.send_trace_message = function (message) {
|
||||
console.log(message);
|
||||
if (!$scope.recording) {
|
||||
return;
|
||||
}
|
||||
message.sender = $scope.client_id;
|
||||
message.trace_id = $scope.trace_id;
|
||||
message.message_id = $scope.message_id_seq();
|
||||
@@ -148,6 +160,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.site_controller = new fsm.FSMController($scope, "site_fsm", site_fsm.Disable, $scope);
|
||||
$scope.buttons_controller = new fsm.FSMController($scope, "buttons_fsm", buttons.Start, $scope);
|
||||
$scope.time_controller = new fsm.FSMController($scope, "time_fsm", time.Start, $scope);
|
||||
$scope.test_controller = new fsm.FSMController($scope, "test_fsm", test_fsm.Start, $scope);
|
||||
$scope.app_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope);
|
||||
|
||||
//App Toolbox Setup
|
||||
@@ -185,6 +198,12 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
let host = hosts[i];
|
||||
console.log(host);
|
||||
host.data = jsyaml.safeLoad(host.variables);
|
||||
if (host.data.type == undefined) {
|
||||
host.data.type = 'unknown';
|
||||
}
|
||||
if (host.data.name == undefined) {
|
||||
host.data.name = host.name;
|
||||
}
|
||||
var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
|
||||
device.icon = true;
|
||||
$scope.inventory_toolbox.items.push(device);
|
||||
@@ -288,9 +307,13 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.mode_controller.delegate_channel = new fsm.Channel($scope.mode_controller,
|
||||
$scope.time_controller,
|
||||
$scope);
|
||||
$scope.test_controller.delegate_channel = new fsm.Channel($scope.test_controller,
|
||||
$scope.mode_controller,
|
||||
$scope);
|
||||
|
||||
|
||||
$scope.first_channel = new fsm.Channel(null,
|
||||
$scope.mode_controller,
|
||||
$scope.test_controller,
|
||||
$scope);
|
||||
|
||||
var getMouseEventResult = function (mouseEvent) {
|
||||
@@ -464,7 +487,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.onMouseDown = function ($event) {
|
||||
$scope.normalize_mouse_event($event);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type));
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
||||
}
|
||||
$scope.last_event = $event;
|
||||
$scope.first_channel.send('MouseDown', $event);
|
||||
@@ -475,7 +498,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.onMouseUp = function ($event) {
|
||||
$scope.normalize_mouse_event($event);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type));
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
||||
}
|
||||
$scope.last_event = $event;
|
||||
$scope.first_channel.send('MouseUp', $event);
|
||||
@@ -486,7 +509,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.onMouseLeave = function ($event) {
|
||||
$scope.normalize_mouse_event($event);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type));
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
||||
}
|
||||
$scope.onMouseLeaveResult = getMouseEventResult($event);
|
||||
$scope.cursor.hidden = true;
|
||||
@@ -496,7 +519,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.onMouseMove = function ($event) {
|
||||
$scope.normalize_mouse_event($event);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type));
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
||||
}
|
||||
//var coords = getCrossBrowserElementCoords($event);
|
||||
$scope.cursor.hidden = false;
|
||||
@@ -513,7 +536,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$scope.onMouseOver = function ($event) {
|
||||
$scope.normalize_mouse_event($event);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type));
|
||||
$scope.send_control_message(new messages.MouseEvent($scope.client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
||||
}
|
||||
$scope.onMouseOverResult = getMouseEventResult($event);
|
||||
$scope.cursor.hidden = false;
|
||||
@@ -529,11 +552,11 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
var deltaY = $event.deltaY;
|
||||
// console.log([$event, delta, deltaX, deltaY]);
|
||||
if ($scope.recording) {
|
||||
$scope.send_control_message(new messages.MouseWheelEvent($scope.client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey));
|
||||
$scope.send_control_message(new messages.MouseWheelEvent($scope.client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey, $scope.trace_id));
|
||||
}
|
||||
$scope.last_event = $event;
|
||||
$scope.first_channel.send('MouseWheel', [$event, delta, deltaX, deltaY]);
|
||||
event.preventDefault();
|
||||
$event.preventDefault();
|
||||
};
|
||||
|
||||
$scope.onKeyDown = function ($event) {
|
||||
@@ -545,7 +568,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
$event.altKey,
|
||||
$event.shiftKey,
|
||||
$event.ctrlKey,
|
||||
$event.metaKey));
|
||||
$event.metaKey,
|
||||
$scope.trace_id));
|
||||
}
|
||||
$scope.last_event = $event;
|
||||
$scope.last_key = $event.key;
|
||||
@@ -653,6 +677,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
};
|
||||
|
||||
$scope.onRenameContextButton = function (button) {
|
||||
console.log(button.name);
|
||||
$scope.context_menus[0].enabled = false;
|
||||
$scope.first_channel.send("LabelEdit", {});
|
||||
};
|
||||
@@ -690,14 +715,31 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
console.log(button.name);
|
||||
$scope.recording = ! $scope.recording;
|
||||
if ($scope.recording) {
|
||||
$scope.trace_id = $scope.trace_id_seq();
|
||||
$scope.send_control_message(new messages.MultipleMessage($scope.client_id,
|
||||
[new messages.StartRecording($scope.client_id),
|
||||
[new messages.StartRecording($scope.client_id, $scope.trace_id),
|
||||
new messages.ViewPort($scope.client_id,
|
||||
$scope.current_scale,
|
||||
$scope.panX,
|
||||
$scope.panY)]));
|
||||
$scope.panY,
|
||||
$scope.trace_id),
|
||||
new messages.Snapshot($scope.client_id,
|
||||
$scope.devices,
|
||||
$scope.links,
|
||||
$scope.groups,
|
||||
$scope.streams,
|
||||
0,
|
||||
$scope.trace_id)]));
|
||||
} else {
|
||||
$scope.send_control_message(new messages.StopRecording($scope.client_id));
|
||||
$scope.send_control_message(new messages.MultipleMessage($scope.client_id,
|
||||
[new messages.Snapshot($scope.client_id,
|
||||
$scope.devices,
|
||||
$scope.links,
|
||||
$scope.groups,
|
||||
$scope.streams,
|
||||
1,
|
||||
$scope.trace_id),
|
||||
new messages.StopRecording($scope.client_id, $scope.trace_id)]));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -789,6 +831,25 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
console.log(button.label);
|
||||
window.open("/network_ui/download_trace?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.client_id);
|
||||
};
|
||||
|
||||
$scope.onDownloadRecordingButton = function (button) {
|
||||
console.log(button.label);
|
||||
window.open("/network_ui/download_recording?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.client_id);
|
||||
};
|
||||
|
||||
$scope.onUploadTestButton = function (button) {
|
||||
console.log(button.name);
|
||||
window.open("/network_ui/upload_test", "_top");
|
||||
};
|
||||
|
||||
$scope.onRunTestsButton = function (button) {
|
||||
console.log(button.name);
|
||||
|
||||
$scope.test_results = [];
|
||||
$scope.current_tests = $scope.tests.slice();
|
||||
$scope.first_channel.send("EnableTest", new messages.EnableTest());
|
||||
};
|
||||
|
||||
// Buttons
|
||||
var button_offset = 200;
|
||||
|
||||
@@ -802,6 +863,9 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
new models.Button("CONFIGURE", button_offset + 520, 48, 90, 30, $scope.onConfigureButton, $scope),
|
||||
new models.Button("EXPORT YAML", button_offset + 620, 48, 120, 30, $scope.onExportYamlButton, $scope),
|
||||
new models.Button("DOWNLOAD TRACE", button_offset + 750, 48, 150, 30, $scope.onDownloadTraceButton, $scope),
|
||||
new models.Button("DOWNLOAD RECORDING", button_offset + 910, 48, 170, 30, $scope.onDownloadRecordingButton, $scope),
|
||||
new models.Button("UPLOAD TEST", button_offset + 10, 88, 100, 30, $scope.onUploadTestButton, $scope),
|
||||
new models.Button("RUN TESTS", button_offset + 120, 88, 100, 30, $scope.onRunTestsButton, $scope),
|
||||
];
|
||||
|
||||
var LAYERS_X = 160;
|
||||
@@ -1429,6 +1493,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
//Erase the existing state
|
||||
$scope.devices = [];
|
||||
$scope.links = [];
|
||||
$scope.groups = [];
|
||||
$scope.streams = [];
|
||||
|
||||
var device_map = {};
|
||||
var device_interface_map = {};
|
||||
@@ -1634,12 +1700,6 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
}
|
||||
};
|
||||
|
||||
$scope.send_coverage = function () {
|
||||
console.log("Sending coverage");
|
||||
if (typeof(window.__coverage__) !== "undefined" && window.__coverage__ !== null) {
|
||||
$scope.send_control_message(new messages.Coverage($scope.client_id, window.__coverage__));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.control_socket.onmessage = function(message) {
|
||||
@@ -1743,6 +1803,112 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
|
||||
map.set(key, stream.offset + 1);
|
||||
}
|
||||
};
|
||||
|
||||
setInterval( function () {
|
||||
var test_event = null;
|
||||
if ($scope.test_events.length > 0) {
|
||||
test_event = $scope.test_events.shift();
|
||||
console.log(test_event);
|
||||
test_event.sender = 0;
|
||||
try {
|
||||
$scope.first_channel.send(test_event.msg_type, test_event);
|
||||
} catch (err) {
|
||||
$scope.test_errors.push(err);
|
||||
}
|
||||
}
|
||||
$scope.$apply();
|
||||
}, 10);
|
||||
|
||||
ConfigService
|
||||
.getConfig()
|
||||
.then(function(config){
|
||||
$scope.version = config.version;
|
||||
});
|
||||
|
||||
$scope.reset_coverage = function() {
|
||||
var i = null;
|
||||
var coverage = null;
|
||||
var f = null;
|
||||
if (typeof(window.__coverage__) !== "undefined" && window.__coverage__ !== null) {
|
||||
for (f in window.__coverage__) {
|
||||
coverage = window.__coverage__[f];
|
||||
for (i in coverage.b) {
|
||||
coverage.b[i] = [0, 0];
|
||||
}
|
||||
for (i in coverage.f) {
|
||||
coverage.f[i] = 0;
|
||||
}
|
||||
for (i in coverage.s) {
|
||||
coverage.s[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.reset_flags = function () {
|
||||
$scope.debug = {'hidden': true};
|
||||
$scope.hide_buttons = false;
|
||||
$scope.hide_links = false;
|
||||
$scope.hide_interfaces = false;
|
||||
$scope.hide_groups = false;
|
||||
};
|
||||
|
||||
|
||||
$scope.reset_fsm_state = function () {
|
||||
$scope.null_controller.state = null_fsm.Start;
|
||||
$scope.null_controller.state.start($scope.null_controller);
|
||||
$scope.hotkeys_controller.state = hotkeys.Start;
|
||||
$scope.hotkeys_controller.state.start($scope.hotkeys_controller);
|
||||
$scope.view_controller.state = view.Start;
|
||||
$scope.view_controller.state.start($scope.view_controller);
|
||||
$scope.device_detail_controller.state = device_detail_fsm.Start;
|
||||
$scope.device_detail_controller.state.start($scope.device_detail_controller);
|
||||
$scope.move_controller.state = move.Start;
|
||||
$scope.move_controller.state.start($scope.move_controller);
|
||||
$scope.link_controller.state = link.Start;
|
||||
$scope.link_controller.state.start($scope.link_controller);
|
||||
$scope.stream_controller.state = stream_fsm.Start;
|
||||
$scope.stream_controller.state.start($scope.stream_controller);
|
||||
$scope.group_controller.state = group.Start;
|
||||
$scope.group_controller.state.start($scope.group_controller);
|
||||
$scope.rack_controller.state = rack_fsm.Disable;
|
||||
$scope.rack_controller.state.start($scope.rack_controller);
|
||||
$scope.site_controller.state = site_fsm.Disable;
|
||||
$scope.site_controller.state.start($scope.site_controller);
|
||||
$scope.buttons_controller.state = buttons.Start;
|
||||
$scope.buttons_controller.state.start($scope.buttons_controller);
|
||||
$scope.time_controller.state = time.Start;
|
||||
$scope.time_controller.state.start($scope.time_controller);
|
||||
$scope.app_toolbox_controller.state = toolbox_fsm.Start;
|
||||
$scope.app_toolbox_controller.state.start($scope.app_toolbox_controller);
|
||||
$scope.inventory_toolbox_controller.state = toolbox_fsm.Start;
|
||||
$scope.inventory_toolbox_controller.state.start($scope.inventory_toolbox_controller);
|
||||
$scope.rack_toolbox_controller.state = toolbox_fsm.Start;
|
||||
$scope.rack_toolbox_controller.state.start($scope.rack_toolbox_controller);
|
||||
$scope.site_toolbox_controller.state = toolbox_fsm.Start;
|
||||
$scope.site_toolbox_controller.state.start($scope.site_toolbox_controller);
|
||||
$scope.mode_controller.state = mode_fsm.Start;
|
||||
$scope.mode_controller.state.start($scope.mode_controller);
|
||||
};
|
||||
|
||||
$scope.reset_history = function () {
|
||||
$scope.history = [];
|
||||
};
|
||||
|
||||
$scope.reset_toolboxes = function () {
|
||||
$scope.app_toolbox.items = [];
|
||||
$scope.app_toolbox.items.push(new models.Process(0, 'BGP', 'process', 0, 0));
|
||||
$scope.app_toolbox.items.push(new models.Process(0, 'OSPF', 'process', 0, 0));
|
||||
$scope.app_toolbox.items.push(new models.Process(0, 'STP', 'process', 0, 0));
|
||||
$scope.app_toolbox.items.push(new models.Process(0, 'Zero Pipeline', 'process', 0, 0));
|
||||
|
||||
for(i = 0; i < $scope.app_toolbox.items.length; i++) {
|
||||
$scope.app_toolbox.items[i].icon = true;
|
||||
}
|
||||
$scope.inventory_toolbox.items = [];
|
||||
$scope.rack_toolbox.items = [];
|
||||
$scope.site_toolbox.items = [];
|
||||
};
|
||||
};
|
||||
|
||||
exports.NetworkUIController = NetworkUIController;
|
||||
|
||||
Reference in New Issue
Block a user