зеркало из https://github.com/mozilla/treeherder.git
Bug 1585966 - Centered header titles from Compare views should be editable
This commit is contained in:
Родитель
b2c6b5c76a
Коммит
979573904e
|
@ -9,8 +9,9 @@ import {
|
|||
|
||||
import projects from '../mock/repositories';
|
||||
import CompareTableControls from '../../../ui/perfherder/compare/CompareTableControls';
|
||||
import { compareTableText, filterText } from '../../../ui/perfherder/constants';
|
||||
import CompareTable from '../../../ui/perfherder/compare/CompareTable';
|
||||
import ComparePageTitle from '../../../ui/perfherder/compare/ComparePageTitle';
|
||||
import { compareTableText, filterText } from '../../../ui/perfherder/constants';
|
||||
|
||||
// TODO addtional tests:
|
||||
// 1) that the table is receiving the correct data structure after data
|
||||
|
@ -132,6 +133,15 @@ const compareTable = (
|
|||
/>,
|
||||
);
|
||||
|
||||
const comparepageTitle = () =>
|
||||
render(
|
||||
<ComparePageTitle
|
||||
title="Perfherder Compare Revisions"
|
||||
updateParams={() => {}}
|
||||
pageTitleQueryParam="Perfherder Compare Revisions"
|
||||
/>,
|
||||
);
|
||||
|
||||
test('toggle buttons should filter results by selected filter', async () => {
|
||||
const { getByText } = compareTableControls();
|
||||
|
||||
|
@ -313,3 +323,100 @@ test('retrigger button should not appear for test with no jobs', async () => {
|
|||
|
||||
expect(mockDataRetrigger.retriggers).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('display of page title', async () => {
|
||||
const { getAllByTitle, getAllByText } = comparepageTitle();
|
||||
|
||||
const pageTitleTitle = getAllByTitle('Click to change the page title');
|
||||
const pageTitleDefaultText = getAllByText('Perfherder Compare Revisions');
|
||||
|
||||
// title defaults to 'Perfherder Compare Revisions'
|
||||
expect(pageTitleTitle[0]).toHaveTextContent('Perfherder Compare Revisions');
|
||||
expect(pageTitleDefaultText).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('Button hides when clicking on it and a Input is displayed', async () => {
|
||||
const { queryByText, container } = comparepageTitle();
|
||||
const pageTitleDefaultText = queryByText('Perfherder Compare Revisions');
|
||||
await fireEvent.click(pageTitleDefaultText);
|
||||
expect(container.firstChild).toHaveClass('input-group');
|
||||
});
|
||||
|
||||
test('clicking the title button does not change the title', async () => {
|
||||
const { getByText, getByDisplayValue } = comparepageTitle();
|
||||
|
||||
const pageTitleDefaultText = await waitForElement(() =>
|
||||
getByText('Perfherder Compare Revisions'),
|
||||
);
|
||||
|
||||
fireEvent.click(pageTitleDefaultText);
|
||||
await waitForElement(() => getByDisplayValue('Perfherder Compare Revisions'));
|
||||
|
||||
await waitForElement(() => getByDisplayValue('Perfherder Compare Revisions'));
|
||||
});
|
||||
|
||||
test('setting a title on page updates the title accordingly', async () => {
|
||||
const { getByText, getByDisplayValue } = comparepageTitle();
|
||||
|
||||
const pageTitleDefaultText = await waitForElement(() =>
|
||||
getByText('Perfherder Compare Revisions'),
|
||||
);
|
||||
|
||||
fireEvent.click(pageTitleDefaultText);
|
||||
const inputField = await waitForElement(() =>
|
||||
getByDisplayValue('Perfherder Compare Revisions'),
|
||||
);
|
||||
fireEvent.change(inputField, {
|
||||
target: { value: 'some new value' },
|
||||
});
|
||||
// pressing 'Enter' has some issues on react-testing-library;
|
||||
// found workaround on https://github.com/testing-library/react-testing-library/issues/269
|
||||
fireEvent.keyPress(inputField, { key: 'Enter', keyCode: 13 });
|
||||
|
||||
// ensure this updated the title
|
||||
await waitForElement(() => getByDisplayValue('some new value'));
|
||||
});
|
||||
|
||||
test('re-editing the title is possible', async () => {
|
||||
const { getByText, getByDisplayValue } = comparepageTitle();
|
||||
|
||||
const pageTitleDefaultText = await waitForElement(() =>
|
||||
getByText('Perfherder Compare Revisions'),
|
||||
);
|
||||
|
||||
fireEvent.click(pageTitleDefaultText);
|
||||
const inputField = await waitForElement(() =>
|
||||
getByDisplayValue('Perfherder Compare Revisions'),
|
||||
);
|
||||
fireEvent.change(inputField, {
|
||||
target: { value: 'some new value' },
|
||||
});
|
||||
fireEvent.keyPress(inputField, { key: 'Enter', keyCode: 13 });
|
||||
|
||||
await waitForElement(() => getByDisplayValue('some new value'));
|
||||
fireEvent.change(inputField, {
|
||||
target: { value: 'another new value' },
|
||||
});
|
||||
fireEvent.keyPress(inputField, { key: 'Enter', keyCode: 13 });
|
||||
|
||||
await waitForElement(() => getByDisplayValue('another new value'));
|
||||
});
|
||||
|
||||
test("'Escape' from partially edited title does not update original title", async () => {
|
||||
const { getByText, getByDisplayValue } = comparepageTitle();
|
||||
|
||||
const pageTitleDefaultText = await waitForElement(() =>
|
||||
getByText('Perfherder Compare Revisions'),
|
||||
);
|
||||
|
||||
fireEvent.click(pageTitleDefaultText);
|
||||
const inputField = await waitForElement(() =>
|
||||
getByDisplayValue('Perfherder Compare Revisions'),
|
||||
);
|
||||
fireEvent.change(inputField, {
|
||||
target: { value: 'new value' },
|
||||
});
|
||||
fireEvent.keyDown(inputField, { key: 'Escape' });
|
||||
|
||||
await waitForElement(() => getByText('Perfherder Compare Revisions'));
|
||||
});
|
||||
|
|
|
@ -454,3 +454,13 @@ li.pagination-active.active > button {
|
|||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
visibility: hidden;
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.page-title-text:hover .edit-icon {
|
||||
visibility: visible;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Input, InputGroup } from 'reactstrap';
|
||||
import { faEdit } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import { replaceLocation, getAllUrlParams } from '../../helpers/location';
|
||||
|
||||
export default class ComparePageTitle extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inEditMode: false,
|
||||
pageTitle: props.pageTitleQueryParam || props.title,
|
||||
newPageTitle: props.pageTitleQueryParam || props.title,
|
||||
};
|
||||
}
|
||||
|
||||
goToEditMode = () => {
|
||||
this.setState({
|
||||
inEditMode: true,
|
||||
});
|
||||
};
|
||||
|
||||
resetToDefault = async event => {
|
||||
const { title } = this.props;
|
||||
const { newPageTitle } = this.state || event.target.value;
|
||||
this.setState({
|
||||
inEditMode: false,
|
||||
pageTitle: title,
|
||||
newPageTitle: title,
|
||||
});
|
||||
this.changeQueryParam(newPageTitle);
|
||||
};
|
||||
|
||||
editpageTitle = newPageTitle => {
|
||||
this.setState({ newPageTitle });
|
||||
};
|
||||
|
||||
changeTitle = async newTitle => {
|
||||
const { pageTitle } = this.state;
|
||||
|
||||
this.setState({ inEditMode: false });
|
||||
if (newTitle !== pageTitle) {
|
||||
this.setState({ pageTitle: newTitle });
|
||||
this.changeQueryParam(newTitle);
|
||||
}
|
||||
};
|
||||
|
||||
changeQueryParam = newTitle => {
|
||||
const params = getAllUrlParams();
|
||||
params.set('pageTitle', newTitle);
|
||||
replaceLocation(params, '/compare');
|
||||
};
|
||||
|
||||
userActionListener = async event => {
|
||||
const { pageTitle } = this.state;
|
||||
const { newPageTitle } = this.state || event.target.value;
|
||||
|
||||
if (!newPageTitle && event.key !== 'Escape') {
|
||||
this.resetToDefault(event);
|
||||
} else if (event.key === 'Enter') {
|
||||
this.changeTitle(newPageTitle);
|
||||
} else if (event.key === 'Escape') {
|
||||
this.setState({ inEditMode: false, newPageTitle: pageTitle });
|
||||
}
|
||||
};
|
||||
|
||||
injectEnter = () => {
|
||||
const keyboardEvent = new KeyboardEvent('keydown', { key: 'Enter' });
|
||||
this.userActionListener(keyboardEvent);
|
||||
};
|
||||
|
||||
injectEscape = () => {
|
||||
const keyboardEvent = new KeyboardEvent('keydown', { key: 'Escape' });
|
||||
this.userActionListener(keyboardEvent);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { inEditMode, pageTitle, newPageTitle } = this.state;
|
||||
|
||||
return !inEditMode ? (
|
||||
<Button
|
||||
className="text-center"
|
||||
size="lg"
|
||||
color="white"
|
||||
onClick={this.goToEditMode}
|
||||
title="Click to change the page title"
|
||||
>
|
||||
<h1 className="page-title-text">
|
||||
{pageTitle}
|
||||
<FontAwesomeIcon
|
||||
icon={faEdit}
|
||||
className="fa-xs align-top edit-icon"
|
||||
/>
|
||||
</h1>
|
||||
</Button>
|
||||
) : (
|
||||
<InputGroup>
|
||||
<Input
|
||||
className="pb-1 col-sm-12 page-title-input"
|
||||
ref={this.inputRef}
|
||||
color="white"
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: 'xx-large',
|
||||
}}
|
||||
value={newPageTitle}
|
||||
onChange={event => this.editpageTitle(event.target.value)}
|
||||
onKeyDown={event => this.userActionListener(event)}
|
||||
autoFocus
|
||||
/>
|
||||
<Button
|
||||
className="ml-3 my-2"
|
||||
vertical="center"
|
||||
size="lg"
|
||||
color="secondary"
|
||||
onClick={this.injectEnter}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button size="lg" color="link" onClick={this.injectEscape}>
|
||||
Cancel
|
||||
</Button>
|
||||
</InputGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ComparePageTitle.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
pageTitleQueryParam: PropTypes.string.isRequired,
|
||||
};
|
|
@ -22,6 +22,7 @@ import LoadingSpinner from '../../shared/LoadingSpinner';
|
|||
import { scrollToLine } from '../../helpers/utils';
|
||||
|
||||
import RevisionInformation from './RevisionInformation';
|
||||
import ComparePageTitle from './ComparePageTitle';
|
||||
import CompareTableControls from './CompareTableControls';
|
||||
import NoiseTable from './NoiseTable';
|
||||
|
||||
|
@ -189,6 +190,7 @@ export default class CompareTableView extends React.Component {
|
|||
newRevision,
|
||||
originalResultSet,
|
||||
newResultSet,
|
||||
pageTitle,
|
||||
} = this.props.validated;
|
||||
|
||||
const {
|
||||
|
@ -274,9 +276,14 @@ export default class CompareTableView extends React.Component {
|
|||
<Row>
|
||||
<Col sm="12" className="text-center pb-1">
|
||||
<h1>
|
||||
{hasSubtests
|
||||
? `${title} subtest summary`
|
||||
: 'Perfherder Compare Revisions'}
|
||||
<ComparePageTitle
|
||||
title={
|
||||
hasSubtests
|
||||
? `${title} subtest summary`
|
||||
: 'Perfherder Compare Revisions'
|
||||
}
|
||||
pageTitleQueryParam={pageTitle}
|
||||
/>
|
||||
</h1>
|
||||
<RevisionInformation
|
||||
originalProject={originalProject}
|
||||
|
|
Загрузка…
Ссылка в новой задаче