tests: prefer attributes over classes in e2e tests

This commit is contained in:
Roman Hotsiy 2018-03-19 16:33:26 +02:00
parent 03cc781b8d
commit 5b136c1a2f
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
6 changed files with 23 additions and 19 deletions

View File

@ -14,13 +14,13 @@ describe('Menu', () => {
cy cy
.contains('h1', 'Introduction') .contains('h1', 'Introduction')
.scrollIntoView() .scrollIntoView()
.get('.menu-item.active:not(.-depth0)') .get('[role=menuitem].active:not(.-depth0)')
.should('have.text', 'Introduction'); .should('have.text', 'Introduction');
cy cy
.contains('h2', 'Add a new pet to the store') .contains('h2', 'Add a new pet to the store')
.scrollIntoView() .scrollIntoView()
.get('.menu-item.active:not(.-depth0)') .get('[role=menuitem].active:not(.-depth0)')
.should('have.length', 2) .should('have.length', 2)
.last() .last()
.should('have.text', 'Add a new pet to the store') .should('have.text', 'Add a new pet to the store')
@ -29,23 +29,23 @@ describe('Menu', () => {
// for some reason fails in cypress headless. Works fine in all browsers and cypress interactive // for some reason fails in cypress headless. Works fine in all browsers and cypress interactive
xit('should update URL hash on clicking on menu items', function() { xit('should update URL hash on clicking on menu items', function() {
cy.contains('.menu-item.-depth1', 'pet').click({ force: true }); cy.contains('[role=menuitem].-depth1', 'pet').click({ force: true });
cy.location('hash').should('equal', '#tag/pet'); cy.location('hash').should('equal', '#tag/pet');
cy.contains('.menu-item', 'Find pet by ID').click({ force: true }); cy.contains('[role=menuitem]', 'Find pet by ID').click({ force: true });
cy.location('hash').should('equal', '#operation/getPetById'); cy.location('hash').should('equal', '#operation/getPetById');
cy.contains('.menu-item', 'OpenAPI Specification').click({ force: true }); cy.contains('[role=menuitem]', 'OpenAPI Specification').click({ force: true });
cy.location('hash').should('equal', '#section/OpenAPI-Specification'); cy.location('hash').should('equal', '#section/OpenAPI-Specification');
}); });
it('should deactivate tag when other is activated', function() { it('should deactivate tag when other is activated', function() {
const petItem = () => cy.contains('.menu-item.-depth1', 'pet'); const petItem = () => cy.contains('[role=menuitem].-depth1', 'pet');
petItem() petItem()
.click({ force: true }) .click({ force: true })
.should('have.class', 'active'); .should('have.class', 'active');
cy.contains('.menu-item.-depth1', 'store').click({ force: true }); cy.contains('[role=menuitem].-depth1', 'store').click({ force: true });
petItem().should('not.have.class', 'active'); petItem().should('not.have.class', 'active');
}); });
}); });

View File

@ -123,7 +123,7 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat
results.sort((a, b) => b.score - a.score); results.sort((a, b) => b.score - a.score);
return ( return (
<SearchWrap> <SearchWrap role="search">
{this.state.term && <ClearIcon onClick={this.clear}>×</ClearIcon>} {this.state.term && <ClearIcon onClick={this.clear}>×</ClearIcon>}
<SearchIcon /> <SearchIcon />
<SearchInput <SearchInput
@ -134,7 +134,7 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat
onChange={this.search} onChange={this.search}
/> />
{results.length > 0 && ( {results.length > 0 && (
<SearchResultsBox> <SearchResultsBox data-role="search:results">
{results.map((res, idx) => ( {results.map((res, idx) => (
<MenuItem <MenuItem
item={Object.create(res.item, { item={Object.create(res.item, {
@ -145,6 +145,7 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat
onActivate={this.props.onActivate} onActivate={this.props.onActivate}
withoutChildren={true} withoutChildren={true}
key={res.item.id} key={res.item.id}
data-role="search:result"
/> />
))} ))}
</SearchResultsBox> </SearchResultsBox>

View File

@ -46,9 +46,7 @@ export const SearchIcon = styled((props: any) => (
} }
`; `;
export const SearchResultsBox = styled.div.attrs({ export const SearchResultsBox = styled.div`
className: 'search-results',
})`
padding: ${props => props.theme.spacingUnit / 4}px 0; padding: ${props => props.theme.spacingUnit / 4}px 0;
background-color: #ededed; background-color: #ededed;
min-height: 150px; min-height: 150px;

View File

@ -11,15 +11,20 @@ interface MenuItemsProps {
active?: boolean; active?: boolean;
onActivate?: (item: IMenuItem) => void; onActivate?: (item: IMenuItem) => void;
style?: React.CSSProperties; style?: React.CSSProperties;
root?: boolean;
} }
@observer @observer
export class MenuItems extends React.Component<MenuItemsProps> { export class MenuItems extends React.Component<MenuItemsProps> {
render() { render() {
const { items } = this.props; const { items, root } = this.props;
const active = this.props.active == null ? true : this.props.active; const active = this.props.active == null ? true : this.props.active;
return ( return (
<MenuItemUl style={this.props.style} active={active}> <MenuItemUl
style={this.props.style}
active={active}
{...(root ? { role: 'navigation' } : {})}
>
{items.map((item, idx) => ( {items.map((item, idx) => (
<MenuItem key={idx} item={item} onActivate={this.props.onActivate} /> <MenuItem key={idx} item={item} onActivate={this.props.onActivate} />
))} ))}

View File

@ -24,10 +24,11 @@ export class SideMenu extends React.Component<{ menu: MenuStore }> {
}} }}
items={store.items} items={store.items}
onActivate={this.activate} onActivate={this.activate}
root={true}
/> />
) : ( ) : (
<PerfectScrollbar updateFn={this.saveScrollUpdate}> <PerfectScrollbar updateFn={this.saveScrollUpdate}>
<MenuItems items={store.items} onActivate={this.activate} /> <MenuItems items={store.items} onActivate={this.activate} root={true} />
</PerfectScrollbar> </PerfectScrollbar>
) )
} }

View File

@ -115,8 +115,9 @@ export const MenuItemLabel = withProps<{
active: boolean; active: boolean;
deprecated?: boolean; deprecated?: boolean;
}>(styled.label).attrs({ }>(styled.label).attrs({
role: 'menuitem',
className: props => className: props =>
classnames('menu-item', '-depth' + props.depth, { classnames('-depth' + props.depth, {
active: props.active, active: props.active,
}), }),
})` })`
@ -137,9 +138,7 @@ export const MenuItemLabel = withProps<{
} }
`; `;
export const MenuItemTitle = withProps<{ width?: string }>(styled.span).attrs({ export const MenuItemTitle = withProps<{ width?: string }>(styled.span)`
className: 'menu-item-title',
})`
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
width: ${props => (props.width ? props.width : 'auto')}; width: ${props => (props.width ? props.width : 'auto')};