@@ -108,6 +108,7 @@ public class ProcessProperties { | |||
SONAR_UPDATECENTER_ACTIVATE("sonar.updatecenter.activate", "true"), | |||
SONARCLOUD_ENABLED("sonar.sonarcloud.enabled", "false"), | |||
SONARCLOUD_HOMEPAGE_URL("sonar.homepage.url", ""), | |||
SONAR_PRISMIC_ACCESS_TOKEN("sonar.prismic.accessToken", ""), | |||
SONAR_ANALYTICS_TRACKING_ID("sonar.analytics.trackingId", ""), | |||
ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS("sonar.onboardingTutorial.showToNewUsers", "true"), |
@@ -52,6 +52,7 @@ import static org.sonar.core.config.WebConstants.SONAR_LF_GRAVATAR_SERVER_URL; | |||
import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_URL; | |||
import static org.sonar.core.config.WebConstants.SONAR_LF_LOGO_WIDTH_PX; | |||
import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED; | |||
import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_HOMEPAGE_URL; | |||
import static org.sonar.process.ProcessProperties.Property.SONAR_ANALYTICS_TRACKING_ID; | |||
import static org.sonar.process.ProcessProperties.Property.SONAR_PRISMIC_ACCESS_TOKEN; | |||
import static org.sonar.process.ProcessProperties.Property.SONAR_UPDATECENTER_ACTIVATE; | |||
@@ -103,6 +104,7 @@ public class GlobalAction implements NavigationWsAction, Startable { | |||
if (isOnSonarCloud) { | |||
this.systemSettingValuesByKey.put(SONAR_PRISMIC_ACCESS_TOKEN.getKey(), config.get(SONAR_PRISMIC_ACCESS_TOKEN.getKey()).orElse(null)); | |||
this.systemSettingValuesByKey.put(SONAR_ANALYTICS_TRACKING_ID.getKey(), config.get(SONAR_ANALYTICS_TRACKING_ID.getKey()).orElse(null)); | |||
this.systemSettingValuesByKey.put(SONARCLOUD_HOMEPAGE_URL.getKey(), config.get(SONARCLOUD_HOMEPAGE_URL.getKey()).orElse(null)); | |||
} | |||
} | |||
@@ -127,16 +127,18 @@ public class GlobalActionTest { | |||
} | |||
@Test | |||
public void return_prismic_setting_on_sonarcloud_only() { | |||
public void return_sonarcloud_settings() { | |||
settings.setProperty("sonar.sonarcloud.enabled", true); | |||
settings.setProperty("sonar.prismic.accessToken", "secret"); | |||
settings.setProperty("sonar.analytics.trackingId", "ga_id"); | |||
settings.setProperty("sonar.homepage.url", "https://s3/homepage.json"); | |||
init(); | |||
assertJson(call()).isSimilarTo("{" + | |||
" \"settings\": {" + | |||
" \"sonar.prismic.accessToken\": \"secret\"" + | |||
" \"sonar.analytics.trackingId\": \"ga_id\"" + | |||
" \"sonar.prismic.accessToken\": \"secret\"," + | |||
" \"sonar.analytics.trackingId\": \"ga_id\"," + | |||
" \"sonar.homepage.url\": \"https://s3/homepage.json\"" + | |||
" }" + | |||
"}"); | |||
} |
@@ -25,6 +25,3 @@ coverage/ | |||
# eslint | |||
eslint-report.json | |||
# SonarCloud homepage file | |||
public/json/homepage.json |
@@ -19,6 +19,7 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import Helmet from 'react-helmet'; | |||
import { connect } from 'react-redux'; | |||
import { FixedNavBar, TopNavBar } from './components/NavBars'; | |||
import FeaturedProjects from './components/FeaturedProjects'; | |||
import Footer from './components/Footer'; | |||
@@ -26,32 +27,48 @@ import { Languages } from './components/Languages'; | |||
import LoginButtons from './components/LoginButtons'; | |||
import Statistics from './components/Statistics'; | |||
import { requestHomepageData, HomepageData, FeaturedProject } from './utils'; | |||
import { getGlobalSettingValue, Store } from '../../../store/rootReducer'; | |||
import { addWhitePageClass, removeWhitePageClass } from '../../../helpers/pages'; | |||
import { getBaseUrl } from '../../../helpers/urls'; | |||
import './new_style.css'; | |||
interface Props { | |||
homePageDataUrl?: string; | |||
} | |||
interface State { | |||
data?: HomepageData; | |||
} | |||
export default class Home extends React.PureComponent<{}, State> { | |||
export class Home extends React.PureComponent<Props, State> { | |||
mounted = false; | |||
state: State = {}; | |||
componentDidMount() { | |||
this.mounted = true; | |||
addWhitePageClass(); | |||
this.fetchData(); | |||
} | |||
componentWillUnmount() { | |||
removeWhitePageClass(); | |||
this.mounted = false; | |||
} | |||
fetchData = () => { | |||
requestHomepageData() | |||
.then(data => this.setState({ data })) | |||
.catch(() => { | |||
/* Fail silently */ | |||
}); | |||
const { homePageDataUrl } = this.props; | |||
if (homePageDataUrl) { | |||
requestHomepageData(homePageDataUrl).then( | |||
data => { | |||
if (this.mounted) { | |||
this.setState({ data }); | |||
} | |||
}, | |||
() => { | |||
/* Fail silently */ | |||
} | |||
); | |||
} | |||
}; | |||
render() { | |||
@@ -84,6 +101,15 @@ export default class Home extends React.PureComponent<{}, State> { | |||
} | |||
} | |||
const mapStateToProps = (state: Store) => { | |||
const homePageDataUrl = getGlobalSettingValue(state, 'sonar.homepage.url'); | |||
return { | |||
homePageDataUrl: homePageDataUrl && homePageDataUrl.value | |||
}; | |||
}; | |||
export default connect(mapStateToProps)(Home); | |||
function PageBackgroundHeader() { | |||
return ( | |||
<div className="sc-header-background"> |
@@ -21,6 +21,8 @@ import * as React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Home from '../Home'; | |||
import { waitAndUpdate } from '../../../../helpers/testUtils'; | |||
import { mockStore } from '../../../../helpers/testMocks'; | |||
import { requestHomepageData } from '../utils'; | |||
jest.mock('../utils', () => { | |||
const utils = require.requireActual('../utils'); | |||
@@ -53,8 +55,13 @@ jest.mock('../utils', () => { | |||
return utils; | |||
}); | |||
beforeEach(() => { | |||
jest.clearAllMocks(); | |||
}); | |||
it('should render', async () => { | |||
const wrapper = shallow(<Home />); | |||
const wrapper = shallowRender('https://static.sonarcloud.io/homepage.json'); | |||
expect(requestHomepageData).toBeCalled(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(wrapper.find('PageBackgroundHeader').dive()).toMatchSnapshot(); | |||
@@ -65,3 +72,24 @@ it('should render', async () => { | |||
expect(wrapper.find('Stats').dive()).toMatchSnapshot(); | |||
expect(wrapper.find('Projects').dive()).toMatchSnapshot(); | |||
}); | |||
it('should not render real Stats and Projects', () => { | |||
const wrapper = shallowRender(undefined); | |||
expect(requestHomepageData).not.toBeCalled(); | |||
expect(wrapper.find('Stats').dive()).toMatchSnapshot(); | |||
expect(wrapper.find('Projects').dive()).toMatchSnapshot(); | |||
}); | |||
function shallowRender(homePageDataUrl: string | undefined) { | |||
return shallow(<Home />, { | |||
context: { | |||
store: mockStore({ | |||
settingsApp: { | |||
values: { | |||
global: { 'sonar.homepage.url': { key: 'sonar.homepage.url', value: homePageDataUrl } } | |||
} | |||
} | |||
}) | |||
} | |||
}).dive(); | |||
} |
@@ -1,5 +1,42 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`should not render real Stats and Projects 1`] = ` | |||
<div | |||
className="sc-section sc-columns" | |||
> | |||
<div | |||
className="sc-column sc-column-full" | |||
> | |||
<h3> | |||
Over 3,000 Projects | |||
<br /> | |||
Continuously Analyzed | |||
</h3> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should not render real Stats and Projects 2`] = ` | |||
<div | |||
className="sc-section sc-columns" | |||
> | |||
<div | |||
className="sc-column sc-column-full" | |||
> | |||
<h6 | |||
className="spacer-bottom" | |||
> | |||
Come join the fun, it’s entirely free for open-source projects! | |||
</h6> | |||
<div | |||
className="sc-spacer-bottom" | |||
> | |||
<LoginButtons /> | |||
</div> | |||
</div> | |||
</div> | |||
`; | |||
exports[`should render 1`] = ` | |||
<div | |||
className="global-container" |
@@ -17,6 +17,8 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { getJSON } from '../../../helpers/request'; | |||
export interface FeaturedProject { | |||
key: string; | |||
avatarUrl: string | null; | |||
@@ -45,10 +47,6 @@ export interface HomepageData { | |||
newPullRequests7d: number; | |||
} | |||
export function requestHomepageData(): Promise<HomepageData> { | |||
return fetch('/json/homepage.json').then(response => response.json()); | |||
} | |||
export const LANGUAGES = [ | |||
{ name: 'Java', file: 'java.svg', width: 65 }, | |||
{ name: 'JavaScript', file: 'js.svg', width: 60 }, | |||
@@ -74,3 +72,7 @@ export const LANGUAGES = [ | |||
{ name: 'XML', file: 'xml.svg', width: 67 }, | |||
{ name: 'COBOL', file: 'cobol.svg', width: 65 } | |||
]; | |||
export function requestHomepageData(url: string): Promise<HomepageData> { | |||
return getJSON(url); | |||
} |