Protractor Serenity中验证元素是否存在的语法咨询
Hey there! I get it—working with Protractor Serenity can feel a bit different from vanilla Protractor, especially when you need to add conditional logic based on whether an element exists. Let's break down how to do this properly, since standard Protractor approaches don't always translate directly to Serenity's task/interaction model.
The Core Issue with Your Previous Attempt
Serenity JS relies on its actor model and encapsulated interactions/tasks, so you can't just return a boolean directly from a raw Protractor check without wrapping it in a Serenity-compatible interaction. That's why your initial code wasn't working—you need to work within Serenity's architecture.
Step 1: Create a Custom Interaction to Check Element Presence
First, let's build a reusable interaction that an actor can perform to check if an element exists. This keeps your logic aligned with Serenity's patterns:
import { Interaction, Target } from '@serenity-js/protractor'; import { browser } from 'protractor'; // Custom interaction to check if a target element is present export const verifyElementPresence = (target: Target) => Interaction.where(`#actor verifies if ${target.name} is present`, async (actor) => { // Get the locator from the Serenity Target const elementLocator = target.locatedBy(); // Use Protractor's native check wrapped in an async function const isPresent = await browser.isElementPresent(elementLocator); // Return the boolean result to use in conditional logic return isPresent; });
Step 2: Use the Interaction in a Task for Conditional Logic
Now, create a task that uses this interaction to decide what to do next. Tasks are where you'll handle your branching logic:
import { Task, actorCalled } from '@serenity-js/core'; import { Click } from '@serenity-js/protractor'; import { verifyElementPresence } from './your-interactions-path'; import { Target } from '@serenity-js/protractor'; // Define your target elements as usual const SubmitButton = Target.the('submit button').locatedBy('#submit-btn'); const SkipLink = Target.the('skip link').locatedBy('#skip-action'); // Task with conditional logic based on element presence export const completeActionConditionally = Task.where( `#actor completes the action based on submit button presence`, async (actor) => { // Await the result of the presence check const submitButtonExists = await actor.attemptsTo(verifyElementPresence(SubmitButton)); if (submitButtonExists) { // If button exists, submit the form await actor.attemptsTo(Click.on(SubmitButton)); } else { // If button doesn't exist, take an alternative action await actor.attemptsTo(Click.on(SkipLink)); } } ); // Example usage in your test actorCalled('Bob').attemptsTo(completeActionConditionally());
Key Notes to Remember
- Always await
actor.attemptsTo(): Since interactions return promises, you need to await them to get the actual boolean result for your condition. - Stick to Serenity's abstractions: Avoid mixing raw Protractor code directly in your tests—wrap it in interactions/tasks to keep your test suite maintainable and aligned with Serenity's design principles.
- Reusability: The
verifyElementPresenceinteraction can be reused across all your tasks where you need to check element existence.
内容的提问来源于stack exchange,提问作者don kon

