Skip to content
Permalink
Browse files
fix(protractor): Added an interaction to Hover.over(target), correcte…
…d the DoubleClick interaction s
  • Loading branch information
jan-molak committed Sep 22, 2019
1 parent 753a0ce commit 13e480f3441b27476db1a6ac853ae528cd8f9016
@@ -11,17 +11,71 @@ describe('Clear', () => {
const Bernie = stage(new UIActors()).actor('Bernie');

const Form = {
Field: Target.the('name field').located(by.id('name')),
Field: Target.the('input field').located(by.id('field')),
};

/** @test {Clear} */
/** @test {Clear.theValueOf} */
it('allows the actor to clear the value of a field', () => Bernie.attemptsTo(
it('allows the actor to clear the value of an input field', () => Bernie.attemptsTo(
Navigate.to(pageFromTemplate(`
<html>
<body>
<form>
<input type="text" id="name" value="Jan" />
<input type="text" id="field" value="Jan" />
</form>
</body>
</html>
`)),

Clear.theValueOf(Form.Field),

Ensure.that(Value.of(Form.Field), equals('')),
));

/** @test {Clear} */
/** @test {Clear.theValueOf} */
it('allows the actor to clear the value of an number field', () => Bernie.attemptsTo(
Navigate.to(pageFromTemplate(`
<html>
<body>
<form>
<input type="number" id="field" value="42" >
</form>
</body>
</html>
`)),

Clear.theValueOf(Form.Field),

Ensure.that(Value.of(Form.Field), equals('')),
));

/** @test {Clear} */
/** @test {Clear.theValueOf} */
it('allows the actor to clear the value of a date field', () => Bernie.attemptsTo(
Navigate.to(pageFromTemplate(`
<html>
<body>
<form>
<input type="date" id="field" value="2019-09-22" />
</form>
</body>
</html>
`)),

Clear.theValueOf(Form.Field),

Ensure.that(Value.of(Form.Field), equals('')),
));

/** @test {Clear} */
/** @test {Clear.theValueOf} */
it('allows the actor to clear the value of an RTL input field', () => Bernie.attemptsTo(
Navigate.to(pageFromTemplate(`
<html dir="rtl">
<body>
<form>
<input type="text" id="field" value="שלום עולם" dir="rtl" />
</form>
</body>
</html>
@@ -35,6 +89,6 @@ describe('Clear', () => {
/** @test {Clear#toString} */
it('provides a sensible description of the interaction being performed', () => {
expect(Clear.theValueOf(Form.Field).toString())
.to.equal('#actor clears the value of the name field');
.to.equal('#actor clears the value of the input field');
});
});
@@ -0,0 +1,49 @@
import { expect, stage } from '@integration/testing-tools';
import { Ensure, equals } from '@serenity-js/assertions';
import { by } from 'protractor';

import { Attribute, Hover, Navigate, Target } from '../../../src';
import { pageFromTemplate } from '../../fixtures';
import { UIActors } from '../../UIActors';

describe('Hover', function () {

const Mickey = stage(new UIActors()).actor('Mickey');

const pageWithALink = pageFromTemplate(`
<html>
<body style="margin:0; padding:0 0 1024px 0;">
<h1>A page with a link</h1>
<a href="javascript:void(0)"
class="off"
onmouseover="this.className='on';" onmouseout="this.className='off';">
>link</a>
</body>
</html>
`);

const Page = {
Header: Target.the('header').located(by.css('h1')),
Link: Target.the('link').located(by.css('a')),
};

/** @test {Scroll} */
/** @test {Scroll.to} */
it('allows the actor to move the mouse to a given target', () => Mickey.attemptsTo(
Navigate.to(pageWithALink),

Ensure.that(Attribute.of(Page.Link).called('class'), equals('off')),

Hover.over(Page.Link),
Ensure.that(Attribute.of(Page.Link).called('class'), equals('on')),

Hover.over(Page.Header),
Ensure.that(Attribute.of(Page.Link).called('class'), equals('off')),
));

/** @test {Enter#toString} */
it('provides a sensible description of the interaction being performed', () => {
expect(Hover.over(Page.Link).toString())
.to.equal(`#actor hovers the mouse over the link`);
});
});
@@ -1,6 +1,6 @@
import { AnswersQuestions, Interaction, Question, UsesAbilities } from '@serenity-js/core';
import { formatted } from '@serenity-js/core/lib/io';
import { ElementFinder } from 'protractor';
import { ElementFinder, protractor } from 'protractor';
import { withAnswerOf } from '../withAnswerOf';

export class Clear extends Interaction {
@@ -13,10 +13,20 @@ export class Clear extends Interaction {
}

performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
return withAnswerOf(actor, this.field, elf => elf.clear());
return withAnswerOf(actor, this.field, elf =>
elf.getAttribute('value').then(value =>
elf.sendKeys(
protractor.Key.END,
...this.times(value.length, protractor.Key.BACK_SPACE),
),
));
}

toString(): string {
return formatted `#actor clears the value of ${ this.field }`;
}

private times(n: number, key: string) {
return Array.from(new Array(n)).map(() => key);
}
}
@@ -14,10 +14,16 @@ export class DoubleClick extends Interaction {
}

performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
// Since the deprecation of Webdriver's ControlFlow,
// Protractor's doubleClick might behave incorrectly when promises are used.
// The mouseMove/doubleClick combo works around that problem.
// See https://github.com/angular/protractor/issues/4578

return withAnswerOf(actor, this.target, elf =>
BrowseTheWeb.as(actor).actions()
.doubleClick(elf)
.perform());
.mouseMove(elf)
.perform()
.then(() => BrowseTheWeb.as(actor).actions().doubleClick().perform()));
}

toString(): string {
@@ -0,0 +1,25 @@
import { AnswersQuestions, Interaction, Question, UsesAbilities } from '@serenity-js/core';
import { formatted } from '@serenity-js/core/lib/io';
import { ElementFinder } from 'protractor';
import { BrowseTheWeb } from '../abilities';
import { withAnswerOf } from '../withAnswerOf';

export class Hover extends Interaction {
static over(target: Question<ElementFinder> | ElementFinder) {
return new Hover(target);
}

constructor(
private readonly target: Question<ElementFinder> | ElementFinder,
) {
super();
}

performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
return withAnswerOf(actor, this.target, elf => BrowseTheWeb.as(actor).actions().mouseMove(elf).perform());
}

toString(): string {
return formatted `#actor hovers the mouse over ${this.target}`;
}
}
@@ -4,6 +4,7 @@ export * from './DeleteCookies';
export * from './DoubleClick';
export * from './Enter';
export { ExecuteScript } from './execute-script';
export * from './Hover';
export * from './Navigate';
export * from './Press';
export * from './Scroll';

0 comments on commit 13e480f

Please sign in to comment.