Compare commits
20 Commits
master
...
JENKINS-35
Author | SHA1 | Date |
---|---|---|
tfennelly | 0ac084d048 | |
tfennelly | 9cf4feff74 | |
tfennelly | 07d6279b67 | |
tfennelly | 28765eb4ab | |
tfennelly | 5e691381f6 | |
tfennelly | 4e40e1d9d4 | |
tfennelly | c7cffe1af8 | |
tfennelly | 180eef07bf | |
tfennelly | 4df5d98136 | |
tfennelly | a079428a19 | |
tfennelly | 82592448b4 | |
tfennelly | 92c82f7790 | |
tfennelly | a4ad73ffaa | |
tfennelly | adb9fa2e4d | |
tfennelly | 73c988e9a0 | |
tfennelly | 3fecbbe658 | |
tfennelly | 12c885afdb | |
tfennelly | a445bf4021 | |
tfennelly | 83321d13f9 | |
tfennelly | c5efa05948 |
|
@ -1,7 +1,16 @@
|
|||
import * as sse from '@jenkins-cd/sse-gateway';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import appConfig from './config';
|
||||
|
||||
const { object, node } = PropTypes;
|
||||
|
||||
// Connect to the SSE Gateway and allocate a
|
||||
// dispatcher for blueocean.
|
||||
// TODO: We might want to move this code to a local SSE util module.
|
||||
sse.connect('jenkins_blueocean');
|
||||
|
||||
appConfig.loadConfig();
|
||||
|
||||
class Dashboard extends Component {
|
||||
|
||||
getChildContext() {
|
||||
|
|
|
@ -10,11 +10,6 @@ import * as pushEventUtil from './util/push-event-util';
|
|||
|
||||
const { object, array, func, node, string } = PropTypes;
|
||||
|
||||
// Connect to the SSE Gateway and allocate a
|
||||
// dispatcher for blueocean.
|
||||
// TODO: We might want to move this code to a local SSE util module.
|
||||
sse.connect('jenkins_blueocean');
|
||||
|
||||
class OrganizationPipelines extends Component {
|
||||
|
||||
// FIXME: IMO the following should be dropped
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* Simple pipeline branch API component.
|
||||
* <p>
|
||||
* Non-react component that contains general API methods for
|
||||
* interacting with pipeline branches, encapsulating REST API calls etc.
|
||||
*/
|
||||
|
||||
import fetch from 'isomorphic-fetch';
|
||||
import config from '../config';
|
||||
import Pipeline from './Pipeline';
|
||||
import * as urlUtils from '../util/UrlUtils';
|
||||
import * as sse from '@jenkins-cd/sse-gateway';
|
||||
import * as pushEventUtil from '../util/push-event-util';
|
||||
|
||||
export default class Branch {
|
||||
|
||||
constructor(pipeline, name) {
|
||||
this.pipeline = pipeline;
|
||||
this.name = name;
|
||||
this.sseListeners = [];
|
||||
}
|
||||
|
||||
runDetailsRouteUrl(runId) {
|
||||
if (runId === undefined) {
|
||||
throw new Error('Branch.runDetailsRouteUrl must be supplied with a "runId" parameter.');
|
||||
}
|
||||
return urlUtils.buildRunDetailsUrl(
|
||||
this.pipeline.organization,
|
||||
this.pipeline.name,
|
||||
this.name, runId, 'pipeline');
|
||||
}
|
||||
|
||||
restUrl() {
|
||||
return `${config.blueoceanAppURL}/rest/organizations/${this.pipeline.organization}/pipelines/${this.pipeline.name}/branches/${this.name}`;
|
||||
}
|
||||
|
||||
onJobChannelEvent(callback) {
|
||||
const _this = this;
|
||||
const jobListener = sse.subscribe('job', (event) => {
|
||||
const eventBranch = exports.fromSSEEvent(event);
|
||||
if (_this.equals(eventBranch)) {
|
||||
callback(event);
|
||||
}
|
||||
});
|
||||
|
||||
this.sseListeners.push(jobListener);
|
||||
}
|
||||
|
||||
clearEventListeners() {
|
||||
for (let i = 0; i < this.sseListeners.length; i++) {
|
||||
try {
|
||||
sse.unsubscribe(this.sseListeners[i]);
|
||||
} catch (e) {
|
||||
console.error('Unexpected error clearing SSE event listeners from Branch object');
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
this.sseListeners = [];
|
||||
}
|
||||
|
||||
run(onFail) {
|
||||
const url = `${this.restUrl()}/runs/`;
|
||||
|
||||
fetch(url, {
|
||||
method: 'post',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then((response) => {
|
||||
if (onFail && (response.status < 200 || response.status > 299)) {
|
||||
onFail(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
equals(branch) {
|
||||
if (branch && branch.name === this.name) {
|
||||
// and it's the same pipeline...
|
||||
return (
|
||||
branch.pipeline.organization === this.pipeline.organization &&
|
||||
branch.pipeline.name === this.pipeline.name
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
exports.fromSSEEvent = function (event) {
|
||||
const eventCopy = pushEventUtil.enrichJobEvent(event);
|
||||
if (!eventCopy.blueocean_is_multi_branch) {
|
||||
return undefined;
|
||||
}
|
||||
return new Branch(
|
||||
new Pipeline('jenkins', eventCopy.blueocean_job_name),
|
||||
eventCopy.blueocean_branch_name
|
||||
);
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Simple pipeline API component.
|
||||
* <p>
|
||||
* Non-react component that contains general API methods for
|
||||
* interacting with pipelines, encapsulating REST API calls etc.
|
||||
*/
|
||||
|
||||
export default class Pipeline {
|
||||
constructor(organization, pipelineName) {
|
||||
this.organization = organization;
|
||||
this.name = pipelineName;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { CommitHash, ReadableDate } from '@jenkins-cd/design-language';
|
||||
import { LiveStatusIndicator, WeatherIcon } from '@jenkins-cd/design-language';
|
||||
import RunPipeline from './RunPipeline.jsx';
|
||||
|
||||
const { object } = PropTypes;
|
||||
|
||||
|
@ -39,7 +40,7 @@ export default class Branches extends Component {
|
|||
|
||||
return (<tr key={name} onClick={open} id={`${name}-${id}`} >
|
||||
<td><WeatherIcon score={weatherScore} /></td>
|
||||
<td>
|
||||
<td onClick={open}>
|
||||
<LiveStatusIndicator result={result === 'UNKNOWN' ? state : result}
|
||||
startTime={startTime} estimatedDuration={estimatedDurationInMillis}
|
||||
/>
|
||||
|
@ -48,6 +49,7 @@ export default class Branches extends Component {
|
|||
<td><CommitHash commitId={commitId} /></td>
|
||||
<td>{msg || '-'}</td>
|
||||
<td><ReadableDate date={endTime || ''} /></td>
|
||||
<td><RunPipeline organization={organization} pipeline={pipelineName} branch={name} /></td>
|
||||
</tr>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ export class MultiBranch extends Component {
|
|||
{ label: 'Last commit', className: 'lastcommit' },
|
||||
{ label: 'Latest message', className: 'message' },
|
||||
{ label: 'Completed', className: 'completed' },
|
||||
{ label: '', className: 'run' },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { LiveStatusIndicator, ReadableDate } from '@jenkins-cd/design-language';
|
||||
import RunPipeline from './RunPipeline.jsx';
|
||||
|
||||
const { object } = PropTypes;
|
||||
|
||||
|
@ -51,6 +52,7 @@ export default class PullRequest extends Component {
|
|||
<td>{title || '-'}</td>
|
||||
<td>{author || '-'}</td>
|
||||
<td><ReadableDate date={endTime} /></td>
|
||||
<td><RunPipeline organization={organization} pipeline={pipelineName} branch={name} /></td>
|
||||
</tr>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ export class PullRequests extends Component {
|
|||
{ label: 'Summary', className: 'summary' },
|
||||
'Author',
|
||||
{ label: 'Completed', className: 'completed' },
|
||||
{ label: '', className: 'run' },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Simple widget for triggering the running of a pipeline.
|
||||
*/
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import Pipeline from '../api/Pipeline';
|
||||
import Branch from '../api/Branch';
|
||||
import { Toast } from '@jenkins-cd/design-language';
|
||||
|
||||
export default class RunPipeline extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const pipeline = new Pipeline(props.organization, props.pipeline);
|
||||
this.branch = new Branch(pipeline, props.branch);
|
||||
this.state = {
|
||||
toast: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const _this = this;
|
||||
const reactContext = this.context;
|
||||
const theBranch = this.branch;
|
||||
|
||||
this.branch.onJobChannelEvent((event) => {
|
||||
if (event.jenkins_event === 'job_run_queue_enter') {
|
||||
_this.setState({
|
||||
toast: { text: `Queued "${theBranch.name}"` },
|
||||
});
|
||||
} else if (event.jenkins_event === 'job_run_started') {
|
||||
_this.setState({
|
||||
toast: {
|
||||
text: `Started "${theBranch.name}" #${event.jenkins_object_id}`,
|
||||
action: {
|
||||
label: 'Open',
|
||||
callback: () => {
|
||||
const runDetailsUrl = theBranch.runDetailsRouteUrl(event.jenkins_object_id);
|
||||
reactContext.location.pathname = runDetailsUrl;
|
||||
reactContext.router.push(runDetailsUrl);
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
_this.setState({ toast: undefined });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.branch.clearEventListeners();
|
||||
}
|
||||
|
||||
run(event) {
|
||||
const _this = this;
|
||||
const theBranch = this.branch;
|
||||
|
||||
this.branch.run((response) => {
|
||||
console.error(`Unexpected error queuing a run of "${theBranch.name}". Response:`);
|
||||
console.error(response);
|
||||
_this.setState({
|
||||
toast: { text: `Failed to queue "${theBranch.name}". Try reloading the page.` },
|
||||
});
|
||||
});
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
render() {
|
||||
const toast = this.state.toast;
|
||||
if (toast) {
|
||||
if (toast.action) {
|
||||
return (<div>
|
||||
<div className="run-pipeline" onClick={(event) => this.run(event)}></div>
|
||||
<div className="run-pipeline-toast">
|
||||
<Toast text={toast.text} action={toast.action.label} onActionClick={() => toast.action.callback()} />
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
return (<div>
|
||||
<div className="run-pipeline" onClick={(event) => this.run(event)}></div>
|
||||
<div className="run-pipeline-toast">
|
||||
<Toast text={toast.text} />
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
return (<div className="run-pipeline" onClick={(event) => this.run(event)}></div>);
|
||||
}
|
||||
}
|
||||
|
||||
RunPipeline.propTypes = {
|
||||
organization: PropTypes.string,
|
||||
pipeline: PropTypes.string,
|
||||
branch: PropTypes.string,
|
||||
};
|
||||
|
||||
RunPipeline.contextTypes = {
|
||||
router: PropTypes.object.isRequired, // From react-router
|
||||
location: PropTypes.object,
|
||||
};
|
|
@ -1 +1,19 @@
|
|||
// Shared consts.urlPrefix
|
||||
//
|
||||
// General "system" config information.
|
||||
//
|
||||
// TODO: This should be in a general sharable component.
|
||||
// Passing it around in the react context is silly.
|
||||
//
|
||||
|
||||
exports.loadConfig = function () {
|
||||
const headElement = document.getElementsByTagName('head')[0];
|
||||
|
||||
// Look up where the Blue Ocean app is hosted
|
||||
exports.blueoceanAppURL = headElement.getAttribute('data-appurl');
|
||||
|
||||
if (typeof exports.blueoceanAppURL !== 'string') {
|
||||
exports.blueoceanAppURL = '/';
|
||||
}
|
||||
|
||||
exports.jenkinsRootURL = headElement.getAttribute('data-rooturl');
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ exports.enrichJobEvent = function (event, activePipelineName) {
|
|||
eventCopy.blueocean_is_multi_branch = false;
|
||||
}
|
||||
|
||||
// Is this even associated with the currently active pipeline job?
|
||||
// Is this event associated with the currently active pipeline job?
|
||||
eventCopy.blueocean_is_for_current_job =
|
||||
(eventCopy.blueocean_job_name === activePipelineName);
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
.pipelines-table {
|
||||
th {
|
||||
width: 10%;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.favorite {
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.branch {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.duration, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
.status-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.multibranch-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.branch {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.lastcommit, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.pr-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.build, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.changeset-table {
|
||||
th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.author {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.artifacts-table {
|
||||
th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.download {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.nodes {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
}
|
||||
.nodes__section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
|
@ -1,111 +1,4 @@
|
|||
.pipelines-table {
|
||||
th {
|
||||
width: 10%;
|
||||
min-width: 100px;
|
||||
}
|
||||
@import "variables";
|
||||
|
||||
.name {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.favorite {
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.branch {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.duration, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
.status-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.multibranch-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.branch {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.lastcommit, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.pr-table {
|
||||
th {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.build, .completed {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.changeset-table {
|
||||
th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.author {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.message {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date {
|
||||
width: 125px;
|
||||
}
|
||||
}
|
||||
|
||||
.artifacts-table {
|
||||
th {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.name {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.download {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.nodes {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
}
|
||||
.nodes__section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@import "core";
|
||||
@import "run-pipeline";
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="314.068px" height="314.068px" viewBox="0 0 314.068 314.068" style="enable-background:new 0 0 314.068 314.068;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g id="_x33_56._Play">
|
||||
<g>
|
||||
<path fill="#1C436A" d="M293.002,78.53C249.646,3.435,153.618-22.296,78.529,21.068C3.434,64.418-22.298,160.442,21.066,235.534
|
||||
c43.35,75.095,139.375,100.83,214.465,57.47C310.627,249.639,336.371,153.62,293.002,78.53z M219.834,265.801
|
||||
c-60.067,34.692-136.894,14.106-171.576-45.973C13.568,159.761,34.161,82.935,94.23,48.26
|
||||
c60.071-34.69,136.894-14.106,171.578,45.971C300.493,154.307,279.906,231.117,219.834,265.801z M213.555,150.652l-82.214-47.949
|
||||
c-7.492-4.374-13.535-0.877-13.493,7.789l0.421,95.174c0.038,8.664,6.155,12.191,13.669,7.851l81.585-47.103
|
||||
C221.029,162.082,221.045,155.026,213.555,150.652z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="314.068px" height="314.068px" viewBox="0 0 314.068 314.068" style="enable-background:new 0 0 314.068 314.068;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<g id="_x33_56._Play">
|
||||
<g>
|
||||
<path fill="#4A90E2" d="M293.002,78.53C249.646,3.435,153.618-22.296,78.529,21.068C3.434,64.418-22.298,160.442,21.066,235.534
|
||||
c43.35,75.095,139.375,100.83,214.465,57.47C310.627,249.639,336.371,153.62,293.002,78.53z M219.834,265.801
|
||||
c-60.067,34.692-136.894,14.106-171.576-45.973C13.568,159.761,34.161,82.935,94.23,48.26
|
||||
c60.071-34.69,136.894-14.106,171.578,45.971C300.493,154.307,279.906,231.117,219.834,265.801z M213.555,150.652l-82.214-47.949
|
||||
c-7.492-4.374-13.535-0.877-13.493,7.789l0.421,95.174c0.038,8.664,6.155,12.191,13.669,7.851l81.585-47.103
|
||||
C221.029,162.082,221.045,155.026,213.555,150.652z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,36 @@
|
|||
.jdl-table {
|
||||
.run-pipeline {
|
||||
z-index: 2000;
|
||||
font-size: 10px;
|
||||
padding-left: 5px;
|
||||
padding-top: 2px;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url('./icons/run.svg');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.run-pipeline:hover {
|
||||
background-image: url('./icons/run-darkened.svg'); // TODO: nicer if it could be done via a data-uri transform
|
||||
}
|
||||
|
||||
.run-pipeline-toast {
|
||||
position: fixed;
|
||||
left: 15px;
|
||||
bottom: 15px;
|
||||
|
||||
// Need to set higher specificity rules for some of the
|
||||
// Toast styles because they are being overridden by other
|
||||
// styles in JDL (table styles).
|
||||
// TODO: remove post https://issues.jenkins-ci.org/browse/JENKINS-36198
|
||||
.toast {
|
||||
a.action {
|
||||
color: @blueocean-blue;
|
||||
}
|
||||
.text {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
@blueocean-blue: #4A90E2;
|
||||
@blueocean-blue-darkened: darken(@blueocean-blue, 20%);
|
|
@ -0,0 +1,23 @@
|
|||
import { assert } from 'chai';
|
||||
|
||||
import Pipeline from '../../main/js/api/Pipeline';
|
||||
import Branch, { fromSSEEvent } from '../../main/js/api/Branch';
|
||||
|
||||
describe('Branch', () => {
|
||||
|
||||
it('equals', () => {
|
||||
const pipeline_1 = new Pipeline('jenkins', 'pipeline1');
|
||||
const pipeline_2 = new Pipeline('jenkins', 'pipeline2');
|
||||
const branch_1_1 = new Branch(pipeline_1, 'branch_1');
|
||||
const branch_1_2 = new Branch(pipeline_1, 'branch_2');
|
||||
const branch_2_1 = new Branch(pipeline_2, 'branch_1');
|
||||
|
||||
// same branch, different pipeline
|
||||
assert.equal(false, branch_1_1.equals(branch_1_2));
|
||||
// same pipeline, different branch
|
||||
assert.equal(false, branch_1_1.equals(branch_2_1));
|
||||
// same pipeline, same branch
|
||||
assert.equal(true, branch_1_1.equals(new Branch(pipeline_1, 'branch_1')));
|
||||
});
|
||||
|
||||
});
|
|
@ -35,7 +35,7 @@ describe("Branches should render", () => {
|
|||
const hashComp = row[3].getRenderOutput().props.children;
|
||||
const hashRendered = sd.shallowRender(hashComp).getRenderOutput();
|
||||
assert.equal(hashRendered.props.children, commitHash);
|
||||
assert.equal(row.length, 6);
|
||||
assert.equal(row.length, 7);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('PullRequest should render', () => {
|
|||
|
||||
it('does renders the PullRequest with data', () => {
|
||||
const result = tree.everySubTree('td');
|
||||
assert.equal(result.length, 5);
|
||||
assert.equal(result.length, 6);
|
||||
assert.equal(data.length, 2);
|
||||
assert.equal(pr.length, 1);
|
||||
const im = new RunsRecord(pr[0]);
|
||||
|
|
Loading…
Reference in New Issue