Tests: Adds end-to-end tests skeleton and basic smoke test scenario (#16901)

* Chore: Adds neccessary packages

* Wip: Initial dummy test in place

* Feature: Downloads Chromium if needed

* Fix: Adds global config object

* Refactor: Adds basic e2eScenario

* Build: Adds end to end tests to config

* Build: Changes end to end job

* Build: Adds browsers to image

* Build: Adds failing test

* Refactor: Adds first e2e-test scenario

* Fix: Ignores test output in gitignore

* Refactor: Adds compare screenshots ability

* Refactor: Removes unnecessary code

* Build: Removes jest-puppeteer

* Fix: Replaces test snapshots

* Refactor: Creates output dir if missing

* Refactor: Changes aria-labels to be more consistent

* Docs: Adds section about end to end tests

* Fix: Fixes snapshots

* Docs: Adds information about ENV variables
This commit is contained in:
Hugo Häggmark
2019-05-08 16:50:21 +02:00
committed by GitHub
parent ceb9f0855b
commit a4d287d2e1
45 changed files with 838 additions and 28 deletions

View File

@@ -20,7 +20,7 @@
<div class="search-section__header" ng-show="section.hideHeader"></div>
<div ng-if="section.expanded">
<a ng-repeat="item in section.items" class="search-item search-item--indent" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" >
<a ng-repeat="item in section.items" class="search-item search-item--indent" ng-class="{'selected': item.selected}" ng-href="{{::item.url}}" aria-label="{{::item.title}}">
<div ng-click="ctrl.toggleSelection(item, $event)" class="center-vh">
<gf-form-checkbox
ng-show="ctrl.editable"

View File

@@ -132,10 +132,15 @@ export class AddPanelWidget extends React.Component<Props, State> {
dashboard.removePanel(this.props.panel);
};
renderOptionLink = (icon, text, onClick) => {
renderOptionLink = (icon: string, text: string, onClick) => {
return (
<div>
<a href="#" onClick={onClick} className="add-panel-widget__link btn btn-inverse">
<a
href="#"
onClick={onClick}
className="add-panel-widget__link btn btn-inverse"
aria-label={`${text} CTA button`}
>
<div className="add-panel-widget__icon">
<i className={`gicon gicon-${icon}`} />
</div>

View File

@@ -35,6 +35,7 @@ exports[`Render should render component 1`] = `
>
<div>
<a
aria-label="Add Query CTA button"
className="add-panel-widget__link btn btn-inverse"
href="#"
onClick={[Function]}
@@ -53,6 +54,7 @@ exports[`Render should render component 1`] = `
</div>
<div>
<a
aria-label="Choose Visualization CTA button"
className="add-panel-widget__link btn btn-inverse"
href="#"
onClick={[Function]}

View File

@@ -16,7 +16,11 @@ export const DashNavButton: FunctionComponent<Props> = ({ icon, tooltip, classSu
if (onClick) {
return (
<Tooltip content={tooltip}>
<button className={`btn navbar-button navbar-button--${classSuffix}`} onClick={onClick}>
<button
className={`btn navbar-button navbar-button--${classSuffix}`}
onClick={onClick}
aria-label={`${tooltip} navbar button`}
>
<i className={icon} />
</button>
</Tooltip>

View File

@@ -17,7 +17,7 @@ const template = `
<div class="p-t-2">
<div class="gf-form">
<label class="gf-form-label width-8">New name</label>
<input type="text" class="gf-form-input" ng-model="ctrl.clone.title" give-focus="true" required>
<input type="text" class="gf-form-input" ng-model="ctrl.clone.title" give-focus="true" required aria-label="Save dashboard title field">
</div>
<folder-picker initial-folder-id="ctrl.folderId"
on-change="ctrl.onFolderChange($folder)"
@@ -34,7 +34,14 @@ const template = `
</div>
<div class="gf-form-button-row text-center">
<button type="submit" class="btn btn-primary" ng-click="ctrl.save()" ng-disabled="!ctrl.isValidFolderSelection">Save</button>
<button
type="submit"
class="btn btn-primary"
ng-click="ctrl.save()"
ng-disabled="!ctrl.isValidFolderSelection"
aria-label="Save dashboard button">
Save
</button>
<a class="btn-text" ng-click="ctrl.dismiss();">Cancel</a>
</div>
</form>

View File

@@ -92,7 +92,7 @@
</div>
</div>
<div class="gf-form" ng-show="modeSharePanel">
<a href="{{imageUrl}}" target="_blank"><i class="fa fa-camera"></i> Direct link rendered image</a>
<a href="{{imageUrl}}" target="_blank" aria-label="Link to rendered image"><i class="fa fa-camera"></i> Direct link rendered image</a>
</div>
</div>
</script>

View File

@@ -90,7 +90,12 @@ export class PanelHeader extends Component<Props, State> {
error={error}
/>
<div className={panelHeaderClass}>
<div className="panel-title-container" onClick={this.onMenuToggle} onMouseDown={this.onMouseDown}>
<div
className="panel-title-container"
onClick={this.onMenuToggle}
onMouseDown={this.onMouseDown}
aria-label="Panel Title"
>
<div className="panel-title">
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text">

View File

@@ -14,7 +14,9 @@ export const PanelHeaderMenuItem: FC<Props & PanelMenuItem> = props => {
<li className={isSubMenu ? 'dropdown-submenu' : null}>
<a onClick={props.onClick}>
{props.iconClassName && <i className={props.iconClassName} />}
<span className="dropdown-item-text">{props.text}</span>
<span className="dropdown-item-text" aria-label={`${props.text} panel menu item`}>
{props.text}
</span>
{props.shortcut && <span className="dropdown-menu-item-shortcut">{props.shortcut}</span>}
</a>
{props.children}

View File

@@ -145,7 +145,7 @@ function TabItem({ tab, activeTab, onClick }: TabItemParams) {
return (
<div className="panel-editor-tabs__item" onClick={() => onClick(tab)}>
<a className={tabClasses}>
<a className={tabClasses} aria-label={`${tab.text} tab button`}>
<Tooltip content={`${tab.text}`} placement="auto">
<i className={`gicon gicon-${tab.id}${activeTab === tab.id ? '-active' : ''}`} />
</Tooltip>

View File

@@ -54,6 +54,7 @@ class NewDataSourcePage extends PureComponent<Props> {
onClick={() => this.onDataSourceTypeClicked(plugin)}
className="add-data-source-grid-item"
key={`${plugin.id}-${index}`}
aria-label={`${plugin.name} datasource plugin`}
>
<img className="add-data-source-grid-item-logo" src={plugin.info.logos.small} />
<span className="add-data-source-grid-item-text">{plugin.name}</span>

View File

@@ -12,7 +12,13 @@ const ButtonRow: FC<Props> = ({ isReadOnly, onDelete, onSubmit, onTest }) => {
return (
<div className="gf-form-button-row">
{!isReadOnly && (
<button type="submit" className="btn btn-primary" disabled={isReadOnly} onClick={event => onSubmit(event)}>
<button
type="submit"
className="btn btn-primary"
disabled={isReadOnly}
onClick={event => onSubmit(event)}
aria-label="Save and Test button"
>
Save &amp; Test
</button>
)}

View File

@@ -212,7 +212,7 @@ export class DataSourceSettingsPage extends PureComponent<Props, State> {
<div className="gf-form-group">
{testingMessage && (
<div className={`alert-${testingStatus} alert`}>
<div className={`alert-${testingStatus} alert`} aria-label="Datasource settings page Alert">
<div className="alert-icon">
{testingStatus === 'error' ? (
<i className="fa fa-exclamation-triangle" />
@@ -221,7 +221,9 @@ export class DataSourceSettingsPage extends PureComponent<Props, State> {
)}
</div>
<div className="alert-body">
<div className="alert-title">{testingMessage}</div>
<div className="alert-title" aria-label="Datasource settings page Alert message">
{testingMessage}
</div>
</div>
</div>
)}

View File

@@ -33,6 +33,7 @@ exports[`Render should render with buttons enabled 1`] = `
className="gf-form-button-row"
>
<button
aria-label="Save and Test button"
className="btn btn-primary"
disabled={false}
onClick={[Function]}

View File

@@ -17,7 +17,7 @@ const panelTemplate = `
<i class="fa fa-spinner fa-spin"></i>
</span>
<panel-header class="panel-title-container" panel-ctrl="ctrl"></panel-header>
<panel-header class="panel-title-container" panel-ctrl="ctrl" aria-label="Panel Title"></panel-header>
</div>
<div class="panel-content">

View File

@@ -34,7 +34,7 @@ function renderMenuItem(item, ctrl) {
}
html += `><i class="${item.icon}"></i>`;
html += `<span class="dropdown-item-text">${item.text}</span>`;
html += `<span class="dropdown-item-text" aria-label="${item.text} panel menu item">${item.text}</span>`;
if (item.shortcut) {
html += `<span class="dropdown-menu-item-shortcut">${item.shortcut}</span>`;

View File

@@ -8,15 +8,15 @@
<div class="login-inner-box" id="login-view">
<form name="loginForm" class="login-form-group gf-form-group" ng-hide="disableLoginForm">
<div class="login-form">
<input type="text" name="username" class="gf-form-input login-form-input" required ng-model='formModel.user' placeholder={{loginHint}}
<input type="text" name="username" class="gf-form-input login-form-input" required ng-model='formModel.user' placeholder={{loginHint}} aria-label="Username input field"
autofocus autofill-event-fix>
</div>
<div class="login-form">
<input type="password" name="password" class="gf-form-input login-form-input" required ng-model="formModel.password" id="inputPassword"
placeholder="{{passwordHint}}">
placeholder="{{passwordHint}}" aria-label="Password input field">
</div>
<div class="login-button-group">
<button type="submit" class="btn btn-large p-x-2" ng-if="!loggingIn" ng-click="submit();" ng-class="{'btn-inverse': !loginForm.$valid, 'btn-primary': loginForm.$valid}">
<button type="submit" aria-label="Login button" class="btn btn-large p-x-2" ng-if="!loggingIn" ng-click="submit();" ng-class="{'btn-inverse': !loginForm.$valid, 'btn-primary': loginForm.$valid}">
Log In
</button>
<button type="submit" class="btn btn-large p-x-2 btn-inverse btn-loading" ng-if="loggingIn">

View File

@@ -3,7 +3,7 @@
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Scenario</label>
<div class="gf-form-select-wrapper width-15">
<select class="gf-form-input" ng-model="ctrl.target.scenarioId" ng-options="v.id as v.name for v in ctrl.scenarioList" ng-change="ctrl.scenarioChanged()"></select>
<select class="gf-form-input" ng-model="ctrl.target.scenarioId" ng-options="v.id as v.name for v in ctrl.scenarioList" ng-change="ctrl.scenarioChanged()" aria-label="Scenario Select"></select>
</div>
</div>
<div class="gf-form gf-form gf-form--grow" ng-if="ctrl.scenario.stringInput">

View File

@@ -44,7 +44,7 @@
</div>
</div>
<div class="section gf-form-group">
<div class="section gf-form-group" aria-label="X-Axis section">
<h5 class="section-heading">X-Axis</h5>
<gf-form-switch class="gf-form" label="Show" label-class="width-6" checked="ctrl.panel.xaxis.show" on-change="ctrl.render()"></gf-form-switch>