Intern-based functional tests
This commit makes it possible to execute UI functional tests either based on Casper or on Intern/Selenium Change-Id: I21d342093f142a1bbe7b8ae4f2c96fad1c125a0b
This commit is contained in:
parent
ec51a0dfdd
commit
3577169e20
|
@ -158,7 +158,7 @@ function runIntern(params) {
|
|||
return function() {
|
||||
var baseDir = 'static';
|
||||
var runner = './node_modules/.bin/intern-runner';
|
||||
var browser = params.browser || argv.browser || 'phantomjs';
|
||||
var browser = params.browser || argv.browser || 'firefox';
|
||||
var options = [['config', 'tests/intern-' + browser + '.js']];
|
||||
var suiteOptions = [];
|
||||
['suites', 'functionalSuites'].forEach(function(suiteType) {
|
||||
|
@ -181,7 +181,8 @@ function runIntern(params) {
|
|||
};
|
||||
}
|
||||
|
||||
gulp.task('intern:unit', runIntern({suites: argv.suites || 'static/tests/unit/**/*.js'}));
|
||||
gulp.task('intern:unit', runIntern({suites: argv.suites || 'static/tests/unit/**/*.js', browser: 'phantomjs'}));
|
||||
gulp.task('intern:functional', runIntern({functionalSuites: argv.suites || 'static/tests/functional/**/test_*.js'}));
|
||||
|
||||
gulp.task('unit-tests', function(cb) {
|
||||
runSequence('selenium', 'intern:unit', function(err) {
|
||||
|
@ -190,6 +191,13 @@ gulp.task('unit-tests', function(cb) {
|
|||
});
|
||||
});
|
||||
|
||||
gulp.task('functional-tests', function(cb) {
|
||||
runSequence('selenium', 'intern:functional', function(err) {
|
||||
shutdownSelenium();
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('jison', function() {
|
||||
return gulp.src('static/expression/parser.jison')
|
||||
.pipe(jison({moduleType: 'js'}))
|
||||
|
|
|
@ -35,6 +35,6 @@
|
|||
"rimraf": "~2.2.8",
|
||||
"run-sequence": "~1.0.2",
|
||||
"selenium-standalone": "~4.4.0",
|
||||
"uglify-js": "~2.4.16"
|
||||
"uglify-js": "~2.4.21"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define(['underscore',
|
||||
'../../helpers'], function(_, Helpers) {
|
||||
'use strict';
|
||||
function ClusterPage(remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
ClusterPage.prototype = {
|
||||
constructor: ClusterPage,
|
||||
goToTab: function(tabName) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return Helpers.clickLinkByText(
|
||||
that.remote,
|
||||
'.tabs-box .tabs a',
|
||||
tabName);
|
||||
});
|
||||
},
|
||||
removeCluster: function() {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(
|
||||
function() {
|
||||
return this.parent
|
||||
.setFindTimeout(2000)
|
||||
.then(function() {
|
||||
return that.goToTab('Actions');
|
||||
})
|
||||
.findByCssSelector('button.delete-environment-btn')
|
||||
.click()
|
||||
.end()
|
||||
.setFindTimeout(2000)
|
||||
.findByCssSelector('div.modal-content')
|
||||
.findByCssSelector('button.remove-cluster-btn')
|
||||
.click()
|
||||
.end()
|
||||
.setFindTimeout(2000)
|
||||
.waitForDeletedByCssSelector('div.modal-content');
|
||||
}
|
||||
);
|
||||
},
|
||||
checkNodeRoles: function(assignRoles) {
|
||||
return this.remote
|
||||
.setFindTimeout(2000)
|
||||
.findAllByCssSelector('div.role-panel label')
|
||||
.then(function(roles) {
|
||||
return roles.reduce(
|
||||
function(result, role) {
|
||||
return role
|
||||
.getVisibleText()
|
||||
.then(function(label) {
|
||||
var index = assignRoles.indexOf(label.substr(1));
|
||||
if (index >= 0) {
|
||||
role.click();
|
||||
assignRoles.splice(index, 1);
|
||||
return assignRoles.length == 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
},
|
||||
checkNodes: function(amount) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.setFindTimeout(2000)
|
||||
.then(function() {
|
||||
return _.range(amount).reduce(
|
||||
function(result, index) {
|
||||
return that.remote
|
||||
.setFindTimeout(1000)
|
||||
.findAllByCssSelector('.node.discover > label')
|
||||
.then(function(nodes) {
|
||||
return nodes[index].click();
|
||||
})
|
||||
.catch(function() {
|
||||
throw new Error('Failed to add ' + amount + ' nodes to the cluster');
|
||||
});
|
||||
},
|
||||
true);
|
||||
});
|
||||
}
|
||||
};
|
||||
return ClusterPage;
|
||||
});
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([], function() {
|
||||
'use strict';
|
||||
function ClustersPage(remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
ClustersPage.prototype = {
|
||||
constructor: ClustersPage,
|
||||
createCluster: function(clusterName) {
|
||||
return this.remote
|
||||
.setFindTimeout(1000)
|
||||
.findByClassName('create-cluster')
|
||||
.click()
|
||||
.end()
|
||||
.setFindTimeout(2000)
|
||||
.findByCssSelector('div.modal-content')
|
||||
.findByName('name')
|
||||
.clearValue()
|
||||
.type(clusterName)
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.pressKeys('\uE007')
|
||||
.end()
|
||||
.setFindTimeout(4000)
|
||||
.waitForDeletedByCssSelector('div.modal-content')
|
||||
.end();
|
||||
},
|
||||
clusterSelector: '.clusterbox div.name',
|
||||
goToEnvironment: function(clusterName) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.setFindTimeout(5000)
|
||||
.findAllByCssSelector(that.clusterSelector)
|
||||
.then(function(divs) {
|
||||
return divs.reduce(
|
||||
function(matchFound, element) {
|
||||
return element.getVisibleText().then(
|
||||
function(name) {
|
||||
if (name === clusterName) {
|
||||
element.click();
|
||||
return true;
|
||||
}
|
||||
return matchFound;
|
||||
}
|
||||
)},
|
||||
false
|
||||
);
|
||||
})
|
||||
.then(function(result) {
|
||||
if (!result) {
|
||||
throw new Error('Cluster ' + clusterName + ' not found');
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
return ClustersPage;
|
||||
});
|
|
@ -0,0 +1,132 @@
|
|||
define([
|
||||
'intern/node_modules/dojo/node!fs',
|
||||
'../../helpers',
|
||||
'tests/functional/pages/login',
|
||||
'tests/functional/pages/welcome',
|
||||
'tests/functional/pages/cluster',
|
||||
'tests/functional/pages/clusters'
|
||||
],
|
||||
function(fs, Helpers, LoginPage, WelcomePage, ClusterPage, ClustersPage) {
|
||||
'use strict';
|
||||
function CommonMethods(remote) {
|
||||
this.remote = remote;
|
||||
this.loginPage = new LoginPage(remote);
|
||||
this.welcomePage = new WelcomePage(remote);
|
||||
this.clusterPage = new ClusterPage(remote);
|
||||
this.clustersPage = new ClustersPage(remote);
|
||||
}
|
||||
|
||||
CommonMethods.prototype = {
|
||||
constructor: CommonMethods,
|
||||
takeScreenshot: function(filename, error) {
|
||||
return this.remote
|
||||
.takeScreenshot()
|
||||
.then(function(buffer) {
|
||||
if (!filename) {
|
||||
filename = new Date().toTimeString();
|
||||
}
|
||||
fs.writeFileSync('/tmp/' + filename + '.png', buffer);
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
},
|
||||
getOut: function() {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return that.welcomePage.skip();
|
||||
})
|
||||
.then(function() {
|
||||
return that.loginPage.logout();
|
||||
});
|
||||
},
|
||||
getIn: function() {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return that.loginPage.logout();
|
||||
})
|
||||
.then(function() {
|
||||
return that.loginPage.login();
|
||||
})
|
||||
.waitForDeletedByClassName('login-btn')
|
||||
.then(function() {
|
||||
return that.welcomePage.skip();
|
||||
});
|
||||
},
|
||||
clickLink: function(text) {
|
||||
return this.remote
|
||||
.setFindTimeout(1000)
|
||||
.findByLinkText(text)
|
||||
.click()
|
||||
.end();
|
||||
},
|
||||
waitForModal: function() {
|
||||
return this.remote
|
||||
.setTimeout(2000)
|
||||
.findByCssSelector('div.modal-content')
|
||||
.end();
|
||||
},
|
||||
waitForModalToClose: function() {
|
||||
return this.remote
|
||||
.setTimeout(2000)
|
||||
.waitForDeletedByCssSelector('div.modal-content')
|
||||
.end();
|
||||
},
|
||||
goToEnvironment: function(clusterName) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return that.clickLink('Environments');
|
||||
})
|
||||
.then(function() {
|
||||
return that.clustersPage.goToEnvironment(clusterName);
|
||||
});
|
||||
},
|
||||
createCluster: function(clusterName) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return that.clickLink('Environments');
|
||||
})
|
||||
.then(function() {
|
||||
return that.clustersPage.createCluster(clusterName);
|
||||
});
|
||||
},
|
||||
removeCluster: function(clusterName, suppressErrors) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return that.clickLink('Environments');
|
||||
})
|
||||
.then(function() {
|
||||
return that.clustersPage.goToEnvironment(clusterName);
|
||||
})
|
||||
.then(function() {
|
||||
return that.clusterPage.removeCluster();
|
||||
})
|
||||
.catch(function() {
|
||||
if (!suppressErrors) throw new Error('Unable to delete cluster ' + clusterName);
|
||||
});
|
||||
},
|
||||
doesClusterExist: function(clusterName) {
|
||||
var that = this;
|
||||
return this.remote
|
||||
.setFindTimeout(2000)
|
||||
.then(function() {
|
||||
return that.clickLink('Environments');
|
||||
})
|
||||
.findAllByCssSelector(that.clustersPage.clusterSelector)
|
||||
.then(function(divs) {
|
||||
return divs.reduce(function(matchFound, element) {
|
||||
return element.getVisibleText().then(
|
||||
function(name) {
|
||||
return (name === clusterName) || matchFound;
|
||||
}
|
||||
)}, false);
|
||||
});
|
||||
}
|
||||
};
|
||||
return CommonMethods;
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([
|
||||
'../../helpers'
|
||||
], function(Helpers) {
|
||||
'use strict';
|
||||
|
||||
function LoginPage(remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
LoginPage.prototype = {
|
||||
constructor: LoginPage,
|
||||
login: function(username, password) {
|
||||
username = username || Helpers.username;
|
||||
password = password || Helpers.password;
|
||||
var that = this;
|
||||
|
||||
return this.remote
|
||||
.setWindowSize(1280, 1024)
|
||||
.setTimeout('page load', 20000)
|
||||
.getCurrentUrl()
|
||||
.then(function(url) {
|
||||
if (url !== Helpers.serverUrl + '/#login') {
|
||||
return that.logout();
|
||||
}
|
||||
})
|
||||
.setFindTimeout(10000)
|
||||
.findByName('username')
|
||||
.clearValue()
|
||||
.type(username)
|
||||
.end()
|
||||
.findByName('password')
|
||||
.clearValue()
|
||||
.type(password)
|
||||
.end()
|
||||
.findByClassName('login-btn')
|
||||
.click()
|
||||
.end();
|
||||
},
|
||||
logout: function() {
|
||||
return this.remote
|
||||
.getCurrentUrl()
|
||||
.then(function(url) {
|
||||
if (url.indexOf(Helpers.serverUrl) !== 0) {
|
||||
return this.parent
|
||||
.get(Helpers.serverUrl + '/#logout')
|
||||
.setFindTimeout(10000)
|
||||
.findByClassName('login-btn')
|
||||
.then(function() {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
})
|
||||
.setFindTimeout(1000)
|
||||
.findByCssSelector('li.user-icon')
|
||||
.click()
|
||||
.end()
|
||||
.findByCssSelector('.user-popover button.btn-logout')
|
||||
.click()
|
||||
.end()
|
||||
.findByCssSelector('.login-btn')
|
||||
.then(
|
||||
function() {return true},
|
||||
function() {return true}
|
||||
);
|
||||
}
|
||||
};
|
||||
return LoginPage;
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define(['../../helpers'], function(Helpers) {
|
||||
'use strict';
|
||||
function WelcomePage(remote) {
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
WelcomePage.prototype = {
|
||||
constructor: WelcomePage,
|
||||
skip: function(strictCheck) {
|
||||
return this.remote
|
||||
.getCurrentUrl()
|
||||
.then(function(url) {
|
||||
if (url == Helpers.serverUrl + '/#welcome') {
|
||||
return this.parent
|
||||
.setFindTimeout(2000)
|
||||
.findByCssSelector('.welcome-button-box button')
|
||||
.click()
|
||||
.end()
|
||||
.waitForDeletedByCssSelector('.welcome-button-box button')
|
||||
.then(
|
||||
function() {return true},
|
||||
function() {return !strictCheck}
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
return WelcomePage;
|
||||
});
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'intern!object',
|
||||
'intern/chai!assert',
|
||||
'tests/functional/pages/common',
|
||||
'tests/functional/pages/cluster'
|
||||
], function(_, registerSuite, assert, Common, ClusterPage) {
|
||||
'use strict';
|
||||
|
||||
registerSuite(function() {
|
||||
var common,
|
||||
clusterPage,
|
||||
clusterName;
|
||||
|
||||
return {
|
||||
name: 'Clusters page',
|
||||
setup: function() {
|
||||
common = new Common(this.remote);
|
||||
clusterPage = new ClusterPage(this.remote);
|
||||
clusterName = 'Test Cluster #' + Math.round(99999 * Math.random());
|
||||
},
|
||||
beforeEach: function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.getIn();
|
||||
})
|
||||
.then(function() {
|
||||
return common.createCluster(clusterName);
|
||||
});
|
||||
},
|
||||
afterEach: function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.removeCluster(clusterName, true);
|
||||
});
|
||||
},
|
||||
'Remove Cluster': function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.doesClusterExist(clusterName);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert.ok(result, 'Cluster exists');
|
||||
})
|
||||
.then(function() {
|
||||
return common.removeCluster(clusterName);
|
||||
})
|
||||
.then(function() {
|
||||
return common.doesClusterExist(clusterName);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert.notOk(result, 'Cluster removed successfully');
|
||||
});
|
||||
},
|
||||
'Add Cluster Nodes': function() {
|
||||
var nodesAmount = 3,
|
||||
that = this,
|
||||
applyButton;
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.goToEnvironment(clusterName);
|
||||
})
|
||||
.setFindTimeout(5000)
|
||||
.findByCssSelector('button.btn-add-nodes')
|
||||
.click()
|
||||
.end()
|
||||
.findByCssSelector('button.btn-apply')
|
||||
.then(function(button) {
|
||||
applyButton = button;
|
||||
return applyButton.isEnabled().then(function(isEnabled) {
|
||||
assert.isFalse(isEnabled, 'Apply button is disabled until both roles and nodes chosen');
|
||||
return true;
|
||||
});
|
||||
})
|
||||
.end()
|
||||
.findByCssSelector('div.role-panel')
|
||||
.end()
|
||||
.then(function() {
|
||||
return clusterPage.checkNodeRoles(['Controller', 'Storage - Cinder']);
|
||||
})
|
||||
.then(function() {
|
||||
return applyButton.isEnabled().then(function(isEnabled) {
|
||||
assert.isFalse(isEnabled, 'Apply button is disabled until both roles and nodes chosen');
|
||||
return true;
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
return clusterPage.checkNodes(nodesAmount);
|
||||
})
|
||||
.then(function() {
|
||||
applyButton.click();
|
||||
})
|
||||
.setFindTimeout(2000)
|
||||
.findByCssSelector('button.btn-add-nodes')
|
||||
.end()
|
||||
|
||||
.then(function() {
|
||||
return _.range(1, 1 + nodesAmount).reduce(
|
||||
function(nodesFound, index) {
|
||||
return that.remote
|
||||
.setFindTimeout(1000)
|
||||
.findByCssSelector('div.node:nth-child(' + index + ')')
|
||||
.catch(function() {
|
||||
throw new Error('Unable to find ' + index + ' node in cluster');
|
||||
});
|
||||
},
|
||||
0
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([
|
||||
'intern!object',
|
||||
'intern/chai!assert',
|
||||
'tests/functional/pages/common'
|
||||
], function(registerSuite, assert, Common) {
|
||||
'use strict';
|
||||
|
||||
registerSuite(function() {
|
||||
var common,
|
||||
clusterName;
|
||||
|
||||
return {
|
||||
name: 'Clusters page',
|
||||
setup: function() {
|
||||
common = new Common(this.remote);
|
||||
clusterName = 'Test Cluster #' + Math.round(99999 * Math.random());
|
||||
},
|
||||
beforeEach: function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.getIn();
|
||||
})
|
||||
.then(function() {
|
||||
return common.createCluster(clusterName);
|
||||
});
|
||||
},
|
||||
afterEach: function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.removeCluster(clusterName, true);
|
||||
});
|
||||
},
|
||||
'Create Cluster': function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return common.doesClusterExist(clusterName);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert.ok(result, 'Newly created cluster name found in the list');
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2014 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([
|
||||
'intern!object',
|
||||
'intern/chai!assert',
|
||||
'tests/functional/pages/login',
|
||||
'tests/functional/pages/common'
|
||||
], function(registerSuite, assert, LoginPage, Common) {
|
||||
'use strict';
|
||||
|
||||
registerSuite(function() {
|
||||
var loginPage, common;
|
||||
return {
|
||||
name: 'Login page',
|
||||
setup: function() {
|
||||
loginPage = new LoginPage(this.remote);
|
||||
common = new Common(this.remote);
|
||||
},
|
||||
beforeEach: function() {
|
||||
this.remote
|
||||
.then(function() {
|
||||
return common.getOut();
|
||||
});
|
||||
},
|
||||
'Login with incorrect credentials': function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return loginPage.login('login', '*****');
|
||||
})
|
||||
.findByCssSelector('div.login-fields-box p.text-danger')
|
||||
.isDisplayed()
|
||||
.then(function(errorShown) {
|
||||
assert.ok(errorShown, 'Error message is expected to be displayed');
|
||||
});
|
||||
},
|
||||
'Login with proper credentials': function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return loginPage.login();
|
||||
})
|
||||
.waitForDeletedByClassName('login-btn');
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2015 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define([
|
||||
'intern!object',
|
||||
'intern/chai!assert',
|
||||
'tests/functional/pages/login',
|
||||
'tests/functional/pages/welcome'
|
||||
], function(registerSuite, assert, LoginPage, WelcomePage) {
|
||||
'use strict';
|
||||
|
||||
registerSuite(function() {
|
||||
var loginPage,
|
||||
welcomePage;
|
||||
|
||||
return {
|
||||
name: 'Welcome page',
|
||||
setup: function() {
|
||||
loginPage = new LoginPage(this.remote);
|
||||
welcomePage = new WelcomePage(this.remote);
|
||||
},
|
||||
'Skip welcome page': function() {
|
||||
return this.remote
|
||||
.then(function() {
|
||||
return loginPage.login();
|
||||
})
|
||||
.then(function() {
|
||||
return welcomePage.skip(true);
|
||||
})
|
||||
.then(function(result) {
|
||||
assert.ok(result, 'Start using fuel button is present');
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2014 Mirantis, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
**/
|
||||
|
||||
define(['underscore'], function(_) {
|
||||
'use strict';
|
||||
|
||||
var serverHost = '127.0.0.1',
|
||||
serverPort = process.env.SERVER_PORT || 5544,
|
||||
serverUrl = 'http://' + serverHost + ':' + serverPort,
|
||||
username = 'admin',
|
||||
password = 'admin';
|
||||
|
||||
return {
|
||||
username: username,
|
||||
password: password,
|
||||
serverUrl: serverUrl,
|
||||
clickLinkByText: function(remote, cssSelector, linkText) {
|
||||
return remote
|
||||
.setFindTimeout(1000)
|
||||
.findAllByCssSelector(cssSelector)
|
||||
.then(function(links) {
|
||||
return links.reduce(function(matchFound, link) {
|
||||
return link.getVisibleText().then(function(text) {
|
||||
if (_.trim(text) == linkText) {
|
||||
link.click();
|
||||
return true;
|
||||
}
|
||||
return matchFound;
|
||||
});
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -31,8 +31,9 @@ define(['config'], function(config) {
|
|||
'host-node': 'requirejs',
|
||||
'host-browser': '/vendor/bower/requirejs/require.js'
|
||||
},
|
||||
// A regular expression matching URLs to files that should not be included in code coverage analysis
|
||||
grep: /^/,
|
||||
excludeInstrumentation: /^/,
|
||||
loader: config
|
||||
loader: config,
|
||||
reporters: ['console']
|
||||
};
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ casper.then(function() {
|
|||
this.click('.btn-add-nodes');
|
||||
this.test.assertSelectorAppears('.node', 'Add Nodes screen appeared and unallocated nodes loaded');
|
||||
this.then(function() {
|
||||
this.test.assertEvalEquals(function() {return $('.node').length}, 1, 'Number of unallocated nodes is correct');
|
||||
this.test.assertEvalEquals(function() {return $('.node').length}, 9, 'Number of unallocated nodes is correct');
|
||||
this.click('input[name=controller]');
|
||||
this.click('.node input[type=checkbox]');
|
||||
this.test.assertSelectorAppears('.node .role-list > ul', 'Controller role is applied to the node');
|
||||
|
|
75
run_tests.sh
75
run_tests.sh
|
@ -43,6 +43,7 @@ function usage {
|
|||
echo " --no-ui-unit Don't run UI unit tests"
|
||||
echo " --ui-func Run UI functional tests"
|
||||
echo " --no-ui-func Don't run UI functional tests"
|
||||
echo " --ui-selenium Run UI functional selenium tests"
|
||||
echo ""
|
||||
echo "Note: with no options specified, the script will try to run all available"
|
||||
echo " tests with all available checks."
|
||||
|
@ -74,6 +75,7 @@ function process_options {
|
|||
--ui-unit) ui_unit_tests=1;;
|
||||
--no-ui-unit) no_ui_unit_tests=1;;
|
||||
--ui-func) ui_func_tests=1;;
|
||||
--ui-selenium) ui_func_selenium_tests=1;;
|
||||
--no-ui-func) no_ui_func_tests=1;;
|
||||
-t|--tests) certain_tests=1;;
|
||||
-*) testropts="$testropts $arg";;
|
||||
|
@ -110,7 +112,7 @@ ARTIFACTS=${ARTIFACTS:-`pwd`/test_run}
|
|||
TEST_WORKERS=${TEST_WORKERS:-0}
|
||||
mkdir -p $ARTIFACTS
|
||||
|
||||
# disabled/enabled flags that are setted from the cli.
|
||||
# disabled/enabled flags that are set from the cli.
|
||||
# used for manipulating run logic.
|
||||
agent_tests=0
|
||||
no_agent_tests=0
|
||||
|
@ -132,7 +134,7 @@ no_ui_func_tests=0
|
|||
certain_tests=0
|
||||
tasklib_tests=0
|
||||
no_tasklib_tests=0
|
||||
|
||||
ui_func_selenium_tests=0
|
||||
|
||||
function run_tests {
|
||||
run_cleanup
|
||||
|
@ -163,6 +165,7 @@ function run_tests {
|
|||
$ui_lint_checks -eq 0 && \
|
||||
$ui_unit_tests -eq 0 && \
|
||||
$ui_func_tests -eq 0 && \
|
||||
$ui_func_selenium_tests -eq 0 && \
|
||||
$upgrade_system -eq 0 && \
|
||||
$shotgun_tests -eq 0 && \
|
||||
$flake8_checks -eq 0 ]]; then
|
||||
|
@ -214,6 +217,11 @@ function run_tests {
|
|||
run_ui_func_tests || errors+=" ui_func_tests"
|
||||
fi
|
||||
|
||||
if [ $ui_func_selenium_tests -eq 1 ]; then
|
||||
echo "Starting UI functional selenium tests..."
|
||||
run_ui_func_selenium_tests || errors+=" ui_func_selenium_tests"
|
||||
fi
|
||||
|
||||
if [ $upgrade_system -eq 1 ]; then
|
||||
echo "Starting upgrade system tests..."
|
||||
run_upgrade_system_tests || errors+=" upgrade_system_tests"
|
||||
|
@ -363,6 +371,66 @@ function run_ui_func_tests {
|
|||
return $result
|
||||
}
|
||||
|
||||
# Run UI functional tests.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# $@ -- tests to be run; with no arguments all tests will be run
|
||||
function run_ui_func_selenium_tests {
|
||||
local SERVER_PORT=$UI_SERVER_PORT
|
||||
local TESTS_DIR=$ROOT/nailgun/static/tests/functional
|
||||
local TESTS=$TESTS_DIR/test_*.js
|
||||
local artifacts=$ARTIFACTS/ui_func
|
||||
local config=$artifacts/test.yaml
|
||||
prepare_artifacts $artifacts $config
|
||||
local COMPRESSED_STATIC_DIR=$artifacts/static_compressed
|
||||
|
||||
if [ $# -ne 0 ]; then
|
||||
TESTS=$@
|
||||
fi
|
||||
|
||||
pushd $ROOT/nailgun >> /dev/null
|
||||
|
||||
# test compression
|
||||
echo -n "Compressing UI... "
|
||||
local output=$(${GULP} build --static-dir=$COMPRESSED_STATIC_DIR 2>&1)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "$output"
|
||||
popd >> /dev/null
|
||||
exit 1
|
||||
fi
|
||||
echo "done"
|
||||
|
||||
# run js testcases
|
||||
local server_log=`mktemp /tmp/test_nailgun_ui_server.XXXX`
|
||||
local result=0
|
||||
local pid
|
||||
|
||||
for testcase in $TESTS; do
|
||||
|
||||
dropdb $config
|
||||
syncdb $config true
|
||||
|
||||
run_server $SERVER_PORT $server_log $config || \
|
||||
{ echo 'Failed to start Nailgun'; return 1; }
|
||||
|
||||
SERVER_PORT=$SERVER_PORT \
|
||||
${GULP} functional-tests --suites=$testcase
|
||||
if [ $? -ne 0 ]; then
|
||||
result=1
|
||||
break
|
||||
fi
|
||||
|
||||
kill_server $SERVER_PORT
|
||||
|
||||
done
|
||||
|
||||
rm $server_log
|
||||
popd >> /dev/null
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
# Run tests for fuel upgrade system
|
||||
#
|
||||
|
@ -484,6 +552,7 @@ function syncdb {
|
|||
|
||||
if [[ $# -ne 0 && $defaults = true ]]; then
|
||||
NAILGUN_CONFIG=$config tox -evenv -- python manage.py loaddefault > /dev/null
|
||||
NAILGUN_CONFIG=$config tox -evenv -- python manage.py loaddata nailgun/fixtures/sample_environment.json > /dev/null
|
||||
fi
|
||||
|
||||
popd >> /dev/null
|
||||
|
@ -626,6 +695,8 @@ EOL
|
|||
function guess_test_run {
|
||||
if [[ $1 == *ui_tests* && $1 == *.js ]]; then
|
||||
run_ui_func_tests $1 || echo "ERROR: $1"
|
||||
elif [[ $1 == *functional* && $1 == *.js ]]; then
|
||||
run_ui_func_selenium_tests $1 || echo "ERROR: $1"
|
||||
elif [[ $1 == *fuel_upgrade_system* ]]; then
|
||||
run_upgrade_system_tests $1 || echo "ERROR: $1"
|
||||
elif [[ $1 == *shotgun* ]]; then
|
||||
|
|
Loading…
Reference in New Issue