Skip to content

Commit

Permalink
Merge pull request #301 from atlassian/feature/design-4
Browse files Browse the repository at this point in the history
Feature/design 4 merge to main
  • Loading branch information
anshengxu authored Mar 7, 2024
2 parents 57af85a + ba6badf commit b938467
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 124 deletions.
1 change: 0 additions & 1 deletion app/jenkins-for-jira-ui/src/GlobalStyles.styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export const orderedListItem = css`
padding-left: ${token('space.200')};
counter-increment: item;
margin-bottom: ${token('space.075')};
::before {
background: #F7F8F9;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { css } from '@emotion/css';
import { token } from '@atlaskit/tokens';

export const connectionWizardContentContainer = css`
margin-left: ${token('space.negative.400')};
width: 100%;
text-align: center;
margin-bottom: ${token('space.400')};
#connection-wizard-instruction {
margin-top: ${token('space.400')};
Expand Down Expand Up @@ -33,3 +34,23 @@ export const connectionWizardButton = css`
display: flex;
}
`;

export const connectionInfoContainer = css`
background-color: #F7F8F9;
border: 3px;
display: inline;
width: 330px;
padding: ${token('space.250')};
[role=img] {
margin-right: ${token('space.200')};
}
p {
margin-top: ${token('space.0')};
}
`;

export const iconContainer = css`
margin-right: ${token('space.100')};
`;
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import React, { useEffect } from 'react';
import { cx } from '@emotion/css';
import Button from '@atlaskit/button';
import CheckCircleIcon from '@atlaskit/icon/glyph/check-circle';
import ArrowRightIcon from '@atlaskit/icon/glyph/arrow-right';
import UserAvatarCircleIcon from '@atlaskit/icon/glyph/user-avatar-circle';
import { useHistory, useParams } from 'react-router';
import {
connectionWizardNestedOrderedListItem,
connectionWizardOrderedListItem,
connectionWizardContentContainer,
connectionWizardButton
connectionWizardButton,
connectionInfoContainer,
iconContainer
} from './ConnectionWizard.styles';
import {
connectionFlowContainer,
orderedList,
orderedListItem
connectionFlowContainer
} from '../../GlobalStyles.styles';
import { InProductHelpActionType } from '../InProductHelpDrawer/InProductHelpAction';
import { InProductHelpAction, InProductHelpActionType } from '../InProductHelpDrawer/InProductHelpAction';
import { ConnectionFlowHeader } from './ConnectionFlowHeader';
import { InfoPanel } from '../InfoPanel/InfoPanel';
import { AnalyticsEventTypes, AnalyticsScreenEventsEnum } from '../../common/analytics/analytics-events';
import { AnalyticsClient } from '../../common/analytics/analytics-client';
import { CONNECTION_WIZARD_SCREEN_NAME } from '../../common/constants';
Expand Down Expand Up @@ -47,40 +46,33 @@ const ConnectionWizard = (): JSX.Element => {

<div className={cx(connectionWizardContentContainer)}>
<p id="connection-wizard-instruction">To complete this connection you'll need:</p>

<ol className={cx(orderedList)}>
<li className={cx(orderedListItem, connectionWizardOrderedListItem)}>An active Jenkins server</li>
<li className={cx(orderedListItem, connectionWizardOrderedListItem)}>Team knowledge</li>
<p className={cx(connectionWizardNestedOrderedListItem)}>
How your teams use Jenkins
</p>
<li
className={cx(orderedListItem, connectionWizardOrderedListItem)}
>
The help of your Jenkins admin
</li>
<p className={cx(connectionWizardNestedOrderedListItem)}>
Unless you're an admin yourself
</div>
<div className={cx(connectionInfoContainer)}>
<div style={{ display: 'flex', marginBottom: '5px' }}>
<div className={cx(iconContainer)}>
<CheckCircleIcon label='' size='small' primaryColor='grey'/>
</div>
<p>An active Jenkins server</p>
</div>
<div style={{ display: 'flex' }}>
<div className={cx(iconContainer)}><UserAvatarCircleIcon label='' size='small' primaryColor='grey'/></div>
<p>The help of your Jenkins admin, unless you're an admin yourself<br/>
<InProductHelpAction
label="What you'll be doing and how your team can help"
type={InProductHelpActionType.HelpLink}
searchQuery={InProductHelpIds.CONNECTION_WIZARD_DISCUSS_WITH_TEAM}
screenName={CONNECTION_WIZARD_SCREEN_NAME}
/>
</p>
</ol>
</div>
</div>

<InfoPanel
content="If this is your first time connecting a Jenkins server, take a few minutes to talk to your team."
iphContainerWidth="340px"
iphLabel="What to discuss with your team before connecting Jenkins"
iphType={InProductHelpActionType.HelpLink}
screenName={CONNECTION_WIZARD_SCREEN_NAME}
searchQuery={InProductHelpIds.CONNECTION_WIZARD_DISCUSS_WITH_TEAM}
/>

<Button
appearance="primary"
className={cx(connectionWizardButton)}
onClick={(e) => handleNavigateToServerNameScreen(e)}
testId="team-gathered"
testId="continue"
>
I've gathered my team
Continue
<ArrowRightIcon label="Continue to next screen" />
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const jenkinsSetupHeader = css`

export const jenkinsSetupContent = css`
font-size: 14px;
color: #626F86;
margin: ${token('space.300')} auto !important;
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ describe('JenkinsSetup Component', () => {
jest.spyOn(fetchGlobalPageUrlModule, 'fetchGlobalPageUrl').mockResolvedValueOnce('https://somesite.atlassian.net/blah');
jest.spyOn(getAllJenkinsServersModule, 'getAllJenkinsServers').mockResolvedValueOnce([]);

const { getByText, queryByText } = render(<JenkinsSetup />);
const { getByText } = render(<JenkinsSetup />);
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
expect(getByText('Connect Jenkins to Jira')).toBeInTheDocument();
expect(queryByText('Server name:')).toBeNull();
});

it('should display the server name', async () => {
it('should have the server name in the Setup Content', async () => {
(fetchGlobalPageUrlModule.fetchSiteName as jest.Mock).mockResolvedValueOnce('https://mocked-site-name.com');

(getJenkinsServerWithSecretModule.getJenkinsServerWithSecret as jest.Mock).mockResolvedValueOnce({
Expand All @@ -89,11 +88,11 @@ describe('JenkinsSetup Component', () => {
render(<JenkinsSetup />);
});

expect(screen.getByText(/Server name:/i)).toBeInTheDocument();
expect(screen.getByText(/Server name:/i)).toHaveTextContent('Mocked Server');
expect(screen.getByText(/To complete the connection for /i)).toBeInTheDocument();
expect(screen.getByText(/To complete the connection for /i)).toHaveTextContent('Mocked Server');
});

it('toggles between "A Jenkins admin is helping me" and "I am the Jenkins admin" views', async () => {
it('toggles between "A Jenkins admin on my team" and "I am a Jenkins admin" views', async () => {
(fetchGlobalPageUrlModule.fetchSiteName as jest.Mock).mockResolvedValueOnce('https://mocked-site-name.com');

(getJenkinsServerWithSecretModule.getJenkinsServerWithSecret as jest.Mock).mockResolvedValueOnce({
Expand All @@ -118,13 +117,13 @@ describe('JenkinsSetup Component', () => {
const { getByText, queryByText } = screen;

await waitFor(() => {
fireEvent.click(getByText('A Jenkins admin is helping me'));
fireEvent.click(getByText('A Jenkins admin on my team'));
expect(getByText('Copy the items below and give them to your Jenkins admin')).toBeInTheDocument();
expect(queryByText('Log in to Jenkins in another window and use the items below to set up your server.')).not.toBeInTheDocument();
});

await waitFor(() => {
fireEvent.click(getByText('I\'m logging into Jenkins myself'));
fireEvent.click(getByText('I am a Jenkins admin'));
expect(queryByText('Copy the items below and give them to your Jenkins admin')).not.toBeInTheDocument();
expect(getByText('Log in to Jenkins in another window and use the items below to set up your server.')).toBeInTheDocument();
});
Expand Down Expand Up @@ -155,7 +154,7 @@ describe('JenkinsSetup Component', () => {
const { getByText, getByTestId } = screen;

await waitFor(() => {
fireEvent.click(getByText('A Jenkins admin is helping me'));
fireEvent.click(getByText('A Jenkins admin on my team'));
});

await act(async () => {
Expand All @@ -173,6 +172,12 @@ describe('JenkinsSetup Component', () => {
fireEvent.click(getByTestId('i-am-the-jenkins-admin'));
});

await act(async () => {
fireEvent.click(getByTestId('site-name-copy-button'));
});

expect(document.execCommand).toHaveBeenCalledWith('copy');

await act(async () => {
fireEvent.click(getByTestId('copy-webhook-url'));
});
Expand All @@ -186,7 +191,7 @@ describe('JenkinsSetup Component', () => {
expect(document.execCommand).toHaveBeenCalledWith('copy');
});

it('displays "Next" button when either "A Jenkins admin is helping me" or "I\'m logging into Jenkins myself" is selected', async () => {
it('displays "Finish" button when either "A Jenkins admin on my team" or "I am a Jenkins admin" is selected', async () => {
(fetchGlobalPageUrlModule.fetchSiteName as jest.Mock).mockResolvedValueOnce('https://mocked-site-name.com');

(getJenkinsServerWithSecretModule.getJenkinsServerWithSecret as jest.Mock).mockResolvedValueOnce({
Expand All @@ -211,13 +216,13 @@ describe('JenkinsSetup Component', () => {
const { getByText } = screen;

await waitFor(() => {
fireEvent.click(getByText('A Jenkins admin is helping me'));
expect(getByText('Next')).toBeInTheDocument();
fireEvent.click(getByText('A Jenkins admin on my team'));
expect(getByText('Finish')).toBeInTheDocument();
});

await waitFor(() => {
fireEvent.click(getByText('I\'m logging into Jenkins myself'));
expect(getByText('Next')).toBeInTheDocument();
fireEvent.click(getByText('I am a Jenkins admin'));
expect(getByText('Finish')).toBeInTheDocument();
});
});
});
Loading

0 comments on commit b938467

Please sign in to comment.