aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]server/sonar-web/src/main/js/libs/third-party/jquery.mockjax.js451
-rw-r--r--server/sonar-web/test/helpers/test-page.js20
-rw-r--r--server/sonar-web/test/intern.js3
-rw-r--r--server/sonar-web/test/medium/base.html2
-rw-r--r--server/sonar-web/test/medium/coding-rules.spec.js924
-rw-r--r--server/sonar-web/test/medium/computation.spec.js2
-rwxr-xr-xtravis.sh2
7 files changed, 1263 insertions, 141 deletions
diff --git a/server/sonar-web/src/main/js/libs/third-party/jquery.mockjax.js b/server/sonar-web/src/main/js/libs/third-party/jquery.mockjax.js
index fc6327fd1c1..b935290ff58 100644..100755
--- a/server/sonar-web/src/main/js/libs/third-party/jquery.mockjax.js
+++ b/server/sonar-web/src/main/js/libs/third-party/jquery.mockjax.js
@@ -1,15 +1,51 @@
-(function($) {
+/*! jQuery Mockjax
+ * A Plugin providing simple and flexible mocking of ajax requests and responses
+ *
+ * Version: 2.0.1
+ * Home: https://github.com/jakerella/jquery-mockjax
+ * Copyright (c) 2015 Jordan Kasper, formerly appendTo;
+ * NOTE: This repository was taken over by Jordan Kasper (@jakerella) October, 2014
+ *
+ * Dual licensed under the MIT or GPL licenses.
+ * http://opensource.org/licenses/MIT OR http://www.gnu.org/licenses/gpl-2.0.html
+ */
+(function(root, factory) {
+ 'use strict';
+
+ // AMDJS module definition
+ if ( typeof define === 'function' && define.amd && define.amd.jQuery ) {
+ define(['jquery'], function($) {
+ return factory($, root);
+ });
+
+ // CommonJS module definition
+ } else if ( typeof exports === 'object') {
+
+ // NOTE: To use Mockjax as a Node module you MUST provide the factory with
+ // a valid version of jQuery and a window object (the global scope):
+ // var mockjax = require('jquery.mockjax')(jQuery, window);
+
+ module.exports = factory;
+
+ // Global jQuery in web browsers
+ } else {
+ return factory(root.jQuery || root.$, root);
+ }
+}(this, function($, window) {
+ 'use strict';
+
var _ajax = $.ajax,
mockHandlers = [],
mockedAjaxCalls = [],
+ unmockedAjaxCalls = [],
CALLBACK_REGEX = /=\?(&|$)/,
jsc = (new Date()).getTime();
// Parse the given XML string.
function parseXML(xml) {
- if ( window.DOMParser == undefined && window.ActiveXObject ) {
- DOMParser = function() { };
+ if ( window.DOMParser === undefined && window.ActiveXObject ) {
+ window.DOMParser = function() { };
DOMParser.prototype.parseFromString = function( xmlString ) {
var doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
@@ -22,25 +58,20 @@
var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
if ( $.isXMLDoc( xmlDoc ) ) {
var err = $('parsererror', xmlDoc);
- if ( err.length == 1 ) {
- throw('Error: ' + $(xmlDoc).text() );
+ if ( err.length === 1 ) {
+ throw new Error('Error: ' + $(xmlDoc).text() );
}
} else {
- throw('Unable to parse XML');
+ throw new Error('Unable to parse XML');
}
return xmlDoc;
} catch( e ) {
- var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
+ var msg = ( e.name === undefined ? e : e.name + ': ' + e.message );
$(document).trigger('xmlParseError', [ msg ]);
return undefined;
}
}
- // Trigger a jQuery event
- function trigger(s, type, args) {
- (s.context ? $(s.context) : $.event).trigger(type, args);
- }
-
// Check if the data field on the mock handler and the request match. This
// can be used to restrict a mock handler to being used only when a certain
// set of data is passed to it.
@@ -49,21 +80,23 @@
// Test for situations where the data is a querystring (not an object)
if (typeof live === 'string') {
// Querystring may be a regex
- return $.isFunction( mock.test ) ? mock.test(live) : mock == live;
+ return $.isFunction( mock.test ) ? mock.test(live) : mock === live;
}
$.each(mock, function(k) {
if ( live[k] === undefined ) {
identical = false;
return identical;
} else {
- // This will allow to compare Arrays
if ( typeof live[k] === 'object' && live[k] !== null ) {
+ if ( identical && $.isArray( live[k] ) ) {
+ identical = $.isArray( mock[k] ) && live[k].length === mock[k].length;
+ }
identical = identical && isMockDataEqual(mock[k], live[k]);
} else {
if ( mock[k] && $.isFunction( mock[k].test ) ) {
identical = identical && mock[k].test(live[k]);
} else {
- identical = identical && ( mock[k] == live[k] );
+ identical = identical && ( mock[k] === live[k] );
}
}
}
@@ -72,10 +105,10 @@
return identical;
}
- // See if a mock handler property matches the default settings
- function isDefaultSetting(handler, property) {
- return handler[property] === $.mockjaxSettings[property];
- }
+ // See if a mock handler property matches the default settings
+ function isDefaultSetting(handler, property) {
+ return handler[property] === $.mockjaxSettings[property];
+ }
// Check the given handler should mock the given request
function getMockForRequest( handler, requestSettings ) {
@@ -96,21 +129,42 @@
// Look for a simple wildcard '*' or a direct URL match
var star = handler.url.indexOf('*');
if (handler.url !== requestSettings.url && star === -1 ||
- !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace(/\*/g, '.+')).test(requestSettings.url)) {
+ !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&').replace(/\*/g, '.+')).test(requestSettings.url)) {
return null;
}
}
+ // Inspect the request headers submitted
+ if ( handler.requestHeaders ) {
+ //No expectation for headers, do not mock this request
+ if (requestSettings.headers === undefined) {
+ return null;
+ } else {
+ var headersMismatch = false;
+ $.each(handler.requestHeaders, function(key, value) {
+ var v = requestSettings.headers[key];
+ if(v !== value) {
+ headersMismatch = true;
+ return false;
+ }
+ });
+ //Headers do not match, do not mock this request
+ if (headersMismatch) {
+ return null;
+ }
+ }
+ }
+
// Inspect the data submitted in the request (either POST body or GET query string)
- if ( handler.data && requestSettings.data ) {
- if ( !isMockDataEqual(handler.data, requestSettings.data) ) {
+ if ( handler.data ) {
+ if ( ! requestSettings.data || !isMockDataEqual(handler.data, requestSettings.data) ) {
// They're not identical, do not mock this request
return null;
}
}
// Inspect the request type
if ( handler && handler.type &&
- handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) {
+ handler.type.toLowerCase() !== requestSettings.type.toLowerCase() ) {
// The request type doesn't match (GET vs. POST)
return null;
}
@@ -118,6 +172,23 @@
return handler;
}
+ function isPosNum(value) {
+ return typeof value === 'number' && value >= 0;
+ }
+
+ function parseResponseTimeOpt(responseTime) {
+ if ($.isArray(responseTime) && responseTime.length === 2) {
+ var min = responseTime[0];
+ var max = responseTime[1];
+ if(isPosNum(min) && isPosNum(max)) {
+ return Math.floor(Math.random() * (max - min)) + min;
+ }
+ } else if(isPosNum(responseTime)) {
+ return responseTime;
+ }
+ return DEFAULT_RESPONSE_TIME;
+ }
+
// Process the xhr objects send operation
function _xhrSend(mockHandler, requestSettings, origSettings) {
@@ -125,52 +196,70 @@
var process = (function(that) {
return function() {
return (function() {
- var onReady;
-
// The request has returned
- this.status = mockHandler.status;
+ this.status = mockHandler.status;
this.statusText = mockHandler.statusText;
- this.readyState = 4;
+ this.readyState = 1;
+
+ var finishRequest = function () {
+ this.readyState = 4;
+
+ var onReady;
+ // Copy over our mock to our xhr object before passing control back to
+ // jQuery's onreadystatechange callback
+ if ( requestSettings.dataType === 'json' && ( typeof mockHandler.responseText === 'object' ) ) {
+ this.responseText = JSON.stringify(mockHandler.responseText);
+ } else if ( requestSettings.dataType === 'xml' ) {
+ if ( typeof mockHandler.responseXML === 'string' ) {
+ this.responseXML = parseXML(mockHandler.responseXML);
+ //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
+ this.responseText = mockHandler.responseXML;
+ } else {
+ this.responseXML = mockHandler.responseXML;
+ }
+ } else if (typeof mockHandler.responseText === 'object' && mockHandler.responseText !== null) {
+ // since jQuery 1.9 responseText type has to match contentType
+ mockHandler.contentType = 'application/json';
+ this.responseText = JSON.stringify(mockHandler.responseText);
+ } else {
+ this.responseText = mockHandler.responseText;
+ }
+ if( typeof mockHandler.status === 'number' || typeof mockHandler.status === 'string' ) {
+ this.status = mockHandler.status;
+ }
+ if( typeof mockHandler.statusText === 'string') {
+ this.statusText = mockHandler.statusText;
+ }
+ // jQuery 2.0 renamed onreadystatechange to onload
+ onReady = this.onreadystatechange || this.onload;
+
+ // jQuery < 1.4 doesn't have onreadystate change for xhr
+ if ( $.isFunction( onReady ) ) {
+ if( mockHandler.isTimeout) {
+ this.status = -1;
+ }
+ onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
+ } else if ( mockHandler.isTimeout ) {
+ // Fix for 1.3.2 timeout to keep success from firing.
+ this.status = -1;
+ }
+ };
// We have an executable function, call it to give
// the mock handler a chance to update it's data
if ( $.isFunction(mockHandler.response) ) {
- mockHandler.response(origSettings);
- }
- // Copy over our mock to our xhr object before passing control back to
- // jQuery's onreadystatechange callback
- if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) {
- this.responseText = JSON.stringify(mockHandler.responseText);
- } else if ( requestSettings.dataType == 'xml' ) {
- if ( typeof mockHandler.responseXML == 'string' ) {
- this.responseXML = parseXML(mockHandler.responseXML);
- //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
- this.responseText = mockHandler.responseXML;
+ // Wait for it to finish
+ if ( mockHandler.response.length === 2 ) {
+ mockHandler.response(origSettings, function () {
+ finishRequest.call(that);
+ });
+ return;
} else {
- this.responseXML = mockHandler.responseXML;
+ mockHandler.response(origSettings);
}
- } else {
- this.responseText = mockHandler.responseText;
- }
- if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) {
- this.status = mockHandler.status;
- }
- if( typeof mockHandler.statusText === "string") {
- this.statusText = mockHandler.statusText;
}
- // jQuery 2.0 renamed onreadystatechange to onload
- onReady = this.onreadystatechange || this.onload;
- // jQuery < 1.4 doesn't have onreadystate change for xhr
- if ( $.isFunction( onReady ) ) {
- if( mockHandler.isTimeout) {
- this.status = -1;
- }
- onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
- } else if ( mockHandler.isTimeout ) {
- // Fix for 1.3.2 timeout to keep success from firing.
- this.status = -1;
- }
+ finishRequest.call(that);
}).apply(that);
};
})(this);
@@ -182,28 +271,27 @@
url: mockHandler.proxy,
type: mockHandler.proxyType,
data: mockHandler.data,
- dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType,
+ dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
complete: function(xhr) {
mockHandler.responseXML = xhr.responseXML;
mockHandler.responseText = xhr.responseText;
- // Don't override the handler status/statusText if it's specified by the config
- if (isDefaultSetting(mockHandler, 'status')) {
- mockHandler.status = xhr.status;
- }
- if (isDefaultSetting(mockHandler, 'statusText')) {
- mockHandler.statusText = xhr.statusText;
- }
-
- this.responseTimer = setTimeout(process, mockHandler.responseTime || 0);
+ // Don't override the handler status/statusText if it's specified by the config
+ if (isDefaultSetting(mockHandler, 'status')) {
+ mockHandler.status = xhr.status;
+ }
+ if (isDefaultSetting(mockHandler, 'statusText')) {
+ mockHandler.statusText = xhr.statusText;
+ }
+ this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
}
});
} else {
- // type == 'POST' || 'GET' || 'DELETE'
+ // type === 'POST' || 'GET' || 'DELETE'
if ( requestSettings.async === false ) {
// TODO: Blocking delay
process();
} else {
- this.responseTimer = setTimeout(process, mockHandler.responseTime || 50);
+ this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
}
}
}
@@ -216,6 +304,9 @@
if (typeof mockHandler.headers === 'undefined') {
mockHandler.headers = {};
}
+ if (typeof requestSettings.headers === 'undefined') {
+ requestSettings.headers = {};
+ }
if ( mockHandler.contentType ) {
mockHandler.headers['content-type'] = mockHandler.contentType;
}
@@ -233,25 +324,29 @@
clearTimeout(this.responseTimer);
},
setRequestHeader: function(header, value) {
- mockHandler.headers[header] = value;
+ requestSettings.headers[header] = value;
},
getResponseHeader: function(header) {
// 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
if ( mockHandler.headers && mockHandler.headers[header] ) {
// Return arbitrary headers
return mockHandler.headers[header];
- } else if ( header.toLowerCase() == 'last-modified' ) {
+ } else if ( header.toLowerCase() === 'last-modified' ) {
return mockHandler.lastModified || (new Date()).toString();
- } else if ( header.toLowerCase() == 'etag' ) {
+ } else if ( header.toLowerCase() === 'etag' ) {
return mockHandler.etag || '';
- } else if ( header.toLowerCase() == 'content-type' ) {
+ } else if ( header.toLowerCase() === 'content-type' ) {
return mockHandler.contentType || 'text/plain';
}
},
getAllResponseHeaders: function() {
var headers = '';
+ // since jQuery 1.9 responseText type has to match contentType
+ if (mockHandler.contentType) {
+ mockHandler.headers['Content-Type'] = mockHandler.contentType;
+ }
$.each(mockHandler.headers, function(k, v) {
- headers += k + ': ' + v + "\n";
+ headers += k + ': ' + v + '\n';
});
return headers;
}
@@ -265,7 +360,7 @@
processJsonpUrl( requestSettings );
- requestSettings.dataType = "json";
+ requestSettings.dataType = 'json';
if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
createJsonpCallback(requestSettings, mockHandler, origSettings);
@@ -276,8 +371,8 @@
parts = rurl.exec( requestSettings.url ),
remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
- requestSettings.dataType = "script";
- if(requestSettings.type.toUpperCase() === "GET" && remote ) {
+ requestSettings.dataType = 'script';
+ if(requestSettings.type.toUpperCase() === 'GET' && remote ) {
var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
// Check if we are supposed to return a Deferred back to the mock call, or just
@@ -294,13 +389,13 @@
// Append the required callback parameter to the end of the request URL, for a JSONP request
function processJsonpUrl( requestSettings ) {
- if ( requestSettings.type.toUpperCase() === "GET" ) {
+ if ( requestSettings.type.toUpperCase() === 'GET' ) {
if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
- requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") +
- (requestSettings.jsonp || "callback") + "=?";
+ requestSettings.url += (/\?/.test( requestSettings.url ) ? '&' : '?') +
+ (requestSettings.jsonp || 'callback') + '=?';
}
} else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
- requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?";
+ requestSettings.data = (requestSettings.data ? requestSettings.data + '&' : '') + (requestSettings.jsonp || 'callback') + '=?';
}
}
@@ -308,58 +403,82 @@
function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
// Synthesize the mock request for adding a script tag
var callbackContext = origSettings && origSettings.context || requestSettings,
- newMock = null;
-
+ // If we are running under jQuery 1.5+, return a deferred object
+ newMock = ($.Deferred) ? (new $.Deferred()) : null;
// If the response handler on the moock is a function, call it
if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
+
mockHandler.response(origSettings);
- } else {
-
+
+
+ } else if ( typeof mockHandler.responseText === 'object' ) {
// Evaluate the responseText javascript in a global context
- if( typeof mockHandler.responseText === 'object' ) {
- $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
- } else {
- $.globalEval( '(' + mockHandler.responseText + ')');
- }
+ $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
+
+ } else if (mockHandler.proxy) {
+
+ // This handles the unique case where we have a remote URL, but want to proxy the JSONP
+ // response to another file (not the same URL as the mock matching)
+ _ajax({
+ global: false,
+ url: mockHandler.proxy,
+ type: mockHandler.proxyType,
+ data: mockHandler.data,
+ dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
+ complete: function(xhr) {
+ $.globalEval( '(' + xhr.responseText + ')');
+ completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
+ }
+ });
+
+ return newMock;
+
+ } else {
+ $.globalEval( '(' + mockHandler.responseText + ')');
}
+ completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
+
+ return newMock;
+ }
+
+ function completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock ) {
+ var json;
+
// Successful response
- jsonpSuccess( requestSettings, callbackContext, mockHandler );
- jsonpComplete( requestSettings, callbackContext, mockHandler );
-
- // If we are running under jQuery 1.5+, return a deferred object
- if($.Deferred){
- newMock = new $.Deferred();
- if(typeof mockHandler.responseText == "object"){
- newMock.resolveWith( callbackContext, [mockHandler.responseText] );
- }
- else{
- newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] );
- }
+ setTimeout(function() {
+ jsonpSuccess( requestSettings, callbackContext, mockHandler );
+ jsonpComplete( requestSettings, callbackContext );
+ }, parseResponseTimeOpt( mockHandler.responseTime ));
+
+ if ( newMock ) {
+ try {
+ json = $.parseJSON( mockHandler.responseText );
+ } catch (err) { /* just checking... */ }
+
+ newMock.resolveWith( callbackContext, [json || mockHandler.responseText] );
}
- return newMock;
}
// Create the required JSONP callback function for the request
function createJsonpCallback( requestSettings, mockHandler, origSettings ) {
var callbackContext = origSettings && origSettings.context || requestSettings;
- var jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++);
+ var jsonp = requestSettings.jsonpCallback || ('jsonp' + jsc++);
// Replace the =? sequence both in the query string and the data
if ( requestSettings.data ) {
- requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1");
+ requestSettings.data = (requestSettings.data + '').replace(CALLBACK_REGEX, '=' + jsonp + '$1');
}
- requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1");
+ requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, '=' + jsonp + '$1');
// Handle JSONP-style loading
- window[ jsonp ] = window[ jsonp ] || function( tmp ) {
- data = tmp;
+ window[ jsonp ] = window[ jsonp ] || function() {
jsonpSuccess( requestSettings, callbackContext, mockHandler );
- jsonpComplete( requestSettings, callbackContext, mockHandler );
+ jsonpComplete( requestSettings, callbackContext );
// Garbage collect
window[ jsonp ] = undefined;
@@ -367,9 +486,6 @@
delete window[ jsonp ];
} catch(e) {}
- if ( head ) {
- head.removeChild( script );
- }
};
}
@@ -377,49 +493,65 @@
function jsonpSuccess(requestSettings, callbackContext, mockHandler) {
// If a local callback was specified, fire it and pass it the data
if ( requestSettings.success ) {
- requestSettings.success.call( callbackContext, mockHandler.responseText || "", status, {} );
+ requestSettings.success.call( callbackContext, mockHandler.responseText || '', 'success', {} );
}
// Fire the global callback
if ( requestSettings.global ) {
- trigger(requestSettings, "ajaxSuccess", [{}, requestSettings] );
+ (requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxSuccess', [{}, requestSettings]);
}
}
// The JSONP request was completed
function jsonpComplete(requestSettings, callbackContext) {
- // Process result
if ( requestSettings.complete ) {
- requestSettings.complete.call( callbackContext, {} , status );
+ requestSettings.complete.call( callbackContext, {
+ statusText: 'success',
+ status: 200
+ } , 'success' );
}
// The request was completed
if ( requestSettings.global ) {
- trigger( "ajaxComplete", [{}, requestSettings] );
+ (requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxComplete', [{}, requestSettings]);
}
// Handle the global AJAX counter
if ( requestSettings.global && ! --$.active ) {
- $.event.trigger( "ajaxStop" );
+ $.event.trigger( 'ajaxStop' );
}
}
// The core $.ajax replacement.
function handleAjax( url, origSettings ) {
- var mockRequest, requestSettings, mockHandler;
+ var mockRequest, requestSettings, mockHandler, overrideCallback;
// If url is an object, simulate pre-1.5 signature
- if ( typeof url === "object" ) {
+ if ( typeof url === 'object' ) {
origSettings = url;
url = undefined;
} else {
// work around to support 1.5 signature
+ origSettings = origSettings || {};
origSettings.url = url;
}
// Extend the original settings for the request
- requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings);
+ requestSettings = $.ajaxSetup({}, origSettings);
+ requestSettings.type = requestSettings.method = requestSettings.method || requestSettings.type;
+
+ // Generic function to override callback methods for use with
+ // callback options (onAfterSuccess, onAfterError, onAfterComplete)
+ overrideCallback = function(action, mockHandler) {
+ var origHandler = origSettings[action.toLowerCase()];
+ return function() {
+ if ( $.isFunction(origHandler) ) {
+ origHandler.apply(this, [].slice.call(arguments));
+ }
+ mockHandler['onAfter' + action]();
+ };
+ };
// Iterate over our mock handlers (in registration order) until we find
// one that is willing to intercept the request
@@ -440,7 +572,7 @@
$.mockjaxSettings.log( mockHandler, requestSettings );
- if ( requestSettings.dataType === "jsonp" ) {
+ if ( requestSettings.dataType && requestSettings.dataType.toUpperCase() === 'JSONP' ) {
if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
// This mock will handle the JSONP request
return mockRequest;
@@ -455,21 +587,48 @@
mockHandler.timeout = requestSettings.timeout;
mockHandler.global = requestSettings.global;
+ // In the case of a timeout, we just need to ensure
+ // an actual jQuery timeout (That is, our reponse won't)
+ // return faster than the timeout setting.
+ if ( mockHandler.isTimeout ) {
+ if ( mockHandler.responseTime > 1 ) {
+ origSettings.timeout = mockHandler.responseTime - 1;
+ } else {
+ mockHandler.responseTime = 2;
+ origSettings.timeout = 1;
+ }
+ }
+
+ // Set up onAfter[X] callback functions
+ if ( $.isFunction( mockHandler.onAfterSuccess ) ) {
+ origSettings.success = overrideCallback('Success', mockHandler);
+ }
+ if ( $.isFunction( mockHandler.onAfterError ) ) {
+ origSettings.error = overrideCallback('Error', mockHandler);
+ }
+ if ( $.isFunction( mockHandler.onAfterComplete ) ) {
+ origSettings.complete = overrideCallback('Complete', mockHandler);
+ }
+
copyUrlParameters(mockHandler, origSettings);
+ /* jshint loopfunc:true */
(function(mockHandler, requestSettings, origSettings, origHandler) {
+
mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
// Mock the XHR object
xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); }
}));
})(mockHandler, requestSettings, origSettings, mockHandlers[k]);
+ /* jshint loopfunc:true */
return mockRequest;
}
// We don't have a mock request
+ unmockedAjaxCalls.push(origSettings);
if($.mockjaxSettings.throwUnmocked === true) {
- throw('AJAX not mocked: ' + origSettings.url);
+ throw new Error('AJAX not mocked: ' + origSettings.url);
}
else { // trigger a normal request
return _ajax.apply($, [origSettings]);
@@ -517,20 +676,23 @@
ajax: handleAjax
});
+ var DEFAULT_RESPONSE_TIME = 500;
+
+
$.mockjaxSettings = {
- //url: null,
- //type: 'GET',
- log: function( mockHandler, requestSettings ) {
+ //url: null,
+ //type: 'GET',
+ log: function( mockHandler, requestSettings ) {
if ( mockHandler.logging === false ||
( typeof mockHandler.logging === 'undefined' && $.mockjaxSettings.logging === false ) ) {
return;
}
if ( window.console && console.log ) {
var message = 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url;
- var request = $.extend({}, requestSettings);
+ var request = $.ajaxSetup({}, requestSettings);
if (typeof console.log === 'function') {
- console.log(message, JSON.stringify(request.data));
+ console.log(message, request);
} else {
try {
console.log( message + ' ' + JSON.stringify(request) );
@@ -542,8 +704,8 @@
},
logging: true,
status: 200,
- statusText: "OK",
- responseTime: 500,
+ statusText: 'OK',
+ responseTime: DEFAULT_RESPONSE_TIME,
isTimeout: false,
throwUnmocked: false,
contentType: 'text/plain',
@@ -566,20 +728,37 @@
mockHandlers[i] = settings;
return i;
};
- $.mockjaxClear = function(i) {
- if ( arguments.length == 1 ) {
+ $.mockjax.clear = function(i) {
+ if ( i || i === 0 ) {
mockHandlers[i] = null;
} else {
mockHandlers = [];
}
mockedAjaxCalls = [];
+ unmockedAjaxCalls = [];
};
$.mockjax.handler = function(i) {
- if ( arguments.length == 1 ) {
+ if ( arguments.length === 1 ) {
return mockHandlers[i];
}
};
$.mockjax.mockedAjaxCalls = function() {
return mockedAjaxCalls;
};
-})(jQuery);
+ $.mockjax.unfiredHandlers = function() {
+ var results = [];
+ for (var i=0, len=mockHandlers.length; i<len; i++) {
+ var handler = mockHandlers[i];
+ if (handler !== null && !handler.fired) {
+ results.push(handler);
+ }
+ }
+ return results;
+ };
+ $.mockjax.unmockedAjaxCalls = function() {
+ return unmockedAjaxCalls;
+ };
+
+ return $.mockjax;
+
+}));
diff --git a/server/sonar-web/test/helpers/test-page.js b/server/sonar-web/test/helpers/test-page.js
index b07a0b91a0b..8e370300d71 100644
--- a/server/sonar-web/test/helpers/test-page.js
+++ b/server/sonar-web/test/helpers/test-page.js
@@ -109,6 +109,15 @@ define(function (require) {
});
};
+ Command.prototype.submitForm = function (selector) {
+ return new this.constructor(this, function () {
+ return this.parent
+ .execute(function (selector) {
+ jQuery(selector).submit();
+ }, [selector]);
+ });
+ };
+
Command.prototype.mockFromFile = function (url, file, options) {
var response = fs.readFileSync('src/test/json/' + file, 'utf-8');
return new this.constructor(this, function () {
@@ -132,7 +141,7 @@ define(function (require) {
return new this.constructor(this, function () {
return this.parent
.execute(function () {
- jQuery.mockjaxClear();
+ jQuery.mockjax.clear();
});
});
};
@@ -162,4 +171,13 @@ define(function (require) {
});
};
+ Command.prototype.forceJSON = function () {
+ return new this.constructor(this, function () {
+ return this.parent
+ .execute(function () {
+ jQuery.ajaxSetup({ dataType: 'json' });
+ });
+ });
+ };
+
});
diff --git a/server/sonar-web/test/intern.js b/server/sonar-web/test/intern.js
index 1de94e101e3..6e846af1423 100644
--- a/server/sonar-web/test/intern.js
+++ b/server/sonar-web/test/intern.js
@@ -23,7 +23,8 @@ define(['intern'], function (intern) {
'test/medium/users.spec',
'test/medium/issues.spec',
'test/medium/update-center.spec',
- 'test/medium/computation.spec'
+ 'test/medium/computation.spec',
+ 'test/medium/coding-rules.spec'
],
tunnel: tunnel,
diff --git a/server/sonar-web/test/medium/base.html b/server/sonar-web/test/medium/base.html
index 09060d02b4a..4a241acad60 100644
--- a/server/sonar-web/test/medium/base.html
+++ b/server/sonar-web/test/medium/base.html
@@ -43,8 +43,8 @@
<script src="../../build/js/libs/csv.js"></script>
<script src="../../build/js/libs/dashboard.js"></script>
<script src="../../build/js/libs/recent-history.js"></script>
- <script src="../../build/js/libs/third-party/require.js"></script>
<script src="../../build/js/libs/third-party/jquery.mockjax.js"></script>
+ <script src="../../build/js/libs/third-party/require.js"></script>
<script>var baseUrl = '';
var $j = jQuery.noConflict();
window.suppressTranslationWarnings = true;
diff --git a/server/sonar-web/test/medium/coding-rules.spec.js b/server/sonar-web/test/medium/coding-rules.spec.js
new file mode 100644
index 00000000000..cf50688cd96
--- /dev/null
+++ b/server/sonar-web/test/medium/coding-rules.spec.js
@@ -0,0 +1,924 @@
+define(function (require) {
+ var bdd = require('intern!bdd');
+ require('../helpers/test-page');
+
+ bdd.describe('Coding Rules Page', function () {
+
+ bdd.it('should show alert when there is no available profiles for activation', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app-no-available-profiles.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-no-available-profiles.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-no-available-profiles.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementExist('#coding-rules-quality-profile-activate')
+ .clickElement('#coding-rules-quality-profile-activate')
+ .checkElementExist('.modal')
+ .checkElementExist('.modal .alert');
+ });
+
+ bdd.it('should show profile facet', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-profile-facet.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', '609')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search',
+ 'coding-rules-spec/search-profile-facet-qprofile-active.json',
+ { data: { activation: true } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementInclude('#coding-rules-total', '407')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"] .js-active.facet-toggle-active')
+ .clearMocks()
+ .mockFromFile('/api/rules/search',
+ 'coding-rules-spec/search-profile-facet-qprofile-inactive.json',
+ { data: { activation: 'false' } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"] .js-inactive')
+ .checkElementInclude('#coding-rules-total', '408')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"] .js-inactive.facet-toggle-active')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-profile-facet.json')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', '609');
+ });
+
+ bdd.it('should show query facet', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', '609')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-query.json', { data: { q: 'query' } })
+ .fillElement('[data-property="q"] input', 'query')
+ .submitForm('[data-property="q"] form')
+ .checkElementInclude('#coding-rules-total', '4')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .fillElement('[data-property="q"] input', '')
+ .submitForm('[data-property="q"] form')
+ .checkElementInclude('#coding-rules-total', '609');
+ });
+
+ bdd.it('should show rule permalink', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementExist('a[href="/coding_rules#rule_key=squid%3AS2204"]');
+ });
+
+ bdd.it('should activate profile', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-activate-profile.json')
+ .mockFromString('/api/qualityprofiles/activate_rule', '{}')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementNotExist('.coding-rules-detail-quality-profile-name')
+ .checkElementExist('#coding-rules-quality-profile-activate')
+ .clickElement('#coding-rules-quality-profile-activate')
+ .checkElementExist('.modal')
+ .clearMocks()
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-activate-profile-with-profile.json')
+ .mockFromString('/api/qualityprofiles/activate_rule', '{}')
+ .mockFromString('/api/issues/search', '{}')
+ .clickElement('#coding-rules-quality-profile-activation-activate')
+ .checkElementExist('.coding-rules-detail-quality-profile-name')
+ .checkElementExist('.coding-rules-detail-quality-profile-name')
+ .checkElementExist('.coding-rules-detail-quality-profile-severity')
+ .checkElementExist('.coding-rules-detail-quality-profile-deactivate');
+ });
+
+ bdd.it('should create custom rule', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-create-custom-rules.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clearMocks()
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-custom-rules.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-custom-rules.json',
+ { data: { template_key: 'squid:ArchitecturalConstraint' } })
+ .mockFromString('/api/rules/create', '{}')
+ .mockFromString('/api/issues/search', '{}')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('#coding-rules-detail-custom-rules .coding-rules-detail-list-name')
+ .clearMocks()
+ .mockFromString('/api/rules/create', '{}')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-custom-rules.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-custom-rules2.json')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 1)
+ .clickElement('.js-create-custom-rule')
+ .fillElement('.modal form [name="name"]', 'test')
+ .fillElement('.modal form [name="markdown_description"]', 'test')
+ .clickElement('#coding-rules-custom-rule-creation-create')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 2);
+ });
+
+ bdd.it('should reactivate custom rule', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-create-custom-rules.json')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.coding-rule.selected')
+ .clearMocks()
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-custom-rules.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-custom-rules.json',
+ { data: { template_key: 'squid:ArchitecturalConstraint' } })
+ .mockFromFile('/api/rules/create', 'coding-rules-spec/create-create-custom-rules.json', { status: 409 })
+ .mockFromString('/api/issues/search', '{}')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.js-create-custom-rule')
+ .clickElement('.js-create-custom-rule')
+ .checkElementExist('.modal')
+ .fillElement('.modal form [name="name"]', 'My Custom Rule')
+ .fillElement('.modal form [name="markdown_description"]', 'My Description')
+ .clickElement('#coding-rules-custom-rule-creation-create')
+ .checkElementExist('.modal .alert-warning')
+ .clearMocks()
+ .mockFromFile('/api/rules/create', 'coding-rules-spec/create-create-custom-rules.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-custom-rules2.json',
+ { data: { template_key: 'squid:ArchitecturalConstraint' } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-create-custom-rules.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-custom-rules.json')
+ .clickElement('.modal #coding-rules-custom-rule-creation-reactivate')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 2);
+ });
+
+ bdd.it('should create manual rule', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-create-manual-rule.json')
+ .mockFromFile('/api/rules/create', 'coding-rules-spec/show-create-manual-rule.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-manual-rule.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.js-create-manual-rule')
+ .clickElement('.js-create-manual-rule')
+ .checkElementExist('.modal')
+ .fillElement('.modal [name="name"]', 'Manual Rule')
+ .fillElement('.modal [name="markdown_description"]', 'Manual Rule Description')
+ .clickElement('.modal #coding-rules-manual-rule-creation-create')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementInclude('.coding-rules-detail-header', 'Manual Rule')
+ .checkElementInclude('.coding-rule-details', 'manual:Manual_Rule')
+ .checkElementInclude('.coding-rules-detail-description', 'Manual Rule Description');
+ });
+
+ bdd.it('should reactivate manual rule', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-create-manual-rule.json')
+ .mockFromFile('/api/rules/create', 'coding-rules-spec/show-create-manual-rule.json', { status: 409 })
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-manual-rule.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.js-create-manual-rule')
+ .clickElement('.js-create-manual-rule')
+ .checkElementExist('.modal')
+ .checkElementExist('.modal #coding-rules-manual-rule-creation-create')
+ .fillElement('.modal [name="name"]', 'Manual Rule')
+ .fillElement('.modal [name="markdown_description"]', 'Manual Rule Description')
+ .clickElement('.modal #coding-rules-manual-rule-creation-create')
+ .checkElementExist('.modal .alert-warning')
+ .clearMocks()
+ .mockFromFile('/api/rules/create', 'coding-rules-spec/show.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-create-manual-rule.json')
+ .clickElement('.modal #coding-rules-manual-rule-creation-reactivate')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementInclude('.coding-rules-detail-header', 'Manual Rule')
+ .checkElementInclude('.coding-rule-details', 'manual:Manual_Rule')
+ .checkElementInclude('.coding-rules-detail-description', 'Manual Rule Description');
+ });
+
+ bdd.it('should delete custom rules', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-delete-custom-rule-custom-rules.json',
+ { data: { template_key: 'squid:ArchitecturalConstraint' } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-delete-custom-rule.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-delete-custom-rule.json')
+ .mockFromString('/api/rules/delete', '{}')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('#coding-rules-detail-custom-rules .coding-rules-detail-list-name')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 2)
+ .clickElement('.js-delete-custom-rule')
+ .clickElement('[data-confirm="yes"]')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 1);
+ });
+
+ bdd.it('should delete manual rules', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-delete-manual-rule-before.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-delete-manual-rule.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.js-delete')
+ .clickElement('.js-delete')
+ .checkElementExist('[data-confirm="yes"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-delete-manual-rule-after.json')
+ .mockFromString('/api/rules/delete', '{}')
+ .clickElement('[data-confirm="yes"]')
+ .checkElementInclude('#coding-rules-total', 0);
+ });
+
+ bdd.it('should show custom rules', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-show-cutsom-rule-custom-rules.json',
+ { data: { template_key: 'squid:ArchitecturalConstraint' } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-show-cutsom-rule.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-show-cutsom-rule.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('#coding-rules-detail-custom-rules .coding-rules-detail-list-name')
+ .checkElementExist('#coding-rules-detail-custom-rules')
+ .checkElementCount('#coding-rules-detail-custom-rules .coding-rules-detail-list-name', 2)
+ .checkElementInclude('#coding-rules-detail-custom-rules .coding-rules-detail-list-name',
+ 'Do not use org.h2.util.StringUtils');
+ });
+
+ bdd.it('should show deprecated label', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-deprecated.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .checkElementInclude('.coding-rule.selected', 'DEPRECATED');
+ });
+
+ bdd.it('should show rule details', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-show-details.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show-show-details.json')
+ .mockFromString('/api/issues/search', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementInclude('.search-navigator-workspace-details',
+ 'Throwable and Error classes should not be caught')
+ .checkElementInclude('.search-navigator-workspace-details', 'squid:S1181')
+ .checkElementExist('.coding-rules-detail-properties .icon-severity-blocker')
+ .checkElementInclude('.coding-rules-detail-properties', 'error-handling')
+ .checkElementInclude('.coding-rules-detail-properties', '2013')
+ .checkElementInclude('.coding-rules-detail-properties', 'SonarQube (Java)')
+ .checkElementInclude('.coding-rules-detail-properties', 'Reliability > Exception handling')
+ .checkElementInclude('.coding-rules-detail-properties', 'LINEAR')
+ .checkElementInclude('.coding-rules-detail-properties', '20min')
+
+ .checkElementInclude('.coding-rules-detail-description', 'is the superclass of all errors and')
+ .checkElementInclude('.coding-rules-detail-description', 'its subclasses should be caught.')
+ .checkElementInclude('.coding-rules-detail-description', 'Noncompliant Code Example')
+ .checkElementInclude('.coding-rules-detail-description', 'Compliant Solution')
+
+ .checkElementInclude('.coding-rules-detail-parameters', 'max')
+ .checkElementInclude('.coding-rules-detail-parameters', 'Maximum authorized number of parameters')
+ .checkElementInclude('.coding-rules-detail-parameters', '7')
+
+ .checkElementCount('.coding-rules-detail-quality-profile-name', 6)
+ .checkElementInclude('.coding-rules-detail-quality-profile-name', 'Default - Top')
+ .checkElementCount('.coding-rules-detail-quality-profile-inheritance', 4)
+ .checkElementInclude('.coding-rules-detail-quality-profile-inheritance', 'Default - Top');
+ });
+
+ bdd.it('should show empty list', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-empty.json')
+ .startApp('coding-rules')
+ .checkElementExist('.search-navigator-facet-box')
+ .checkElementNotExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', 0)
+ .checkElementExist('.search-navigator-no-results');
+ });
+
+ bdd.it('should show facets', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.search-navigator-facet-box')
+ .checkElementCount('.search-navigator-facet-box', 13);
+ });
+
+ bdd.it('should show rule', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .checkElementInclude('.coding-rule.selected', 'Values passed to SQL commands should be sanitized')
+ .checkElementInclude('.coding-rule.selected', 'Java')
+ .checkElementInclude('.coding-rule.selected', 'cwe')
+ .checkElementInclude('.coding-rule.selected', 'owasp-top10')
+ .checkElementInclude('.coding-rule.selected', 'security')
+ .checkElementInclude('.coding-rule.selected', 'sql')
+ .checkElementInclude('.coding-rule.selected', 'custom-tag');
+ });
+
+ bdd.it('should show rule issues', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show.json')
+ .mockFromFile('/api/issues/search', 'coding-rules-spec/issues-search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-most-violated-projects')
+ .checkElementInclude('.js-rule-issues', '7')
+ .checkElementInclude('.coding-rules-most-violated-projects', 'SonarQube')
+ .checkElementInclude('.coding-rules-most-violated-projects', '2')
+ .checkElementInclude('.coding-rules-most-violated-projects', 'SonarQube Runner')
+ .checkElementInclude('.coding-rules-most-violated-projects', '1');
+ });
+
+ bdd.it('should show rules', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementCount('.coding-rule', 25)
+ .checkElementInclude('.coding-rule', 'Values passed to SQL commands should be sanitized')
+ .checkElementInclude('.coding-rule', 'An open curly brace should be located at the beginning of a line')
+ .checkElementInclude('#coding-rules-total', '609');
+ });
+
+ bdd.it('should move between rules from detailed view', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .checkElementInclude('.coding-rules-detail-header',
+ '".equals()" should not be used to test the values')
+ .clearMocks()
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show2.json')
+ .clickElement('.js-next')
+ .checkElementInclude('.coding-rules-detail-header', '"@Override" annotation should be used on any')
+ .clearMocks()
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show.json')
+ .clickElement('.js-prev')
+ .checkElementInclude('.coding-rules-detail-header', '".equals()" should not be used to test the values');
+ });
+
+ bdd.it('should filter similar rules', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected .js-rule-filter')
+ .checkElementInclude('#coding-rules-total', '609')
+ .clickElement('.js-rule-filter')
+ .checkElementExist('.bubble-popup')
+ .checkElementExist('.bubble-popup [data-property="languages"][data-value="java"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-sql-tag.json', { data: { tags: 'sql' } })
+ .clickElement('.bubble-popup [data-property="tags"][data-value="sql"]')
+ .checkElementInclude('#coding-rules-total', '2');
+ });
+
+ bdd.it('should show active severity facet', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', '609')
+ .checkElementExist('.search-navigator-facet-box-forbidden[data-property="active_severities"]')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-qprofile.json',
+ { data: { qprofile: 'java-default-with-mojo-conventions-49307' } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementInclude('#coding-rules-total', '407')
+ .checkElementNotExist('.search-navigator-facet-box-forbidden[data-property="active_severities"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/active-severities-facet.json',
+ { data: { facets: 'active_severities', ps: 1 } })
+ .clickElement('[data-property="active_severities"] .js-facet-toggle')
+ .checkElementExist('[data-property="active_severities"] [data-value="BLOCKER"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-BLOCKER.json',
+ { data: { active_severities: 'BLOCKER' } })
+ .clickElement('[data-property="active_severities"] [data-value="BLOCKER"]')
+ .checkElementInclude('#coding-rules-total', '4')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', '609')
+ .checkElementExist('.search-navigator-facet-box-forbidden[data-property="active_severities"]');
+ });
+
+ bdd.it('should show available since facet', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', '609')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-limited.json',
+ { data: { available_since: '2014-12-01' } })
+ .clickElement('[data-property="available_since"] .js-facet-toggle')
+ .fillElement('[data-property="available_since"] input', '2014-12-01')
+ .execute(function () {
+ // TODO do not use jQuery
+ jQuery('[data-property="available_since"] input').change();
+ })
+ .checkElementInclude('#coding-rules-total', '101');
+ });
+
+ bdd.it('should bulk activate', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromString('/api/qualityprofiles/activate_rules', '{ "succeeded": 225 }')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.coding-rule')
+ .checkElementExist('.js-bulk-change')
+ .clickElement('.js-bulk-change')
+ .checkElementExist('.bubble-popup')
+ .checkElementExist('.bubble-popup .js-bulk-change[data-action="activate"]')
+ .clickElement('.js-bulk-change[data-action="activate"]')
+ .checkElementExist('.modal')
+ .checkElementExist('.modal #coding-rules-bulk-change-profile')
+ .checkElementExist('.modal #coding-rules-submit-bulk-change')
+ .fillElement('#coding-rules-bulk-change-profile', 'java-default-with-mojo-conventions-49307')
+ .clickElement('.modal #coding-rules-submit-bulk-change')
+ .checkElementExist('.modal .alert-success')
+ .checkElementInclude('.modal', 'Default - Maven Conventions')
+ .checkElementInclude('.modal', 'Java')
+ .checkElementInclude('.modal', '225');
+ });
+
+ bdd.it('should fail to bulk activate', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromString('/api/qualityprofiles/activate_rules', '{ "succeeded": 225, "failed": 395 }')
+ .startApp('coding-rules')
+ .forceJSON()
+ .checkElementExist('.coding-rule')
+ .checkElementExist('.js-bulk-change')
+ .clickElement('.js-bulk-change')
+ .checkElementExist('.bubble-popup')
+ .checkElementExist('.bubble-popup .js-bulk-change[data-action="activate"]')
+ .clickElement('.js-bulk-change[data-action="activate"]')
+ .checkElementExist('.modal')
+ .checkElementExist('.modal #coding-rules-bulk-change-profile')
+ .checkElementExist('.modal #coding-rules-submit-bulk-change')
+ .fillElement('#coding-rules-bulk-change-profile', 'java-default-with-mojo-conventions-49307')
+ .clickElement('.modal #coding-rules-submit-bulk-change')
+ .checkElementExist('.modal .alert-warning')
+ .checkElementInclude('.modal', '225')
+ .checkElementInclude('.modal', '395');
+ });
+
+ bdd.it('should filter profiles by language during bulk change', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .clickElement('.js-facet[data-value="java"]')
+ .checkElementExist('.js-bulk-change')
+ .clickElement('.js-bulk-change')
+ .checkElementExist('.bubble-popup')
+ .checkElementExist('.bubble-popup .js-bulk-change[data-action="activate"]')
+ .clickElement('.js-bulk-change[data-action="activate"]')
+ .checkElementExist('.modal')
+ .checkElementExist('.modal #coding-rules-bulk-change-profile')
+ .checkElementCount('.modal #coding-rules-bulk-change-profile option', 8);
+ });
+
+ bdd.it('should change selected profile during bulk change', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-qprofile-active.json',
+ { data: { activation: true } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromString('/api/qualityprofiles/deactivate_rules', '{ "succeeded": 7 }')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementExist('.js-bulk-change')
+ .clickElement('.js-bulk-change')
+ .checkElementExist('.bubble-popup')
+ .checkElementExist('.bubble-popup .js-bulk-change[data-param="java-default-with-mojo-conventions-49307"]')
+ .clickElement('.js-bulk-change[data-param="java-default-with-mojo-conventions-49307"]')
+ .checkElementExist('.modal')
+ .checkElementNotExist('.modal #coding-rules-bulk-change-profile')
+ .clickElement('.modal #coding-rules-submit-bulk-change')
+ .checkElementExist('.modal .alert-success')
+ .checkElementInclude('.modal', '7');
+ });
+
+ bdd.it('should show characteristic facet', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementExist('.search-navigator-facet-box-collapsed[data-property="debt_characteristics"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-characteristic.json',
+ { data: { facets: 'debt_characteristics' } })
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="PORTABILITY"]')
+ .checkElementCount('[data-property="debt_characteristics"] .js-facet', 32)
+ .checkElementCount('[data-property="debt_characteristics"] .js-facet.search-navigator-facet-indent', 24)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-with-portability-characteristic.json',
+ { data: { debt_characteristics: 'PORTABILITY' } })
+ .clickElement('.js-facet[data-value="PORTABILITY"]')
+ .checkElementInclude('#coding-rules-total', 21)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-without-characteristic.json',
+ { data: { has_debt_characteristic: 'false' } })
+ .clickElement('.js-facet[data-empty-characteristic]')
+ .checkElementInclude('#coding-rules-total', 208)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-with-memory-efficiency-characteristic.json',
+ { data: { debt_characteristics: 'MEMORY_EFFICIENCY' } })
+ .clickElement('.js-facet[data-value="MEMORY_EFFICIENCY"]')
+ .checkElementInclude('#coding-rules-total', 3);
+ });
+
+ bdd.it('should disable characteristic facet', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-characteristic.json',
+ { data: { facets: 'debt_characteristics' } })
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="PORTABILITY"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-with-portability-characteristic.json',
+ { data: { debt_characteristics: 'PORTABILITY' } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('.js-facet[data-value="PORTABILITY"]')
+ .checkElementInclude('#coding-rules-total', 21)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', 609)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-characteristic.json',
+ { data: { facets: 'debt_characteristics' } })
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="MEMORY_EFFICIENCY"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-with-memory-efficiency-characteristic.json',
+ { data: { debt_characteristics: 'MEMORY_EFFICIENCY' } })
+ .clickElement('.js-facet[data-value="MEMORY_EFFICIENCY"]')
+ .checkElementInclude('#coding-rules-total', 3)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', 609)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-characteristic.json',
+ { data: { facets: 'debt_characteristics' } })
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-empty-characteristic]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-without-characteristic.json',
+ { data: { has_debt_characteristic: 'false' } })
+ .clickElement('.js-facet[data-empty-characteristic]')
+ .checkElementInclude('#coding-rules-total', 208)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="debt_characteristics"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', 609);
+ });
+
+ bdd.it('should show template facet', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementExist('.search-navigator-facet-box-collapsed[data-property="is_template"]')
+
+ .clickElement('[data-property="is_template"] .js-facet-toggle')
+ .checkElementExist('[data-property="is_template"] .js-facet[data-value="true"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-only-templates.json',
+ { data: { 'is_template': 'true' } })
+ .clickElement('[data-property="is_template"] .js-facet[data-value="true"]')
+ .checkElementInclude('#coding-rules-total', 8)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-hide-templates.json',
+ { data: { 'is_template': 'false' } })
+ .clickElement('[data-property="is_template"] .js-facet[data-value="false"]')
+ .checkElementInclude('#coding-rules-total', 7)
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="is_template"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', 609);
+ });
+
+ bdd.it('should show language facet', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromString('/api/languages/list', '{"languages":[{"key":"custom","name":"Custom"}]}',
+ { data: { q: 'custom' } })
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .clickElement('[data-property="languages"] .select2-choice')
+ .checkElementExist('.select2-search')
+ .fillElement('.select2-input', 'custom')
+ .execute(function () {
+ // TODO remove jQuery usage
+ jQuery('.select2-input').trigger('keyup-change');
+ })
+ .checkElementExist('.select2-result')
+ .checkElementInclude('.select2-result', 'Custom')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-with-custom-language.json',
+ { data: { languages: 'custom' } })
+ .execute(function () {
+ // TODO remove jQuery usage
+ jQuery('.select2-result').mouseup();
+ })
+ .checkElementInclude('#coding-rules-total', 13)
+ .checkElementExist('[data-property="languages"] .js-facet.active')
+ .checkElementInclude('[data-property="languages"] .js-facet.active', 'custom')
+ .checkElementInclude('[data-property="languages"] .js-facet.active', '13');
+ });
+
+ bdd.it('should reload results', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', 609)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search2.json')
+ .clickElement('.js-reload')
+ .checkElementInclude('#coding-rules-total', 413);
+ });
+
+ bdd.it('should do a new search', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', 609)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search2.json', { data: { languages: 'java' } })
+ .clickElement('.js-facet[data-value="java"]')
+ .checkElementInclude('#coding-rules-total', 413)
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('.js-new-search')
+ .checkElementInclude('#coding-rules-total', 609);
+ });
+
+ bdd.it('should go back', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromFile('/api/rules/show', 'coding-rules-spec/show.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule.selected')
+ .clickElement('.coding-rule.selected .js-rule')
+ .checkElementExist('.coding-rules-detail-header')
+ .clickElement('.js-back')
+ .checkElementNotExist('.js-back')
+ .checkElementNotExist('.coding-rules-detail-header');
+ });
+
+ bdd.it('should show inheritance facet', function () {
+ return this.remote
+ .open()
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementInclude('#coding-rules-total', '609')
+ .checkElementExist('.search-navigator-facet-box-forbidden[data-property="inheritance"]')
+
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-qprofile.json',
+ { data: { qprofile: 'java-default-with-mojo-conventions-49307' } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementInclude('#coding-rules-total', '407')
+ .checkElementNotExist('.search-navigator-facet-box-forbidden[data-property="inheritance"]')
+
+ .clickElement('[data-property="inheritance"] .js-facet-toggle')
+ .checkElementExist('[data-property="inheritance"] [data-value="NONE"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-not-inherited.json',
+ { data: { inheritance: 'NONE' } })
+ .clickElement('[data-property="inheritance"] [data-value="NONE"]')
+ .checkElementInclude('#coding-rules-total', '103')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-inherited.json',
+ { data: { inheritance: 'INHERITED' } })
+ .clickElement('[data-property="inheritance"] [data-value="INHERITED"]')
+ .checkElementInclude('#coding-rules-total', '101')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-overriden.json',
+ { data: { inheritance: 'OVERRIDES' } })
+ .clickElement('[data-property="inheritance"] [data-value="OVERRIDES"]')
+ .checkElementInclude('#coding-rules-total', '102')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-qprofile2.json',
+ { data: { qprofile: 'java-top-profile-without-formatting-conventions-50037' } })
+ .clickElement('.js-facet[data-value="java-top-profile-without-formatting-conventions-50037"]')
+ .checkElementInclude('#coding-rules-total', '408')
+ .checkElementExist('.search-navigator-facet-box-forbidden[data-property="inheritance"]')
+
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementInclude('#coding-rules-total', '609')
+ .checkElementExist('.search-navigator-facet-box-forbidden[data-property="inheritance"]');
+ });
+
+ bdd.it('should show activation details', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementNotExist('.coding-rule-activation')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clearMocks()
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-actives.json', { data: { activation: true } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementCount('.coding-rule-activation', 2)
+ .checkElementCount('.coding-rule-activation .icon-severity-major', 2)
+ .checkElementCount('.coding-rule-activation .icon-inheritance', 1)
+ .checkElementNotExist('.coding-rules-detail-quality-profile-activate');
+ });
+
+ bdd.it('should activate rule', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-inactive.json',
+ { data: { activation: 'false' } })
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .mockFromString('/api/qualityprofiles/activate_rule', '{}')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementNotExist('.coding-rule-activation')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"] .js-inactive')
+ .checkElementNotExist('.coding-rule-activation .icon-severity-major')
+ .checkElementExist('.coding-rules-detail-quality-profile-activate')
+ .clickElement('.coding-rules-detail-quality-profile-activate')
+ .checkElementExist('.modal')
+ .checkElementExist('#coding-rules-quality-profile-activation-select')
+ .checkElementCount('#coding-rules-quality-profile-activation-select option', 1)
+ .checkElementExist('#coding-rules-quality-profile-activation-severity')
+ .clickElement('#coding-rules-quality-profile-activation-activate')
+ .checkElementExist('.coding-rule-activation .icon-severity-major')
+ .checkElementExist('.coding-rule-activation .icon-severity-major')
+ .checkElementNotExist('.coding-rules-detail-quality-profile-activate')
+ .checkElementExist('.coding-rules-detail-quality-profile-deactivate');
+ });
+
+ bdd.it('should deactivate rule', function () {
+ return this.remote
+ .open()
+ .mockFromString('/api/l10n/index', '{}')
+ .mockFromFile('/api/rules/app', 'coding-rules-spec/app.json')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search.json')
+ .startApp('coding-rules')
+ .checkElementExist('.coding-rule')
+ .checkElementNotExist('.coding-rule-activation')
+ .clickElement('[data-property="qprofile"] .js-facet-toggle')
+ .checkElementExist('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .clearMocks()
+ .mockFromString('/api/qualityprofiles/deactivate_rule', '{}')
+ .mockFromFile('/api/rules/search', 'coding-rules-spec/search-active.json', { data: { activation: true } })
+ .clickElement('.js-facet[data-value="java-default-with-mojo-conventions-49307"]')
+ .checkElementExist('.coding-rule-activation .icon-severity-major')
+ .checkElementNotExist('.coding-rules-detail-quality-profile-activate')
+ .clickElement('.coding-rules-detail-quality-profile-deactivate')
+ .checkElementExist('button[data-confirm="yes"]')
+ .clickElement('button[data-confirm="yes"]')
+ .checkElementNotExist('.coding-rule-activation .icon-severity-major')
+ .checkElementNotExist('.coding-rule-activation .icon-severity-major')
+ .checkElementExist('.coding-rules-detail-quality-profile-activate')
+ .checkElementNotExist('.coding-rules-detail-quality-profile-deactivate');
+ });
+ });
+});
diff --git a/server/sonar-web/test/medium/computation.spec.js b/server/sonar-web/test/medium/computation.spec.js
index f6af86f4654..4884204fbf1 100644
--- a/server/sonar-web/test/medium/computation.spec.js
+++ b/server/sonar-web/test/medium/computation.spec.js
@@ -30,7 +30,7 @@ define(function (require) {
.startApp('computation', { urlRoot: '/test/medium/base.html' })
.checkElementCount('#computation-list li[data-id]', 2)
.clearMocks()
- .mockFromFile('/api/computation/history', 'computation-spec/history-big-2.json', { data: { p: '2' } })
+ .mockFromFile('/api/computation/history', 'computation-spec/history-big-2.json', { data: { p: 2 } })
.clickElement('#computation-fetch-more')
.checkElementCount('#computation-list li[data-id]', 3);
});
diff --git a/travis.sh b/travis.sh
index f616c39006f..58de4bc9953 100755
--- a/travis.sh
+++ b/travis.sh
@@ -33,7 +33,7 @@ MYSQL)
WEB)
export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
+ /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
wget http://selenium-release.storage.googleapis.com/2.46/selenium-server-standalone-2.46.0.jar
nohup java -jar selenium-server-standalone-2.46.0.jar &
sleep 3