Serenity js 如何使用两个参数创建任务?

Serenity js 如何使用两个参数创建任务?,serenity-js,Serenity Js,在Serenity js书中,我们有一个任务示例,其中只有一个参数: // spec/screenplay/tasks/add_a_todo_item.ts import { PerformsTasks, Task } from 'serenity-js/protractor'; export class AddATodoItem implements Task { static called(itemName: string) { // stat

在Serenity js书中,我们有一个任务示例,其中只有一个参数:

// spec/screenplay/tasks/add_a_todo_item.ts
import { PerformsTasks, Task } from 'serenity-js/protractor';

export class AddATodoItem implements Task {

static called(itemName: string) {                       // static method to improve the readability
    return new AddATodoItem(itemName);
}

performAs(actor: PerformsTasks): PromiseLike<void> {    // required by the Task interface
    return actor.attemptsTo(                            // delegates the work to lower-level tasks
        // todo: interact with the UI
    );
}

constructor(private itemName: string) {                 // constructor assigning the name of the item
                                                        // to a private field
}
performAs:只需添加交互即可键入截止日期

我们将有第二个静态方法。 并且可能会更改被调用的方法返回


感谢您的解释。

根据哪些参数是必需的,哪些是可选的,以及您希望任务包含多少参数,有几种方法可以完成此任务

无参数 如果您有一个没有参数的任务,则更容易定义它的方法是使用
任务。其中

从'@serenity js/core'导入{Task};
const Login=()=>Task.where(`actor登录`,
单击.on(提交按钮),
);
这与使用下面的类样式定义几乎相同,但代码要少得多:

类登录扩展任务{
表演(演员:表演任务){
返回actor.attemptto(
单击.on(提交按钮),
);
}
toString(){
返回“#参与者登录”;
}
}
一个参数 您可以将上述方法用于应接收一个参数的任务:

constloginas=(username:string)=>Task.where(`actor以${username}身份登录),
在(用户名字段)中输入.theValue(用户名),
单击.on(提交按钮),
);
或者,您也可以按如下方式实现:

const登录={
as:(username:string)=>Task.where(`actor以${username}身份登录),
在(用户名字段)中输入.theValue(用户名),
单击.on(提交按钮),
),
}
我发现第二个版本更优雅,更符合内置交互,如
Click.on
Enter.theValue
,等等,因为您将在参与者流中调用
Login.as
,而不是
LoginAs

N参数 如果有超过1个参数,但所有参数都是必需的,并且您只需要一个优雅的DSL,那么您可以如下扩展上述模式:

const登录={
as:(用户名:字符串)=>({
identifiedBy:(password:string)=>Task.where(`actor以${username}身份登录),
在(…)中输入.theValue(用户名),
在(…)中输入.theValue(password).into,
单击.on(提交按钮),
}),
}
然后调用上述任务:

actor.attemptto(
Login.as(用户名).identifiedBy(密码),
);
这种设计不是特别灵活,因为它不允许您更改参数的顺序(即,您不能说
Login.identifiedBy(password).as(username)
)或使某些参数成为可选参数,但它只需相对较少的实现工作即可为您提供一个美观的DSL

更灵活 如果您需要更大的灵活性,例如在某些参数是可选的场景中,您可以选择类样式定义和准(我说“准”,因为它不会改变对象,而是生成新对象)

例如,假设系统要求提供用户名,但密码可能是可选的

类登录扩展任务{
静态身份(用户名:字符串){
返回新登录名(用户名);
}
identifiedBy(密码:string){
返回新登录名(this.username,password);
}
建造师(
私有只读用户名:string,
私有只读密码:字符串=“”,
) {
超级();
}
表演(演员:表演任务){
return actor.attemptto(
在(…)中输入.theValue(用户名),
在(…)中输入.theValue(password).into,
单击.on(提交按钮),
);
}
toString(){
return`#actor以${this.username}身份登录`;
}
}
当然,您可以更进一步,将实例化任务的行为与任务本身分离,如果不同任务的差异足以证明单独的实现是合理的,这将非常有用:

导出类登录{
静态身份(用户名:字符串){
返回新的loginWithUserName(用户名);
}
}
类loginWithUserName仅扩展任务{
建造师(
私有只读用户名:string,
) {
超级();
}
identifiedBy(密码:string){
返回带有用户名和密码(this.username,password)的新登录名;
}
表演(演员:表演任务){
return actor.attemptto(
在(…)中输入.theValue(用户名),
单击.on(提交按钮),
);
}
toString(){
return`#actor以${this.username}身份登录`;
}
}
使用UserName和Password扩展任务的类Login{
建造师(
私有只读用户名:string,
私有只读用户名:string,
) {
超级();
}
表演(演员:表演任务){
return actor.attemptto(
在(…)中输入.theValue(this.username),
在(…)中输入.theValue(this.password).into,
单击.on(提交按钮),
);
}
toString(){
return`#actor以${this.username}身份登录`;
}
}
上述两种实现都允许您以
Login.as(username)
Login.as(username).identifiedBy(password)
的形式调用任务,但第一种实现使用默认值空字符串作为密码,第二种实现甚至不触及密码字段

我希望这有帮助


Jan

谢谢Jan。你的回答将帮助我改进我的编码风格。任何时候,很高兴能提供帮助!欢迎加入与其他Serenity/JS用户聊天:-)
constructor(private itemName: string, private deadline: Date) {
}