import { Project } from '../types';
interface Props {
+ currentUser: T.CurrentUser;
handleFavorite: (component: string, isFavorite: boolean) => void;
height: number;
organization: T.Organization | undefined;
import { Project } from '../types';
import { formatDuration } from '../utils';
import { getProjectUrl } from '../../../helpers/urls';
+import { isLoggedIn } from '../../../helpers/users';
interface Props {
+ currentUser: T.CurrentUser;
handleFavorite: (component: string, isFavorite: boolean) => void;
height: number;
organization: T.Organization | undefined;
export default class ProjectCardLeak extends React.PureComponent<Props> {
render() {
- const { handleFavorite, height, organization, project } = this.props;
+ const { currentUser, handleFavorite, height, organization, project } = this.props;
const { measures } = project;
const hasTags = project.tags.length > 0;
const periodMs = project.leakPeriodDate ? difference(Date.now(), project.leakPeriodDate) : 0;
? translate('projects.no_new_code_period')
: translate('projects.not_analyzed')}
</span>
- {!project.analysisDate && (
+ {!project.analysisDate && isLoggedIn(currentUser) && (
<Link className="button spacer-left" to={getProjectUrl(project.key)}>
{translate('projects.configure_analysis')}
</Link>
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { Project } from '../types';
import { getProjectUrl } from '../../../helpers/urls';
+import { isLoggedIn } from '../../../helpers/users';
interface Props {
+ currentUser: T.CurrentUser;
handleFavorite: (component: string, isFavorite: boolean) => void;
height: number;
organization: T.Organization | undefined;
export default class ProjectCardOverall extends React.PureComponent<Props> {
render() {
- const { handleFavorite, height, organization, project } = this.props;
+ const { currentUser, handleFavorite, height, organization, project } = this.props;
const { measures } = project;
const hasTags = project.tags.length > 0;
<div className="boxed-group-inner">
<div className="project-card-not-analyzed">
<span className="note">{translate('projects.not_analyzed')}</span>
- <Link className="button spacer-left" to={getProjectUrl(project.key)}>
- {translate('projects.configure_analysis')}
- </Link>
+ {isLoggedIn(currentUser) && (
+ <Link className="button spacer-left" to={getProjectUrl(project.key)}>
+ {translate('projects.configure_analysis')}
+ </Link>
+ )}
</div>
</div>
)}
return (
<div key={key} style={{ ...style, height }}>
<ProjectCard
+ currentUser={this.props.currentUser}
handleFavorite={this.props.handleFavorite}
height={height}
key={project.key}
import { shallow } from 'enzyme';
import { Project } from '../../types';
import ProjectCard from '../ProjectCard';
+import { mockCurrentUser } from '../../../../helpers/testMocks';
const ORGANIZATION = { key: 'org', name: 'org' };
function shallowRender(type?: string) {
return shallow(
<ProjectCard
+ currentUser={mockCurrentUser()}
handleFavorite={jest.fn}
height={200}
organization={ORGANIZATION}
import { shallow } from 'enzyme';
import ProjectCardLeak from '../ProjectCardLeak';
import { Project } from '../../types';
+import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
jest.mock(
'date-fns/difference_in_milliseconds',
visibility: 'public'
};
+const USER_LOGGED_OUT = mockCurrentUser();
+const USER_LOGGED_IN = mockLoggedInUser();
+
it('should display analysis date and leak start date', () => {
const card = shallowRender(PROJECT);
expect(card.find('.project-card-dates').exists()).toBeTruthy();
expect(shallowRender({ ...PROJECT, analysisDate: undefined })).toMatchSnapshot();
});
-function shallowRender(project: Project) {
+it('should display configure analysis button for logged in user', () => {
+ expect(shallowRender({ ...PROJECT, analysisDate: undefined }, USER_LOGGED_IN)).toMatchSnapshot();
+});
+
+function shallowRender(project: Project, user: T.CurrentUser = USER_LOGGED_OUT) {
return shallow(
<ProjectCardLeak
+ currentUser={user}
handleFavorite={jest.fn()}
height={100}
organization={undefined}
import { shallow } from 'enzyme';
import ProjectCardOverall from '../ProjectCardOverall';
import { Project } from '../../types';
+import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
const MEASURES = {
alert_status: 'OK',
visibility: 'public'
};
+const USER_LOGGED_OUT = mockCurrentUser();
+const USER_LOGGED_IN = mockLoggedInUser();
+
it('should display analysis date (and not leak period) when defined', () => {
expect(
shallowRender(PROJECT)
expect(shallowRender({ ...PROJECT, analysisDate: undefined })).toMatchSnapshot();
});
-function shallowRender(project: Project) {
+it('should display configure analysis button for logged in user', () => {
+ expect(shallowRender({ ...PROJECT, analysisDate: undefined }, USER_LOGGED_IN)).toMatchSnapshot();
+});
+
+function shallowRender(project: Project, user: T.CurrentUser = USER_LOGGED_OUT) {
return shallow(
<ProjectCardOverall
+ currentUser={user}
handleFavorite={jest.fn()}
height={100}
organization={undefined}
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should display not analyzed yet 1`] = `
+exports[`should display configure analysis button for logged in user 1`] = `
<div
className="boxed-group project-card"
data-key="foo"
</div>
`;
+exports[`should display not analyzed yet 1`] = `
+<div
+ className="boxed-group project-card"
+ data-key="foo"
+ style={
+ Object {
+ "height": 100,
+ }
+ }
+>
+ <div
+ className="boxed-group-header clearfix"
+ >
+ <div
+ className="project-card-header"
+ >
+ <h2
+ className="project-card-name"
+ >
+ <Connect(ProjectCardOrganization)
+ organization={
+ Object {
+ "key": "org",
+ "name": "org",
+ }
+ }
+ />
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/dashboard",
+ "query": Object {
+ "id": "foo",
+ },
+ }
+ }
+ >
+ Foo
+ </Link>
+ </h2>
+ <div
+ className="project-card-header-right"
+ >
+ <Connect(PrivacyBadge)
+ className="spacer-left"
+ organization={
+ Object {
+ "key": "org",
+ "name": "org",
+ }
+ }
+ qualifier="TRK"
+ tooltipProps={
+ Object {
+ "projectKey": "foo",
+ }
+ }
+ visibility="public"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ className="boxed-group-inner"
+ >
+ <div
+ className="project-card-not-analyzed"
+ >
+ <span
+ className="note"
+ >
+ projects.not_analyzed
+ </span>
+ </div>
+ </div>
+</div>
+`;
+
exports[`should display the leak measures and quality gate 1`] = `
<div
className="boxed-group project-card"
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should display not analyzed yet 1`] = `
+exports[`should display configure analysis button for logged in user 1`] = `
<div
className="boxed-group project-card"
data-key="foo"
</div>
`;
+exports[`should display not analyzed yet 1`] = `
+<div
+ className="boxed-group project-card"
+ data-key="foo"
+ style={
+ Object {
+ "height": 100,
+ }
+ }
+>
+ <div
+ className="boxed-group-header clearfix"
+ >
+ <div
+ className="project-card-header"
+ >
+ <h2
+ className="project-card-name"
+ >
+ <Connect(ProjectCardOrganization)
+ organization={
+ Object {
+ "key": "org",
+ "name": "org",
+ }
+ }
+ />
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/dashboard",
+ "query": Object {
+ "branch": undefined,
+ "id": "foo",
+ },
+ }
+ }
+ >
+ Foo
+ </Link>
+ </h2>
+ <div
+ className="project-card-header-right"
+ >
+ <Connect(PrivacyBadge)
+ className="spacer-left"
+ organization={
+ Object {
+ "key": "org",
+ "name": "org",
+ }
+ }
+ qualifier="TRK"
+ tooltipProps={
+ Object {
+ "projectKey": "foo",
+ }
+ }
+ visibility="public"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ className="boxed-group-inner"
+ >
+ <div
+ className="project-card-not-analyzed"
+ >
+ <span
+ className="note"
+ >
+ projects.not_analyzed
+ </span>
+ </div>
+ </div>
+</div>
+`;
+
exports[`should display the overall measures and quality gate 1`] = `
<div
className="boxed-group project-card"