diff --git a/core/templates/dev/head/pages/admin-page/jobs-tab/admin-jobs-tab.directive.html b/core/templates/dev/head/pages/admin-page/jobs-tab/admin-jobs-tab.directive.html index 503a10145d63c..a265aa00f182a 100644 --- a/core/templates/dev/head/pages/admin-page/jobs-tab/admin-jobs-tab.directive.html +++ b/core/templates/dev/head/pages/admin-page/jobs-tab/admin-jobs-tab.directive.html @@ -35,11 +35,11 @@

Continuous computations

One-off jobs

Current time: <[$ctrl.HUMAN_READABLE_CURRENT_TIME]>

- - + +
<[job_spec.job_type]>
<[job_spec.job_type]> Current time: <[$ctrl.HUMAN_READABLE_CURRENT_TIME]> + class="oppia-page-card oppia-long-text protractor-test-unfinished-jobs-card" style="max-width: 900px">

Unfinished jobs

Note: This table may be stale; refresh to see the latest state. - + - - + + diff --git a/core/tests/protractor_desktop/adminTabFeatures.js b/core/tests/protractor_desktop/adminTabFeatures.js index eae77eb62d9af..db75dfebea6fd 100644 --- a/core/tests/protractor_desktop/adminTabFeatures.js +++ b/core/tests/protractor_desktop/adminTabFeatures.js @@ -20,7 +20,7 @@ var general = require('../protractor_utils/general.js'); var users = require('../protractor_utils/users.js'); var AdminPage = require('../protractor_utils/AdminPage.js'); -describe('Admin Tab', function() { +describe('Admin Page', function() { var adminPage = null; beforeAll(function() { @@ -49,6 +49,28 @@ describe('Admin Tab', function() { adminPage.updateRole('collectionEditor1', 'collection editor'); adminPage.getUsersAsssignedToRole('collection editor'); adminPage.expectUsernamesToMatch(['collectionEditor1']); + users.logout(); + }); + + it('should run,verify and stop one-off jobs', function() { + users.createAndLoginAdminUser('adminA@adminTab.com', 'alphaMan'); + adminPage.getJobsTab(); + + // The following jobs are selected arbitrarily. + adminPage.startOneOffJob('FeedbackThreadCacheOneOffJob'); + adminPage.expectJobToBeRunning('FeedbackThreadCacheOneOffJob'); + adminPage.expectNumberOfRunningOneOffJobs(1); + + adminPage.startOneOffJob('ExplorationValidityJobManager'); + adminPage.expectJobToBeRunning('ExplorationValidityJobManager'); + adminPage.expectNumberOfRunningOneOffJobs(2); + + adminPage.stopOneOffJob('FeedbackThreadCacheOneOffJob'); + adminPage.expectJobToBeRunning('ExplorationValidityJobManager'); + adminPage.expectNumberOfRunningOneOffJobs(1); + + adminPage.stopOneOffJob('ExplorationValidityJobManager'); + adminPage.expectNumberOfRunningOneOffJobs(0); }); afterEach(function() { diff --git a/core/tests/protractor_utils/AdminPage.js b/core/tests/protractor_utils/AdminPage.js index 77c278ff0049f..b59f5e32ccb04 100644 --- a/core/tests/protractor_utils/AdminPage.js +++ b/core/tests/protractor_utils/AdminPage.js @@ -40,6 +40,11 @@ var AdminPage = function() { var roleUsernameOption = element(by.css( '.protractor-test-username-value')); var viewRoleButton = element(by.css('.protractor-test-role-success')); + var oneOffJobRows = element.all(by.css('.protractor-test-one-off-jobs-rows')); + var unfinishedOneOffJobRows = element.all(by.css( + '.protractor-test-unfinished-one-off-jobs-rows')); + var unfinishedOffJobIDs = element.all(by.css( + '.protractor-test-unfinished-one-off-jobs-id')); // The reload functions are used for mobile testing // done via Browserstack. These functions may cause @@ -124,6 +129,11 @@ var AdminPage = function() { return waitFor.pageToFullyLoad(); }; + this.getJobsTab = function() { + browser.get(ADMIN_URL_SUFFIX + '#/jobs'); + return waitFor.pageToFullyLoad(); + }; + this.editConfigProperty = function( propertyName, objectType, editingInstructions) { this.get(); @@ -142,6 +152,61 @@ var AdminPage = function() { }); }; + this.startOneOffJob = function(jobName) { + this._startOneOffJob(jobName, 0); + }; + + this._startOneOffJob = function(jobName, i) { + waitFor.visibilityOf(oneOffJobRows.first(), + 'Starting one off jobs taking too long to appear.'); + oneOffJobRows.get(i).getText().then((text) => { + if (text.toLowerCase().startsWith(jobName.toLowerCase())) { + oneOffJobRows.get(i).element( + by.css('.protractor-test-one-off-jobs-start-btn')).click(); + } else { + this._startOneOffJob(jobName, ++i); + } + }); + }; + + this.stopOneOffJob = function(jobName) { + this._stopOneOffJob(jobName, 0); + }; + + this._stopOneOffJob = function(jobName, i) { + unfinishedOneOffJobRows.get(i).getText().then((text) => { + if (text.toLowerCase().startsWith(jobName.toLowerCase())) { + unfinishedOneOffJobRows.get(i).element( + by.css('.protractor-test-one-off-jobs-stop-btn')).click(); + } else { + this._stopOneOffJob(jobName, ++i); + } + }); + }; + + this.expectNumberOfRunningOneOffJobs = function(count) { + element.all(by.css( + '.protractor-test-unfinished-one-off-jobs-id')).count().then((len) =>{ + expect(len).toEqual(count); + }); + }; + + this.expectJobToBeRunning = function(jobName) { + browser.refresh(); + waitFor.pageToFullyLoad(); + waitFor.visibilityOf(element( + by.css('.protractor-test-unfinished-jobs-card')), + 'Unfinished Jobs taking too long to appear'); + let unfinishedJobs = unfinishedOffJobIDs.filter((element) => { + return element.getText().then((job) => { + return job.toLowerCase().startsWith(jobName.toLowerCase()); + }); + }); + unfinishedJobs.get(0).getText((job) => { + expect(job.toLowerCase().startsWith(jobName.toLowerCase())).toBeTrue(); + }); + }; + this.updateRole = function(name, newRole) { waitFor.elementToBeClickable( adminRolesTab, 'Admin Roles tab is not clickable');
Job IDJob ID Status Time started Time finished
<[job.id]>
<[job.id]> <[job.status_code]> <[job.human_readable_time_started]> <[job.human_readable_time_finished]>