From: Stas Vilchik Date: Wed, 10 Dec 2014 14:22:28 +0000 (+0100) Subject: SONAR-5884 Add highlighted line to the permalink X-Git-Tag: latest-silver-master-#65~582 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=19c8682a1a00a1df1c80792f041cfa8517044720;p=sonarqube.git SONAR-5884 Add highlighted line to the permalink --- diff --git a/server/sonar-web/src/main/js/source-viewer/header.js b/server/sonar-web/src/main/js/source-viewer/header.js index 2b1c09aac85..ce88070a4a7 100644 --- a/server/sonar-web/src/main/js/source-viewer/header.js +++ b/server/sonar-web/src/main/js/source-viewer/header.js @@ -52,9 +52,12 @@ define([ }, getPermalink: function () { - //TODO Line permalink var query = 'id=' + encodeURIComponent(this.model.get('key')), windowParams = 'resizable=1,scrollbars=1,status=1'; + console.log(this.options.viewer); + if (this.options.viewer.highlightedLine) { + query = query + '&line=' + this.options.viewer.highlightedLine; + } window.open(baseUrl + '/component/index?' + query, this.model.get('name'), windowParams); }, diff --git a/server/sonar-web/src/main/js/source-viewer/viewer.js b/server/sonar-web/src/main/js/source-viewer/viewer.js index e5f9d49d005..2f596ef7c51 100644 --- a/server/sonar-web/src/main/js/source-viewer/viewer.js +++ b/server/sonar-web/src/main/js/source-viewer/viewer.js @@ -68,11 +68,15 @@ define([ this.loadSourceBeforeThrottled = _.throttle(this.loadSourceBefore, 1000); this.loadSourceAfterThrottled = _.throttle(this.loadSourceAfter, 1000); this.scrollTimer = null; + this.highlightedLine = null; this.listenTo(this, 'loaded', this.onLoaded); }, renderHeader: function () { - this.headerRegion.show(new HeaderView({model: this.model})); + this.headerRegion.show(new HeaderView({ + viewer: this, + model: this.model + })); }, onRender: function () { @@ -376,12 +380,14 @@ define([ }, removeHighlighting: function () { + this.highlightedLine = null; this.$('.' + HIGHLIGHTED_ROW_CLASS).removeClass(HIGHLIGHTED_ROW_CLASS); }, highlightLine: function (line) { var row = this.$('.source-line[data-line-number=' + line + ']'); this.removeHighlighting(); + this.highlightedLine = line; row.addClass(HIGHLIGHTED_ROW_CLASS); return this; }, diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js new file mode 100644 index 00000000000..1b39fdbbabe --- /dev/null +++ b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window-with-line.js @@ -0,0 +1,47 @@ +/* global casper:false */ + +var lib = require('../lib'), + testName = lib.testName('Source Viewer'); + +lib.initMessages(); +lib.changeWorkingDirectory('source-viewer-should-open-in-new-window'); + + +casper.test.begin(testName('source-viewer-should-open-in-new-window-with-line'), function (test) { + casper + .start(lib.buildUrl('source-viewer'), function () { + lib.setDefaultViewport(); + + lib.mockRequest('/api/l10n/index', '{}'); + lib.mockRequestFromFile('/api/components/app', 'api-components-app.json'); + lib.mockRequestFromFile('/api/sources/lines', 'api-sources-lines.json'); + lib.mockRequestFromFile('/api/issues/search', 'api-issues-search.json'); + }) + + .then(function () { + casper.waitForSelector('.source-line'); + }) + + .then(function () { + casper.click('.source-line-number[data-line-number="6"]'); + casper.waitForSelector('.bubble-popup'); + }) + + .then(function () { + casper.click('.js-actions'); + casper.waitForSelector('.js-new-window', function () { + casper.click('.js-new-window'); + }); + }) + + .then(function () { + casper.withPopup(/Simplest\.java/, function () { + this.test.assertUrlMatch('test:fake-project-for-tests:src/main/java/foo/Simplest.java'); + this.test.assertUrlMatch('line=6'); + }); + }) + + .run(function () { + test.done(); + }); +}); diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js new file mode 100644 index 00000000000..56cb84f2855 --- /dev/null +++ b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window.js @@ -0,0 +1,41 @@ +/* global casper:false */ + +var lib = require('../lib'), + testName = lib.testName('Source Viewer'); + +lib.initMessages(); +lib.changeWorkingDirectory('source-viewer-should-open-in-new-window'); + + +casper.test.begin(testName('source-viewer-should-open-in-new-window'), function (test) { + casper + .start(lib.buildUrl('source-viewer'), function () { + lib.setDefaultViewport(); + + lib.mockRequest('/api/l10n/index', '{}'); + lib.mockRequestFromFile('/api/components/app', 'api-components-app.json'); + lib.mockRequestFromFile('/api/sources/lines', 'api-sources-lines.json'); + lib.mockRequestFromFile('/api/issues/search', 'api-issues-search.json'); + }) + + .then(function () { + casper.waitForSelector('.source-line'); + }) + + .then(function () { + casper.click('.js-actions'); + casper.waitForSelector('.js-new-window', function () { + casper.click('.js-new-window'); + }); + }) + + .then(function () { + casper.withPopup(/Simplest\.java/, function () { + this.test.assertUrlMatch('test:fake-project-for-tests:src/main/java/foo/Simplest.java'); + }); + }) + + .run(function () { + test.done(); + }); +}); diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json new file mode 100644 index 00000000000..25b2e1e70f1 --- /dev/null +++ b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-components-app.json @@ -0,0 +1,95 @@ +{ + "key": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "path": "src/main/java/foo/Simplest.java", + "name": "Simplest.java", + "longName": "src/main/java/foo/Simplest.java", + "q": "FIL", + "project": "test:fake-project-for-tests", + "projectName": "Fake Project for Tests", + "fav": false, + "canMarkAsFavourite": true, + "canBulkChange": true, + "canCreateManualIssue": true, + "periods": [ + [ + 1, + "since previous analysis (2014 Dec 09)", + "2014-12-09T10:47:33+0100" + ], + [ + 2, + "over 365 days (2014 Dec 09)", + "2014-12-09T10:47:33+0100" + ] + ], + "severities": [ + [ + "MINOR", + "Minor", + 1 + ], + [ + "MAJOR", + "Major", + 4 + ] + ], + "rules": [ + [ + "squid:IndentationCheck", + "Source code should be correctly indented", + 2 + ], + [ + "squid:S1118", + "Utility classes should not have a public constructor", + 1 + ], + [ + "squid:S00105", + "Tabulation characters should not be used", + 1 + ], + [ + "squid:S106", + "System.out and System.err should not be used as loggers", + 1 + ] + ], + "measures": { + "fNcloc": "8", + "fCoverage": "75.0%", + "fDebt": "44min", + "fSqaleRating": "C", + "fSqaleDebtRatio": "18.3%", + "fIssues": "5", + "fMinorIssues": "1", + "fMajorIssues": "4" + }, + "tabs": [ + "scm", + "coverage" + ], + "manual_rules": [ + { + "key": "manual:api", + "name": "API" + }, + { + "key": "manual:design", + "name": "Design" + }, + { + "key": "manual:error_handling", + "name": "Error handling" + }, + { + "key": "manual:performance", + "name": "Performance" + }, + { + "key": "manual:sql_pitfalls", + "name": "SQL Pitfall" + } + ] +} diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json new file mode 100644 index 00000000000..73d6a9fcf3d --- /dev/null +++ b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-issues-search.json @@ -0,0 +1,234 @@ +{ + "total": 5, + "p": 1, + "ps": 100, + "projects": [ + { + "uuid": "e07e9bed-f45d-4538-a5e8-77031c1ecae7", + "key": "test:fake-project-for-tests", + "id": 36125, + "qualifier": "TRK", + "name": "Fake Project for Tests", + "longName": "Fake Project for Tests" + } + ], + "components": [ + { + "uuid": "b4248001-df0c-436a-8acd-a152809b8a23", + "key": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "id": 36129, + "enabled": true, + "qualifier": "FIL", + "name": "Simplest.java", + "longName": "src/main/java/foo/Simplest.java", + "path": "src/main/java/foo/Simplest.java", + "projectId": 36125, + "subProjectId": 36125 + }, + { + "uuid": "e07e9bed-f45d-4538-a5e8-77031c1ecae7", + "key": "test:fake-project-for-tests", + "id": 36125, + "enabled": true, + "qualifier": "TRK", + "name": "Fake Project for Tests", + "longName": "Fake Project for Tests" + } + ], + "issues": [ + { + "key": "91b13078-6f69-4b51-ab0f-8fd0bc391532", + "component": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "componentId": 36129, + "project": "test:fake-project-for-tests", + "rule": "squid:S00105", + "status": "OPEN", + "severity": "MINOR", + "message": "Replace all tab characters in this file by sequences of white-spaces.", + "debt": "2min", + "creationDate": "2014-12-09T10:47:33+0100", + "updateDate": "2014-12-09T10:47:33+0100", + "fUpdateAge": "3 hours", + "actions": [ + "comment", + "assign", + "assign_to_me", + "plan", + "set_severity" + ], + "transitions": [ + "confirm", + "resolve", + "falsepositive" + ] + }, + { + "key": "c18ae6fa-fac7-46b5-bd71-feef7906b05a", + "component": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "componentId": 36129, + "project": "test:fake-project-for-tests", + "rule": "squid:S1118", + "status": "OPEN", + "severity": "MAJOR", + "message": "Add a private constructor to hide the implicit public one.", + "line": 6, + "debt": "30min", + "creationDate": "2014-12-09T10:47:33+0100", + "updateDate": "2014-12-09T10:47:33+0100", + "fUpdateAge": "3 hours", + "actions": [ + "comment", + "assign", + "assign_to_me", + "plan", + "set_severity" + ], + "transitions": [ + "confirm", + "resolve", + "falsepositive" + ] + }, + { + "key": "816282ec-0ca9-4d03-b8bc-22b515496fe4", + "component": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "componentId": 36129, + "project": "test:fake-project-for-tests", + "rule": "squid:IndentationCheck", + "status": "OPEN", + "severity": "MAJOR", + "message": "Make this line start at column 3.", + "line": 8, + "debt": "1min", + "creationDate": "2014-12-09T10:47:33+0100", + "updateDate": "2014-12-09T10:47:33+0100", + "fUpdateAge": "3 hours", + "actions": [ + "comment", + "assign", + "assign_to_me", + "plan", + "set_severity" + ], + "transitions": [ + "confirm", + "resolve", + "falsepositive" + ] + }, + { + "key": "0229497b-a613-48f3-83ed-2b98983e5e60", + "component": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "componentId": 36129, + "project": "test:fake-project-for-tests", + "rule": "squid:IndentationCheck", + "status": "OPEN", + "severity": "MAJOR", + "message": "Make this line start at column 5.", + "line": 10, + "debt": "1min", + "creationDate": "2014-12-09T10:47:33+0100", + "updateDate": "2014-12-09T10:47:33+0100", + "fUpdateAge": "3 hours", + "actions": [ + "comment", + "assign", + "assign_to_me", + "plan", + "set_severity" + ], + "transitions": [ + "confirm", + "resolve", + "falsepositive" + ] + }, + { + "key": "896ccfe0-bb85-4155-be1f-1aaece716539", + "component": "test:fake-project-for-tests:src/main/java/foo/Simplest.java", + "componentId": 36129, + "project": "test:fake-project-for-tests", + "rule": "squid:S106", + "status": "OPEN", + "severity": "MAJOR", + "message": "Replace this usage of System.out or System.err by a logger.", + "line": 12, + "debt": "10min", + "creationDate": "2014-12-09T10:47:33+0100", + "updateDate": "2014-12-09T10:47:33+0100", + "fUpdateAge": "3 hours", + "actions": [ + "comment", + "assign", + "assign_to_me", + "plan", + "set_severity" + ], + "transitions": [ + "confirm", + "resolve", + "falsepositive" + ] + } + ], + "rules": [ + { + "key": "squid:IndentationCheck", + "name": "Source code should be correctly indented", + "lang": "java", + "desc": "

\nProper indentation is a simple and effective way to improve the code's readability.\nConsistent indentation among developers also reduces the differences that are committed to source control systems, making code reviews easier.\n

\n\n

The following code illustrates this rule with an indentation level of 2:

\n\n
\nclass Foo {\n  public int a; // Compliant\npublic int b;   // Non-Compliant\n}\n
", + "status": "READY", + "langName": "Java" + }, + { + "key": "squid:S1118", + "name": "Utility classes should not have a public constructor", + "lang": "java", + "desc": "

\nUtility classes, which are a collection of static members, are not meant to be instantiated.\nThey should therefore not have public constructors.\n

\n\n

\nJava adds an implicit public constructor to every class which does not define at least one explicitly.\nHence, at least one non-public constructor should be defined.\n

\n\n

The following code:

\n\n
\nclass StringUtils { // Non-Compliant\n\n  public static String concatenate(String s1, String s2) {\n    return s1 + s2;\n  }\n\n}\n
\n\n

should be refactored into:

\n\n
\nclass StringUtils { // Compliant\n\n  private StringUtils() {\n  }\n\n  public static String concatenate(String s1, String s2) {\n    return s1 + s2;\n  }\n\n}\n
", + "status": "READY", + "langName": "Java" + }, + { + "key": "squid:S00105", + "name": "Tabulation characters should not be used", + "lang": "java", + "desc": "

\nDevelopers should not need to configure the tab width of their text editors in order to be able to read source code.\nSo the use of tabulation character must be banned.\n

", + "status": "READY", + "langName": "Java" + }, + { + "key": "squid:S106", + "name": "System.out and System.err should not be used as loggers", + "lang": "java", + "desc": "

Two important requirements must be fulfilled when logging messages:

\n\n\n\n

\nIf a program directly writes to the standard output, there is absolutely no way to comply with these requirements.\nThat's why defining and using a dedicated logger is highly recommended.\n

\n\n

\nThe following code snippet illustrates this rule:\n

\n\n
\nSystem.out.println(\"My Message\");  // Non-Compliant\n\nlogger.log(\"My Message\");          // Compliant\n
", + "status": "READY", + "langName": "Java" + } + ], + "users": [ + { + "login": "admin", + "name": "Admin Admin", + "active": true, + "email": "admin@sonarsource.com" + } + ], + "languages": [ + { + "key": "js", + "name": "JavaScript" + }, + { + "key": "java", + "name": "Java" + } + ], + "maxResultsReached": false, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 5, + "fTotal": "5", + "pages": 1 + } +} diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json new file mode 100644 index 00000000000..b095d82408f --- /dev/null +++ b/server/sonar-web/src/main/js/tests/e2e/tests/source-viewer-should-open-in-new-window/api-sources-lines.json @@ -0,0 +1,130 @@ +{ + "sources": [ + { + "line": 1, + "code": "package foo;", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 2, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 3, + "code": "/**", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "37acee5ff6e67cdb501c08a656fbabf21160b052", + "scmDate": "2013-09-19T15:37:05+0200" + }, + { + "line": 4, + "code": " * Simple class", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "37acee5ff6e67cdb501c08a656fbabf21160b052", + "scmDate": "2013-09-19T15:37:05+0200" + }, + { + "line": 5, + "code": " */", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "37acee5ff6e67cdb501c08a656fbabf21160b052", + "scmDate": "2013-09-19T15:37:05+0200" + }, + { + "line": 6, + "code": "public class Simplest {", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 7, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 8, + "code": " public static int add(int a, int b) {", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 9, + "code": " \t// introduce a variable that is not needed - just to get a violation", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "322e4e8b3cb54a39651f563273745e6ee737fb3e", + "scmDate": "2013-10-15T16:14:22+0200" + }, + { + "line": 10, + "code": " \tint result = a + b;", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "322e4e8b3cb54a39651f563273745e6ee737fb3e", + "scmDate": "2013-10-15T16:14:22+0200" + }, + { + "line": 11, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "44e0c5b4fc18a006a405d3f3d489896245fab3d1", + "scmDate": "2014-01-09T16:48:59+0100" + }, + { + "line": 12, + "code": " \tSystem.out.println(\"\");", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "44e0c5b4fc18a006a405d3f3d489896245fab3d1", + "scmDate": "2014-01-09T16:48:59+0100" + }, + { + "line": 13, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "44e0c5b4fc18a006a405d3f3d489896245fab3d1", + "scmDate": "2014-01-09T16:48:59+0100" + }, + { + "line": 14, + "code": " return result;", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "322e4e8b3cb54a39651f563273745e6ee737fb3e", + "scmDate": "2013-10-15T16:14:22+0200" + }, + { + "line": 15, + "code": " }", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 16, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 17, + "code": "}", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + }, + { + "line": 18, + "code": "", + "scmAuthor": "fabrice.bellingard@sonarsource.com", + "scmRevision": "f467e9befd3ff15bb1dbf634b0e9b45d44110bac", + "scmDate": "2013-09-16T15:31:49+0200" + } + ] +}