Skip to content
This repository has been archived by the owner on Jan 4, 2023. It is now read-only.

Commit

Permalink
[FIX JENKINS-36660] WIP Acceptance tests for nested project and funky…
Browse files Browse the repository at this point in the history
… branch name regressions (#26)

* Added git api for creating local git repos for testing

* stash

* [JENKINS-36660] WIP implementing creation of folder and a freestyle project within the nested path.

* [JENKINS-36660] WIP remove obsolete variable

* [JENKINS-36660] WIP waiting for ever when uncommenting, seems that sse is not getting informed

* [JENKINS-36660] Add tests for JENKINS-36618

* [JENKINS-36660] Extending multibranch AT implementing creation of job

* [JENKINS-36660] Add fixme note so tom knows where the problems lies

* [JENKINS-36660] first working version of creating multibranch in folders

* [JENKINS-36660] fix class name

* [JENKINS-36660] add more test to cover various regressions. The close modal test is breaking my balls though since the opener url is equal to the current location but only in AT.

* [JENKINS-36660] Implement regression testing for all tabs when they should show data. Add commit script for the git repo.

* [JENKINS-36660] remove legacy folder

* [JENKINS-36660] fix renamed methood

* [JENKINS-36660] make sure we do not start without wait for finish

* [JENKINS-36660] Start test for pressing run button. add test to validate activities. move clickTab and related code to url util class

* [JENKINS-36660] Implement check for runButton and start working on queued state

* [JENKINS-36660] WIP queued state testing, infrastructure code to set executors

* [JENKINS-36660] Implement checks for queued jobs

* [JENKINS-36660] using async series to make sure the changeset has passed before doing next step

* [JENKINS-36660] make sure we reset the executors

* [JENKINS-36660] prepare for merge with current master, Disable tests as long ticket is open,
  • Loading branch information
scherler committed Sep 2, 2016
1 parent 5062f20 commit ebad36c
Show file tree
Hide file tree
Showing 23 changed files with 1,126 additions and 76 deletions.
7 changes: 6 additions & 1 deletion package.json
Expand Up @@ -28,6 +28,11 @@
"phantomjs-prebuilt": "2.1.7",
"request": "2.72.0",
"util": "0.10.3",
"xmlhttprequest": "1.8.0"
"xmlhttprequest": "1.8.0",
"fs-extra": "^0.30.0",
"nodegit": "^0.13.2"
},
"dependencies": {
"async": "^2.0.1"
}
}
152 changes: 152 additions & 0 deletions src/main/js/api/git.js
@@ -0,0 +1,152 @@
var NodeGit = require("nodegit");
var fse = require('fs-extra');
var path = require("path");

exports.init = function (pathToRepo, onInit) {
var pathToRepo = path.resolve(pathToRepo);

fse.emptyDirSync(pathToRepo);
NodeGit.Repository.init(pathToRepo, 0)
.then(function (repo) {
var signature = NodeGit.Signature.default(repo);
var initIndex;

repo.refreshIndex()
.then(function (index) {
initIndex = index;
return index.write();
})
.then(function (index) {
return initIndex.writeTree();
})
.then(function (oid) {
return repo.createCommit("HEAD", signature, signature, 'initial commit', oid, []);
})
.done(function () {
if (onInit) {
onInit({
repo: repo,
copyDirToRepo: function (dir) {
var pathToFiles = path.resolve(dir);

if (!fse.existsSync(pathToFiles)) {
throw new Error('No such directory: ' + pathToFiles);
}
if (!fse.statSync(pathToFiles).isDirectory()) {
throw new Error('Not a directory: ' + pathToFiles);
}

fse.copySync(pathToFiles, pathToRepo);
},
commit: function (message) {
if (!message) {
message = 'commit all';
}

var index;
var oid;
var returnPromise = repo.refreshIndex()
.then(function (indexResult) {
index = indexResult;
})
.then(function () {
return index.addAll();
})
.then(function () {
return index.write();
})
.then(function () {
return index.writeTree();
})
.then(function (oidResult) {
oid = oidResult;
return NodeGit.Reference.nameToId(repo, "HEAD");
})
.then(function (head) {
return repo.getCommit(head);
})
.then(function (parent) {
return repo.createCommit("HEAD", signature, signature, message, oid, [parent]);
});

return returnPromise;
},
createRepo: function (fromDir, inDir) {
repo.copyDirToRepo(fromDir);
return repo.commit('Added ');
}
});
}
});

});
};

exports.createRepo = function (fromDir, inDir) {
return new Promise(function (resolve, reject) {
exports.init(inDir, function (repo) {
repo.copyDirToRepo(fromDir);
repo.commit('Copied files from ' + fromDir)
.then(resolve)
.catch(reject);
});
});
};

exports.createBranch = function (branchName, pathToRepo) {
var pathToRepo = path.resolve(pathToRepo);

return NodeGit.Repository.open(pathToRepo)
.then(function (repo) {
return repo.getHeadCommit()
.then(function (commit) {
return repo.createBranch(
branchName,
commit, 0,
repo.defaultSignature(),
'Created "' + branchName + '" branch on HEAD');
});
});
};

exports.createCommit = function (pathToRepo, files) {

const signatureAuthor = NodeGit.Signature.now('Iron Thor', 'ironThor@avengers.com');
var repo, index, oid, remote;

return NodeGit.Repository.open(pathToRepo)
.then(function (repoResult) {
repo = repoResult;
return repo.refreshIndex();
})
.then(function (indexResult) {
index = indexResult;
// this file is in the root of the directory and doesn't need a full path
return files.map(function (fileName) {
console.log('++++Adding file +++', fileName);
index.addByPath(fileName);
})
})
.then(function() {
// this will write files to the index
return index.write();
})
.then(function() {
return index.writeTree();
})
.then(function (oidResult) {
oid = oidResult;
return NodeGit.Reference.nameToId(repo, "HEAD");
})
.then(function (head) {
return repo.getCommit(head);
})
.then(function (parent) {
return repo.createCommit("HEAD", signatureAuthor, signatureAuthor, 'testing commit tab', oid, [parent]);
})
.done(function (commitId) {
console.log("New Commit: ", commitId);
return commitId;
});

};
12 changes: 12 additions & 0 deletions src/main/js/page_objects/blueocean/bluePipelineActivity.js
Expand Up @@ -7,6 +7,7 @@ module.exports = {
pipelinesNav: '.global-header nav a[href="/blue/pipelines"]',
emptyStateShoes: '.empty-state .empty-state-icon.shoes',
activityTable: '.activity-table',
activityTableEntries: 'table.activity-table tbody tr',
}
};

Expand Down Expand Up @@ -35,5 +36,16 @@ module.exports.commands = [{
this.waitForElementVisible('.activity-table tr#' + runName);
this.waitForElementVisible('.activity-table tr#' + runName + ' svg.svgResultStatus');
this.waitForElementPresent('.activity-table tr#' + runName + ' svg path.running');
},
clickTab: function (browser, tab) {
var self = this;
return url.clickTab(browser, self, tab);
},
assertActivitiesToBeEqual: function (browser, expected) {
var self = this;
self.waitForElementVisible('@activityTableEntries');
browser.elements('css selector', 'table.activity-table tbody tr', function (codeCollection) {
this.assert.equal(codeCollection.value.length, expected);
});
}
}];
30 changes: 30 additions & 0 deletions src/main/js/page_objects/blueocean/bluePipelineBranch.js
@@ -0,0 +1,30 @@
var url = require('../../util/url');

module.exports = {
elements: {
runButton: 'div.actions div.run-pipeline',
toasts: 'div.toaster div.toast span.text'
}
};

// Nightwatch commands.
// http://nightwatchjs.org/guide#writing-commands
module.exports.commands = [{
clickRunButton: function (browser) {
var self = this;
self.waitForElementVisible('@runButton');
self.click('@runButton');
browser.elements('css selector', 'div.toaster div.toast span.text', function (codeCollection) {
this.assert.equal(codeCollection.value.length, 2);
codeCollection.value.map(function (item) {
browser.elementIdText(item.ELEMENT, function (value) {
var passed = value.value.indexOf('Queued');
if (passed === -1) {
passed = value.value.indexOf('Started');
}
self.assert.equal(passed > -1, true);
})
})
});
}
}];
107 changes: 85 additions & 22 deletions src/main/js/page_objects/blueocean/bluePipelineRunDetail.js
Expand Up @@ -11,7 +11,14 @@ module.exports = {
followAlongOn: '.step-scroll-area.follow-along-on',
followAlongOff: '.step-scroll-area.follow-along-off',
emptystate: 'div.empty-state',
artifactTable: 'table.artifacts-table',
detailTitle: 'section.table',
closeButton: 'a.closeButton',
activityTable: '.activity-table',
highlightedGraph: 'g.pipeline-selection-highlight',
logConsole: 'div.logConsole',
artifactTable: 'table.artifacts-table tr',
changes: 'table.changeset-table tr',
tests: 'div.new-failure-block div.result-item',
}
};

Expand All @@ -21,12 +28,12 @@ module.exports.commands = [{
forRun: function(jobName, orgName, branchName, buildNumber) {
this.jobName = jobName;
this.orgName = orgName;
this.branchName = (typeof branchName === 'string' ? branchName : jobName);
this.multiBranchJob = (typeof branchName === 'string' ? branchName : jobName);
this.buildNumber = (typeof branchName === 'number' ? branchName : buildNumber);
return this.navigate(this.pageUrl());
},
pageUrl: function(relative) {
var runUrl = url.makeRelative(url.viewRunPipeline(this.orgName, this.jobName, this.branchName, this.buildNumber));
var runUrl = url.makeRelative(url.viewRunPipeline(this.orgName, this.jobName, this.multiBranchJob, this.buildNumber));

return !relative ?
this.api.launchUrl + runUrl :
Expand All @@ -39,31 +46,46 @@ module.exports.commands = [{
tabUrl: function(tabName, relative) {
return this.pageUrl(relative) + '/' + tabName;
},
tabSelector: function(tabName) {
return 'nav.page-tabs a[href="' + this.tabUrl(tabName, true) + '"]';
},
assertBasicLayoutOkay: function() {
this.waitForElementVisible(this.tabSelector('pipeline'));
this.waitForElementVisible(this.tabSelector('changes'));
this.waitForElementVisible(this.tabSelector('tests'));
this.waitForElementVisible(this.tabSelector('artifacts'));
this.waitForElementVisible(url.tabSelector('pipeline'));
this.waitForElementVisible(url.tabSelector('changes'));
this.waitForElementVisible(url.tabSelector('tests'));
this.waitForElementVisible(url.tabSelector('artifacts'));
this.waitForElementVisible('@logHeader');
// TODO: add class info to the page content so we can test it
// Atm there's very little on the page that will allow us to test it.
// E.g. nothing on the pipeline graph that allows us to find it.
},
clickTab: function(browser, tab) {
assertTitle: function (expected) {
var self = this;
self.waitForElementVisible('@detailTitle');
self.getText('@detailTitle', function (response) {
self.assert.equal(typeof response, "object");
self.assert.equal(response.status, 0);
const urlProect = (response.value);
self.assert.equal(urlProect.indexOf(expected)>-1, true);
return self;
})

},
closeModal: function (browser) {
var self = this;
const tabSelector = this.tabSelector(tab);
self.waitForElementVisible(tabSelector);
self.click(tabSelector);
self.waitForElementVisible('@closeButton');
self.click('@closeButton');
browser.url(function (response) {
self.assert.equal(typeof response, "object");
self.assert.equal(response.status, 0);
// did we changed the url on change?
self.assert.equal(response.value.includes(tab), true);
return self;
})
self.assert.equal(typeof response, "object");
self.assert.equal(response.status, 0);
this.pause(10000)
// FIXME JENKINS-36619 -> somehow the close in AT is not working as it should
// I debugged a bit and found out that the "previous" location is the same as
// current, this is the reason, why no url change is triggered. The question remains
// why that is happening
return self;
})
},
clickTab: function(browser, tab) {
var self = this;
return url.clickTab(browser, self, tab);
},
clickFullLog: function (browser) {
var self = this;
Expand Down Expand Up @@ -95,14 +117,55 @@ module.exports.commands = [{
this.expect.element('@code').to.not.be.present.before(1000);

},
validateGraph: function () {
var self = this;
self.waitForElementVisible('@highlightedGraph');
return self;
},
validateSteps: function (browser) {
var self = this;
self.waitForElementVisible('@logConsole');
browser.elements('css selector', '.logConsole', function (codeCollection) {
this.assert.equal(codeCollection.value.length > 0, true);
});
return self;
},
validateLog: function () {
var self = this;
self.waitForElementVisible('@code');
return self;
},
validateEmpty: function () {
var self = this;
self.waitForElementVisible('@emptystate');
return self;
},
validateNotEmpty: function () {
validateNotEmptyArtifacts: function (browser, expectedCount) {
var self = this;
self.waitForElementVisible('@artifactTable');
if (browser && expectedCount) {
browser.elements('css selector', 'table.artifacts-table tr', function (codeCollection) {
this.assert.equal(codeCollection.value.length, expectedCount + 1); // +1 because of the heading row
return self;
});
}
return self;
}
},
validateNotEmptyChanges: function (browser, expectedCount) {
var self = this;
self.waitForElementVisible('@changes');
if (browser && expectedCount) {
browser.elements('css selector', 'table.changeset-table tr', function (codeCollection) {
this.assert.equal(codeCollection.value.length, expectedCount + 1); // +1 because of the heading row
return self;
});
}
return self;
},
validateFailingTests: function () {
var self = this;
self.waitForElementVisible('@tests');
return self;
},

}];
5 changes: 5 additions & 0 deletions src/main/js/page_objects/blueocean/bluePipelines.js
Expand Up @@ -27,5 +27,10 @@ module.exports.commands = [{
},
assertJob: function(jobName) {
this.waitForElementVisible('.pipelines-table tr[data-name="' + jobName + '"]');
},
countJobToBeEqual: function(browser, jobName, count) {
browser.elements('css selector', '.pipelines-table tr[data-name="' + jobName + '"]', function (codeCollection) {
this.assert.equal(codeCollection.value.length, count);
});
}
}];

0 comments on commit ebad36c

Please sign in to comment.