// Copyright 2018 The Kubeflow Authors // // 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. const assert = require('assert'); const URL = require('url').URL; const experimentName = 'tensorboard-example-experiment-' + Date.now(); const pipelineName = 'tensorboard-example-pipeline-' + Date.now(); const runName = 'tensorboard-example-' + Date.now(); const waitTimeout = 5000; function getValueFromDetailsTable(key) { // Find the span that shows the key, get its parent div (the row), then // get that row's inner text, and remove the key const row = $(`span=${key}`).$('..'); return row.getText().substr(`${key}\n`.length); } describe('deploy tensorboard example run', () => { before(() => { browser.url('/'); }); it('opens the pipeline upload dialog', () => { $('#uploadBtn').click(); browser.waitForVisible('#uploadDialog', waitTimeout); }); it('uploads the sample pipeline', () => { browser.chooseFile('#uploadDialog input[type="file"]', './tensorboard-example.yaml'); const input = $('#uploadDialog #uploadFileName'); input.clearElement(); input.setValue(pipelineName); $('#confirmUploadBtn').click(); browser.waitForVisible('#uploadDialog', waitTimeout, true); }); it('opens pipeline details', () => { $('.tableRow a').waitForVisible(waitTimeout); browser.execute('document.querySelector(".tableRow a").click()'); }); it('shows a 1-node static graph', () => { const nodeSelector = '.graphNode'; $(nodeSelector).waitForVisible(); const nodes = $$(nodeSelector).length; assert(nodes === 1, 'should have a 1-node graph, instead has: ' + nodes); }); it('creates a new experiment out of this pipeline', () => { $('#startNewExperimentBtn').click(); browser.waitUntil(() => { return new URL(browser.getUrl()).hash.startsWith('#/experiments/new'); }, waitTimeout); $('#experimentName').setValue(experimentName); $('#createExperimentBtn').click(); }); it('creates a new run in the experiment', () => { $('#choosePipelineBtn').waitForVisible(); $('#choosePipelineBtn').click(); $('.tableRow').waitForVisible(); $('.tableRow').click(); $('#usePipelineBtn').click(); $('#pipelineSelectorDialog').waitForVisible(waitTimeout, true); browser.keys('Tab'); browser.keys(runName); // Deploy $('#createBtn').click(); }); it('redirects back to experiment page', () => { browser.waitUntil(() => { return new URL(browser.getUrl()).hash.startsWith('#/experiments/details/'); }, waitTimeout); }); it('finds the new run in the list of runs, navigates to it', () => { $('.tableRow').waitForVisible(waitTimeout); assert.equal($$('.tableRow').length, 1, 'should only show one run'); // Navigate to details of the deployed run by clicking its anchor element $('.tableRow a').waitForVisible(waitTimeout); browser.execute('document.querySelector(".tableRow a").click()'); }); it('switches to config tab', () => { $('button=Config').waitForVisible(waitTimeout); $('button=Config').click(); }); it('waits for run to finish', () => { let status = getValueFromDetailsTable('Status'); let attempts = 0; const maxAttempts = 60; // Wait for a reasonable amount of time until the run is done while (attempts < maxAttempts && status.trim() !== 'Succeeded') { browser.pause(1000); status = getValueFromDetailsTable('Status'); attempts++; } assert(attempts < maxAttempts, `waited for ${maxAttempts} seconds but run did not succeed. ` + 'Current status is: ' + status); }); it('switches back to graph tab', () => { $('button=Graph').click(); }); it('has a 1-node graph', () => { const nodeSelector = '.graphNode'; const nodes = $$(nodeSelector).length; assert(nodes === 1, 'should have a 1-node graph, instead has: ' + nodes); }); it('opens the side panel when graph node is clicked', () => { $('.graphNode').click(); $('.plotCard').waitForVisible(waitTimeout); }); it('shows a Tensorboard plot card, and clicks its button to start Tensorboard', () => { // First button is the popout button, second is the Tensoboard start button const button = $$('.plotCard button')[1]; button.waitForVisible(); assert(button.getText().trim() === 'Start Tensorboard'); button.click(); }); it('waits until the button turns into Open Tensorboard', () => { // First button is the popout button, second is the Tensoboard open button browser.waitUntil(() => { const button = $$('.plotCard button')[1]; button.waitForVisible(); return button.getText().trim() === 'Open Tensorboard'; }, 2 * 60 * 1000); }); it('opens the Tensorboard app', () => { const anchor = $('.plotCard a'); browser.url(anchor.getAttribute('href')); let attempts = 0; const maxAttempts = 60; // Wait for a reasonable amount of time until Tensorboard app shows up while (attempts < maxAttempts && !$('#topBar').isExisting()) { browser.pause(1000); browser.refresh(); attempts++; } assert($('#topBar').isVisible()); browser.back(); }); it('deletes the uploaded pipeline', () => { $('#pipelinesBtn').click(); browser.waitForVisible('.tableRow', waitTimeout); $('.tableRow').click(); $('#deleteBtn').click(); $('.dialogButton').click(); $('.dialog').waitForVisible(waitTimeout, true); }); });