Replace term.js with xterm.js
This commit is contained in:
parent
229671f485
commit
cddcb1f40a
6 changed files with 57 additions and 257 deletions
|
|
@ -63,6 +63,6 @@
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"react": "^16.4.2",
|
"react": "^16.4.2",
|
||||||
"react-dom": "^16.4.2",
|
"react-dom": "^16.4.2",
|
||||||
"term.js-cockpit": "0.0.10"
|
"xterm": "^3.14.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
@import "~xterm/lib/xterm.css";
|
||||||
@import "term.css";
|
@import "term.css";
|
||||||
|
|
||||||
/* Our terminal or logs */
|
/* Our terminal or logs */
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,13 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import './console.css';
|
||||||
|
import { Terminal as Term } from 'xterm';
|
||||||
let cockpit = require("cockpit");
|
let cockpit = require("cockpit");
|
||||||
let _ = cockpit.gettext;
|
let _ = cockpit.gettext;
|
||||||
let moment = require("moment");
|
let moment = require("moment");
|
||||||
let Term = require("term.js-cockpit");
|
|
||||||
let Journal = require("journal");
|
let Journal = require("journal");
|
||||||
let $ = require("jquery");
|
let $ = require("jquery");
|
||||||
require("console.css");
|
|
||||||
require("bootstrap-slider");
|
require("bootstrap-slider");
|
||||||
|
|
||||||
let padInt = function (n, w) {
|
let padInt = function (n, w) {
|
||||||
|
|
@ -1143,7 +1143,9 @@ export class Player extends React.Component {
|
||||||
cols: this.state.cols,
|
cols: this.state.cols,
|
||||||
rows: this.state.rows,
|
rows: this.state.rows,
|
||||||
screenKeys: true,
|
screenKeys: true,
|
||||||
useStyle: true
|
useStyle: true,
|
||||||
|
/* Exposes the xterm-accessibility-tree */
|
||||||
|
screenReaderMode: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
term.on('title', this.handleTitleChange);
|
term.on('title', this.handleTitleChange);
|
||||||
|
|
@ -1242,35 +1244,35 @@ export class Player extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-footer">
|
<div className="panel-footer">
|
||||||
<Slider length={this.buf.pos} mark={this.state.currentTsPost} fastForwardFunc={this.fastForwardToTS} play={this.play} pause={this.pause} paused={this.state.paused} />
|
<Slider length={this.buf.pos} mark={this.state.currentTsPost} fastForwardFunc={this.fastForwardToTS} play={this.play} pause={this.pause} paused={this.state.paused} />
|
||||||
<button title="Play/Pause - Hotkey: p" type="button" ref="playbtn"
|
<button id="player-play-pause" title="Play/Pause - Hotkey: p" type="button" ref="playbtn"
|
||||||
className="btn btn-default btn-lg margin-right-btn play-btn"
|
className="btn btn-default btn-lg margin-right-btn play-btn"
|
||||||
onClick={this.playPauseToggle}>
|
onClick={this.playPauseToggle}>
|
||||||
<i className={"fa fa-" + (this.state.paused ? "play" : "pause")}
|
<i className={"fa fa-" + (this.state.paused ? "play" : "pause")}
|
||||||
aria-hidden="true" />
|
aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button title="Skip Frame - Hotkey: ." type="button"
|
<button id="player-skip-frame" title="Skip Frame - Hotkey: ." type="button"
|
||||||
className="btn btn-default btn-lg margin-right-btn"
|
className="btn btn-default btn-lg margin-right-btn"
|
||||||
onClick={this.skipFrame}>
|
onClick={this.skipFrame}>
|
||||||
<i className="fa fa-step-forward" aria-hidden="true" />
|
<i className="fa fa-step-forward" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button title="Restart Playback - Hotkey: Shift-R" type="button"
|
<button id="player-restart" title="Restart Playback - Hotkey: Shift-R" type="button"
|
||||||
className="btn btn-default btn-lg" onClick={this.rewindToStart}>
|
className="btn btn-default btn-lg" onClick={this.rewindToStart}>
|
||||||
<i className="fa fa-fast-backward" aria-hidden="true" />
|
<i className="fa fa-fast-backward" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button title="Fast-forward to end - Hotkey: Shift-G" type="button"
|
<button id="player-fast-forward" title="Fast-forward to end - Hotkey: Shift-G" type="button"
|
||||||
className="btn btn-default btn-lg margin-right-btn"
|
className="btn btn-default btn-lg margin-right-btn"
|
||||||
onClick={this.fastForwardToEnd}>
|
onClick={this.fastForwardToEnd}>
|
||||||
<i className="fa fa-fast-forward" aria-hidden="true" />
|
<i className="fa fa-fast-forward" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button title="Speed /2 - Hotkey: {" type="button"
|
<button id="player-speed-down" title="Speed /2 - Hotkey: {" type="button"
|
||||||
className="btn btn-default btn-lg" onClick={this.speedDown}>
|
className="btn btn-default btn-lg" onClick={this.speedDown}>
|
||||||
/2
|
/2
|
||||||
</button>
|
</button>
|
||||||
<button title="Reset Speed - Hotkey: Backspace" type="button"
|
<button id="player-speed-reset" title="Reset Speed - Hotkey: Backspace" type="button"
|
||||||
className="btn btn-default btn-lg" onClick={this.speedReset}>
|
className="btn btn-default btn-lg" onClick={this.speedReset}>
|
||||||
1:1
|
1:1
|
||||||
</button>
|
</button>
|
||||||
<button title="Speed x2 - Hotkey: }" type="button"
|
<button id="player-speed-up" title="Speed x2 - Hotkey: }" type="button"
|
||||||
className="btn btn-default btn-lg margin-right-btn"
|
className="btn btn-default btn-lg margin-right-btn"
|
||||||
onClick={this.speedUp}>
|
onClick={this.speedUp}>
|
||||||
x2
|
x2
|
||||||
|
|
@ -1278,16 +1280,16 @@ export class Player extends React.Component {
|
||||||
<span>{speedStr}</span>
|
<span>{speedStr}</span>
|
||||||
<span style={to_right}>
|
<span style={to_right}>
|
||||||
<span className="session_time">{formatDuration(this.state.currentTsPost)} / {formatDuration(this.buf.pos)}</span>
|
<span className="session_time">{formatDuration(this.state.currentTsPost)} / {formatDuration(this.buf.pos)}</span>
|
||||||
<button title="Drag'n'Pan" type="button" className="btn btn-default btn-lg"
|
<button id="player-drag-pan" title="Drag'n'Pan" type="button" className="btn btn-default btn-lg"
|
||||||
onClick={this.dragPan}>
|
onClick={this.dragPan}>
|
||||||
<i className={"fa fa-" + (this.state.drag_pan ? "hand-rock-o" : "hand-paper-o")}
|
<i className={"fa fa-" + (this.state.drag_pan ? "hand-rock-o" : "hand-paper-o")}
|
||||||
aria-hidden="true" /></button>
|
aria-hidden="true" /></button>
|
||||||
<button title="Zoom In - Hotkey: =" type="button" className="btn btn-default btn-lg"
|
<button id="player-zoom-in" title="Zoom In - Hotkey: =" type="button" className="btn btn-default btn-lg"
|
||||||
onClick={this.zoomIn} disabled={this.state.term_zoom_max}>
|
onClick={this.zoomIn} disabled={this.state.term_zoom_max}>
|
||||||
<i className="fa fa-search-plus" aria-hidden="true" /></button>
|
<i className="fa fa-search-plus" aria-hidden="true" /></button>
|
||||||
<button title="Fit To - Hotkey: Z" type="button" className="btn btn-default btn-lg"
|
<button id="player-fit-to" title="Fit To - Hotkey: Z" type="button" className="btn btn-default btn-lg"
|
||||||
onClick={this.fitTo}><i className="fa fa-expand" aria-hidden="true" /></button>
|
onClick={this.fitTo}><i className="fa fa-expand" aria-hidden="true" /></button>
|
||||||
<button title="Zoom Out - Hotkey: -" type="button" className="btn btn-default btn-lg"
|
<button id="player-zoom-out" title="Zoom Out - Hotkey: -" type="button" className="btn btn-default btn-lg"
|
||||||
onClick={this.zoomOut} disabled={this.state.term_zoom_min}>
|
onClick={this.zoomOut} disabled={this.state.term_zoom_min}>
|
||||||
<i className="fa fa-search-minus" aria-hidden="true" /></button>
|
<i className="fa fa-search-minus" aria-hidden="true" /></button>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
192
src/terminal.jsx
192
src/terminal.jsx
|
|
@ -1,192 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Cockpit.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2016 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* Cockpit is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Cockpit is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import Player from "./player";
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var React = require("react");
|
|
||||||
var Term = require("term");
|
|
||||||
let $ = require("jquery");
|
|
||||||
|
|
||||||
require("console.css");
|
|
||||||
require("jquery-resizable");
|
|
||||||
require("jquery-resizable/resizable.css");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A terminal component that communicates over a cockpit channel.
|
|
||||||
*
|
|
||||||
* The only required property is 'channel', which must point to a cockpit
|
|
||||||
* stream channel.
|
|
||||||
*
|
|
||||||
* The size of the terminal can be set with the 'rows' and 'cols'
|
|
||||||
* properties. If those properties are not given, the terminal will fill
|
|
||||||
* its container.
|
|
||||||
*
|
|
||||||
* If the 'onTitleChanged' callback property is set, it will be called whenever
|
|
||||||
* the title of the terminal changes.
|
|
||||||
*
|
|
||||||
* Call focus() to set the input focus on the terminal.
|
|
||||||
*/
|
|
||||||
var Terminal = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
// cols: React.PropTypes.number,
|
|
||||||
rows: React.PropTypes.number,
|
|
||||||
channel: React.PropTypes.object.isRequired,
|
|
||||||
onTitleChanged: React.PropTypes.func
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillMount: function () {
|
|
||||||
var term = new Term({
|
|
||||||
cols: this.state.cols || 80,
|
|
||||||
rows: this.state.rows || 25,
|
|
||||||
screenKeys: true,
|
|
||||||
useStyle: true
|
|
||||||
});
|
|
||||||
|
|
||||||
term.on('data', function(data) {
|
|
||||||
if (this.props.channel.valid)
|
|
||||||
this.props.channel.send(data);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
if (this.props.onTitleChanged)
|
|
||||||
term.on('title', this.props.onTitleChanged);
|
|
||||||
|
|
||||||
this.setState({ terminal: term });
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidMount: function () {
|
|
||||||
this.state.terminal.open(this.refs.terminal);
|
|
||||||
this.connectChannel();
|
|
||||||
|
|
||||||
let term = this.refs.terminal;
|
|
||||||
let onWindowResize = this.onWindowResize;
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
$(term).resizable({
|
|
||||||
direction: ['right', 'bottom'],
|
|
||||||
stop: function() {
|
|
||||||
onWindowResize();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.props.rows) {
|
|
||||||
window.addEventListener('resize', this.onWindowResize);
|
|
||||||
this.onWindowResize();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUpdate: function (nextProps, nextState) {
|
|
||||||
if (nextState.cols !== this.state.cols || nextState.rows !== this.state.rows) {
|
|
||||||
this.state.terminal.resize(nextState.cols, nextState.rows);
|
|
||||||
this.props.channel.control({
|
|
||||||
window: {
|
|
||||||
rows: nextState.rows,
|
|
||||||
cols: nextState.cols
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextProps.channel !== this.props.channel) {
|
|
||||||
this.state.terminal.reset();
|
|
||||||
this.disconnectChannel();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidUpdate: function (prevProps) {
|
|
||||||
if (prevProps.channel !== this.props.channel)
|
|
||||||
this.connectChannel();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function () {
|
|
||||||
let style = {
|
|
||||||
'min-width': '300px',
|
|
||||||
'min-height': '100px',
|
|
||||||
};
|
|
||||||
// ensure react never reuses this div by keying it with the terminal widget
|
|
||||||
return <div ref="terminal" style={style} className="console-ct" key={this.state.terminal} />;
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.disconnectChannel();
|
|
||||||
this.state.terminal.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
onChannelMessage: function (event, data) {
|
|
||||||
if (this.state.terminal) {
|
|
||||||
this.state.terminal.write(data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onChannelClose: function (event, options) {
|
|
||||||
var term = this.state.terminal;
|
|
||||||
term.write('\x1b[31m' + (options.problem || 'disconnected') + '\x1b[m\r\n');
|
|
||||||
term.cursorHidden = true;
|
|
||||||
term.refresh(term.y, term.y);
|
|
||||||
},
|
|
||||||
|
|
||||||
connectChannel: function () {
|
|
||||||
var channel = this.props.channel;
|
|
||||||
if (channel && channel.valid) {
|
|
||||||
channel.addEventListener('message', this.onChannelMessage.bind(this));
|
|
||||||
channel.addEventListener('close', this.onChannelClose.bind(this));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnectChannel: function () {
|
|
||||||
if (this.props.channel) {
|
|
||||||
this.props.channel.removeEventListener('message', this.onChannelMessage);
|
|
||||||
this.props.channel.removeEventListener('close', this.onChannelClose);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
focus: function () {
|
|
||||||
if (this.state.terminal)
|
|
||||||
this.state.terminal.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
onWindowResize: function () {
|
|
||||||
if (this.refs) {
|
|
||||||
var padding = 2 * 11;
|
|
||||||
var node = this.getDOMNode();
|
|
||||||
var terminal = this.refs.terminal.querySelector('.terminal');
|
|
||||||
|
|
||||||
var ch = document.createElement('div');
|
|
||||||
ch.textContent = 'M';
|
|
||||||
terminal.appendChild(ch);
|
|
||||||
var height = ch.offsetHeight; // offsetHeight is only correct for block elements
|
|
||||||
ch.style.display = 'inline';
|
|
||||||
var width = ch.offsetWidth;
|
|
||||||
terminal.removeChild(ch);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
rows: Math.floor((node.parentElement.clientHeight - padding) / height),
|
|
||||||
cols: Math.floor((node.parentElement.clientWidth - padding) / width)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
send: function(value) {
|
|
||||||
this.state.terminal.send(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// module.exports = { Terminal: Terminal };
|
|
||||||
export class Terminal;
|
|
||||||
|
|
@ -15,45 +15,35 @@ import testlib
|
||||||
# Test with pre-recorded journal with tlog UID 981
|
# Test with pre-recorded journal with tlog UID 981
|
||||||
class TestApplication(testlib.MachineCase):
|
class TestApplication(testlib.MachineCase):
|
||||||
def testPlay(self):
|
def testPlay(self):
|
||||||
term_first_line = "#recording-wrap > div > div > div.panel-body > div > div > div > div:nth-child(1)"
|
term_first_line = ".xterm-accessibility-tree div:nth-child(1)"
|
||||||
play_btn = "button.margin-right-btn:nth-child(3)"
|
|
||||||
b = self.browser
|
b = self.browser
|
||||||
m = self.machine
|
m = self.machine
|
||||||
self.login_and_go("/session-recording")
|
self.login_and_go("/session-recording")
|
||||||
b.wait_present(".content-header-extra")
|
b.wait_present(".content-header-extra")
|
||||||
b.wait_present("#user")
|
b.wait_present("#user")
|
||||||
b.click(".listing-ct-item")
|
b.click(".listing-ct-item")
|
||||||
b.wait_present(play_btn)
|
b.click("#player-play-pause")
|
||||||
b.click(play_btn)
|
|
||||||
b.wait_timeout(30000)
|
b.wait_timeout(30000)
|
||||||
b.wait_in_text(term_first_line, "localhost")
|
b.wait_in_text(term_first_line, "localhost")
|
||||||
|
|
||||||
def testFastforwardControls(self):
|
def testFastforwardControls(self):
|
||||||
fast_forward_btn = "button.btn:nth-child(6)"
|
last_term_line = ".xterm-accessibility-tree > div:nth-child(26)"
|
||||||
restart_btn = "#recording-wrap > div > div > div.panel-footer > button:nth-child(5)"
|
slider = ".slider > .min-slider-handle"
|
||||||
slider = "div.slider-handle:nth-child(5)"
|
|
||||||
term_line = "#recording-wrap > div > div > div.panel-body > div > div > div > div:nth-child(26)"
|
|
||||||
b = self.browser
|
b = self.browser
|
||||||
m = self.machine
|
m = self.machine
|
||||||
self.login_and_go("/session-recording")
|
self.login_and_go("/session-recording")
|
||||||
b.wait_present(".content-header-extra")
|
b.wait_present(".content-header-extra")
|
||||||
b.wait_present("#user")
|
b.wait_present("#user")
|
||||||
b.click(".listing-ct-item")
|
b.click(".listing-ct-item")
|
||||||
b.wait_present(fast_forward_btn)
|
b.click("#player-fast-forward")
|
||||||
b.click(fast_forward_btn)
|
b.wait_in_text(last_term_line, "logout")
|
||||||
b.wait_present(slider)
|
|
||||||
b.wait_attr(slider, "style", "left: 100%;")
|
b.wait_attr(slider, "style", "left: 100%;")
|
||||||
b.wait_in_text(term_line, "logout")
|
|
||||||
# test restart playback
|
# test restart playback
|
||||||
b.wait_present(restart_btn)
|
b.click("#player-restart")
|
||||||
b.click(restart_btn)
|
b.wait_text(".xterm-accessibility-tree > div:nth-child(1)", "Blank line")
|
||||||
b.wait_text(".terminal-cursor", " ")
|
|
||||||
b.wait_attr(slider, "style", "left: 100%;")
|
b.wait_attr(slider, "style", "left: 100%;")
|
||||||
|
|
||||||
def testSpeedControls(self):
|
def testSpeedControls(self):
|
||||||
speed_up_btn = "button.btn:nth-child(9)"
|
|
||||||
speed_down_btn = "button.btn:nth-child(7)"
|
|
||||||
speed_restore_btn = "button.btn:nth-child(8)"
|
|
||||||
speed_val = ".panel-footer > span:nth-child(10)"
|
speed_val = ".panel-footer > span:nth-child(10)"
|
||||||
b = self.browser
|
b = self.browser
|
||||||
m = self.machine
|
m = self.machine
|
||||||
|
|
@ -62,48 +52,49 @@ class TestApplication(testlib.MachineCase):
|
||||||
b.wait_present("#user")
|
b.wait_present("#user")
|
||||||
b.click(".listing-ct-item")
|
b.click(".listing-ct-item")
|
||||||
# increase speed
|
# increase speed
|
||||||
b.wait_present(speed_up_btn)
|
b.wait_present("#player-speed-up")
|
||||||
b.click(speed_up_btn)
|
b.click("#player-speed-up")
|
||||||
b.wait_present(speed_val)
|
b.wait_present(speed_val)
|
||||||
b.wait_text(speed_val, "x2")
|
b.wait_text(speed_val, "x2")
|
||||||
b.click(speed_up_btn)
|
b.click("#player-speed-up")
|
||||||
b.wait_text(speed_val, "x4")
|
b.wait_text(speed_val, "x4")
|
||||||
b.click(speed_up_btn)
|
b.click("#player-speed-up")
|
||||||
b.wait_text(speed_val, "x8")
|
b.wait_text(speed_val, "x8")
|
||||||
b.click(speed_up_btn)
|
b.click("#player-speed-up")
|
||||||
b.wait_text(speed_val, "x16")
|
b.wait_text(speed_val, "x16")
|
||||||
# decrease speed
|
# decrease speed
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "x8")
|
b.wait_text(speed_val, "x8")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "x4")
|
b.wait_text(speed_val, "x4")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "x2")
|
b.wait_text(speed_val, "x2")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "")
|
b.wait_text(speed_val, "")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "/2")
|
b.wait_text(speed_val, "/2")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "/4")
|
b.wait_text(speed_val, "/4")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "/8")
|
b.wait_text(speed_val, "/8")
|
||||||
b.click(speed_down_btn)
|
b.click("#player-speed-down")
|
||||||
b.wait_text(speed_val, "/16")
|
b.wait_text(speed_val, "/16")
|
||||||
# restore speed
|
# restore speed
|
||||||
b.click(speed_restore_btn)
|
b.click("#player-speed-reset")
|
||||||
b.wait_text(speed_val, "")
|
b.wait_text(speed_val, "")
|
||||||
|
|
||||||
def testZoomControls(self):
|
def testZoomControls(self):
|
||||||
zoom_in_btn = "#recording-wrap > div > div > div.panel-footer > span:nth-child(11) > button:nth-child(3)"
|
|
||||||
zoom_out_btn = "#recording-wrap > div > div > div.panel-footer > span:nth-child(11) > button:nth-child(5)"
|
|
||||||
zoom_reset_btn = "#recording-wrap > div > div > div.panel-footer > span:nth-child(11) > button:nth-child(4)"
|
|
||||||
default_scale_sel = '.console-ct[style^="transform: scale(1)"]'
|
default_scale_sel = '.console-ct[style^="transform: scale(1)"]'
|
||||||
zoom_one_scale_sel = '.console-ct[style^="transform: scale(1.1)"]'
|
zoom_one_scale_sel = '.console-ct[style^="transform: scale(1.1)"]'
|
||||||
zoom_two_scale_sel = '.console-ct[style^="transform: scale(1.2)"]'
|
zoom_two_scale_sel = '.console-ct[style^="transform: scale(1.2)"]'
|
||||||
zoom_three_scale_sel = '.console-ct[style^="transform: scale(1.3)"]'
|
zoom_three_scale_sel = '.console-ct[style^="transform: scale(1.3)"]'
|
||||||
zoom_reset_scale_sel = '.console-ct[style^="transform: scale(0.823864)"]'
|
|
||||||
b = self.browser
|
b = self.browser
|
||||||
m = self.machine
|
m = self.machine
|
||||||
|
if m.image in ["fedora-29"] or m.image in ["rhel-8.0"] or m.image in ["rhel-8.1"]:
|
||||||
|
zoom_reset_scale_sel = '.console-ct[style*="transform: scale(0.8"]'
|
||||||
|
else:
|
||||||
|
zoom_reset_scale_sel = '.console-ct[style*="transform: scale(0.9"]'
|
||||||
|
|
||||||
self.login_and_go("/session-recording")
|
self.login_and_go("/session-recording")
|
||||||
b.wait_present(".content-header-extra")
|
b.wait_present(".content-header-extra")
|
||||||
b.wait_present("#user")
|
b.wait_present("#user")
|
||||||
|
|
@ -111,34 +102,32 @@ class TestApplication(testlib.MachineCase):
|
||||||
# Wait for terminal with scale(1)
|
# Wait for terminal with scale(1)
|
||||||
b.wait_present(default_scale_sel)
|
b.wait_present(default_scale_sel)
|
||||||
# Zoom in x3
|
# Zoom in x3
|
||||||
b.click(zoom_in_btn)
|
b.click("#player-zoom-in")
|
||||||
b.wait_present(zoom_one_scale_sel)
|
b.wait_present(zoom_one_scale_sel)
|
||||||
b.click(zoom_in_btn)
|
b.click("#player-zoom-in")
|
||||||
b.wait_present(zoom_two_scale_sel)
|
b.wait_present(zoom_two_scale_sel)
|
||||||
b.click(zoom_in_btn)
|
b.click("#player-zoom-in")
|
||||||
b.wait_present(zoom_three_scale_sel)
|
b.wait_present(zoom_three_scale_sel)
|
||||||
# Zoom Out
|
# Zoom Out
|
||||||
b.click(zoom_out_btn)
|
b.click("#player-zoom-out")
|
||||||
b.wait_present(zoom_two_scale_sel)
|
b.wait_present(zoom_two_scale_sel)
|
||||||
# Reset Zoom
|
# Reset Zoom
|
||||||
b.click(zoom_reset_btn)
|
b.click("#player-fit-to")
|
||||||
b.wait_present(zoom_reset_scale_sel)
|
b.wait_present(zoom_reset_scale_sel)
|
||||||
|
|
||||||
def testSkipFrame(self):
|
def testSkipFrame(self):
|
||||||
skip_frame_btn = "#recording-wrap > div > div > div.panel-footer > button:nth-child(4)"
|
term_first_line = ".xterm-accessibility-tree div:nth-child(1)"
|
||||||
term_first_line = "#recording-wrap > div > div > div.panel-body > div > div > div > div:nth-child(1)"
|
|
||||||
b = self.browser
|
b = self.browser
|
||||||
m = self.machine
|
m = self.machine
|
||||||
self.login_and_go("/session-recording")
|
self.login_and_go("/session-recording")
|
||||||
b.wait_present(".content-header-extra")
|
b.wait_present(".content-header-extra")
|
||||||
b.wait_present("#user")
|
b.wait_present("#user")
|
||||||
b.click(".listing-ct-item")
|
b.click(".listing-ct-item")
|
||||||
b.wait_present(skip_frame_btn)
|
b.click("#player-skip-frame")
|
||||||
b.click(skip_frame_btn)
|
b.click("#player-skip-frame")
|
||||||
b.click(skip_frame_btn)
|
b.click("#player-skip-frame")
|
||||||
b.click(skip_frame_btn)
|
b.click("#player-skip-frame")
|
||||||
b.click(skip_frame_btn)
|
b.click("#player-skip-frame")
|
||||||
b.click(skip_frame_btn)
|
|
||||||
b.wait_timeout(20)
|
b.wait_timeout(20)
|
||||||
b.wait_in_text(term_first_line, "localhost")
|
b.wait_in_text(term_first_line, "localhost")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ var info = {
|
||||||
"index.html",
|
"index.html",
|
||||||
"config.html",
|
"config.html",
|
||||||
"player.jsx",
|
"player.jsx",
|
||||||
|
"console.css",
|
||||||
"recordings.jsx",
|
"recordings.jsx",
|
||||||
"recordings.css",
|
"recordings.css",
|
||||||
"table.css",
|
"table.css",
|
||||||
"terminal.jsx",
|
|
||||||
"manifest.json",
|
"manifest.json",
|
||||||
"timer.css",
|
"timer.css",
|
||||||
"./pkg/lib/listing.less",
|
"./pkg/lib/listing.less",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue