@@ -0,0 +1,12 @@ | |||
package com.sonar.it.samples.modules.b1; | |||
public class HelloB1 { | |||
private int i; | |||
private HelloB1() { | |||
} | |||
public void hello() { | |||
System.out.println("hello" + " world"); | |||
} | |||
} |
@@ -0,0 +1,5 @@ | |||
sonar.projectKey=sample-with-root-dir | |||
sonar.projectName=Sample With Root Dir | |||
sonar.projectVersion=1.0-SNAPSHOT | |||
sonar.sources=. | |||
sonar.language=xoo |
@@ -0,0 +1,16 @@ | |||
package sample; | |||
public class Sample { | |||
public Sample(int i) { | |||
int j = i++; | |||
} | |||
private String myMethod() { | |||
if (foo == bar) { | |||
return "hello"; | |||
} else { | |||
throw new IllegalStateException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
ncloc:13 | |||
#Used by dashboard/widgets tests | |||
complexity:3 | |||
complexity_in_classes:3 | |||
classes:1 | |||
comment_lines:3 | |||
public_api:5 | |||
public_undocumented_api:2 | |||
duplicated_files:1 | |||
duplicated_blocks:2 | |||
duplicated_lines:3 |
@@ -44,6 +44,16 @@ public class ProjectCodeTest { | |||
new SeleneseTest(selenese).runOn(orchestrator); | |||
} | |||
@Test | |||
public void code_page_should_expand_root_dir() throws Exception { | |||
executeBuild("shared/xoo-sample-with-root-dir", "project-for-code-root-dir", "Project For Code"); | |||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("code_page_should_expand_root_dir", | |||
"/projectServices/ProjectCodeTest/code_page_should_expand_root_dir.html" | |||
).build(); | |||
new SeleneseTest(selenese).runOn(orchestrator); | |||
} | |||
private void executeBuild(String projectLocation, String projectKey, String projectName) { | |||
orchestrator.executeBuild( | |||
SonarRunner.create(projectDir(projectLocation)) |
@@ -0,0 +1,30 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||
<link rel="selenium.base" href="http://localhost:49506"/> | |||
<title>code_page_should_expand_root_dir</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr> | |||
<td rowspan="1" colspan="3">code_page_should_expand_root_dir</td> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/sonar/code?id=project-for-code-root-dir</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>waitForText</td> | |||
<td>css=#content</td> | |||
<td>*Hello.xoo*</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</body> | |||
</html> |
@@ -100,6 +100,23 @@ function getPath (componentKey) { | |||
return '/' + encodeURIComponent(componentKey); | |||
} | |||
function expandRootDir (components) { | |||
const rootDir = components.find(component => component.qualifier === 'DIR' && component.name === '/'); | |||
if (rootDir) { | |||
return getChildren(rootDir.key, METRICS_WITH_COVERAGE).then(files => { | |||
return _.without([...components, ...files], rootDir); | |||
}); | |||
} else { | |||
return components; | |||
} | |||
} | |||
function skipRootDir (breadcrumbs) { | |||
return breadcrumbs.filter(component => { | |||
return !(component.qualifier === 'DIR' && component.name === '/'); | |||
}); | |||
} | |||
function retrieveComponentBase (componentKey, candidate) { | |||
return candidate ? | |||
Promise.resolve(candidate) : | |||
@@ -109,13 +126,15 @@ function retrieveComponentBase (componentKey, candidate) { | |||
function retrieveComponentChildren (componentKey, candidate) { | |||
return candidate && candidate.children ? | |||
Promise.resolve(candidate.children) : | |||
getChildren(componentKey, METRICS_WITH_COVERAGE); | |||
getChildren(componentKey, METRICS_WITH_COVERAGE).then(expandRootDir); | |||
} | |||
function retrieveComponentBreadcrumbs (componentKey, candidate) { | |||
return candidate && candidate.breadcrumbs ? | |||
Promise.resolve(candidate.breadcrumbs) : | |||
getComponentNavigation(componentKey).then(navigation => navigation.breadcrumbs); | |||
getComponentNavigation(componentKey) | |||
.then(navigation => navigation.breadcrumbs) | |||
.then(skipRootDir); | |||
} | |||
function retrieveComponent (componentKey, bucket) { |
@@ -46,6 +46,28 @@ function merge (components, candidate) { | |||
return [...(_.without(components, found)), newEntry]; | |||
} | |||
function compare (a, b) { | |||
if (a === b) { | |||
return 0; | |||
} | |||
return a > b ? 1 : -1; | |||
} | |||
function sortChildren (children) { | |||
const QUALIFIERS_ORDER = ['DIR', 'FIL', 'UTS']; | |||
const temp = [...children]; | |||
temp.sort((a, b) => { | |||
const qualifierA = QUALIFIERS_ORDER.indexOf(a.qualifier); | |||
const qualifierB = QUALIFIERS_ORDER.indexOf(b.qualifier); | |||
if (qualifierA !== qualifierB) { | |||
return compare(qualifierA, qualifierB); | |||
} else { | |||
return compare(a.name, b.name); | |||
} | |||
}); | |||
return temp; | |||
} | |||
export const initialState = { | |||
fetching: false, | |||
@@ -70,7 +92,7 @@ export function current (state = initialState, action) { | |||
return { ...state, coverageMetric, baseBreadcrumbs }; | |||
case BROWSE: | |||
const baseComponent = hasSourceCode(action.component) ? null : action.component; | |||
const components = hasSourceCode(action.component) ? null : _.sortBy(action.children, 'name'); | |||
const components = hasSourceCode(action.component) ? null : sortChildren(action.children); | |||
const baseBreadcrumbsLength = state.baseBreadcrumbs.length; | |||
const breadcrumbs = action.breadcrumbs.slice(baseBreadcrumbsLength); | |||
const sourceViewer = hasSourceCode(action.component) ? action.component : null; |
@@ -72,6 +72,20 @@ describe('Code :: Store', () => { | |||
.to.deep.equal(componentsAfter); | |||
}); | |||
it('should sort components by qualifier and then by name', () => { | |||
const component = {}; | |||
const componentsBefore = [ | |||
{ key: 'A', name: 'A', qualifier: 'FIL' }, | |||
{ key: 'B', name: 'B', qualifier: 'DIR' } | |||
]; | |||
const componentsAfter = [ | |||
{ key: 'B', name: 'B', qualifier: 'DIR' }, | |||
{ key: 'A', name: 'A', qualifier: 'FIL' } | |||
]; | |||
expect(current(initialState, browseAction(component, componentsBefore)).components) | |||
.to.deep.equal(componentsAfter); | |||
}); | |||
it('should not be set for components with source code', () => { | |||
const file = { qualifier: 'FIL' }; | |||
expect(current(initialState, browseAction(file, exampleComponents)).components) |