访问新网址赛普拉斯

Posted

技术标签:

【中文标题】访问新网址赛普拉斯【英文标题】:Visit new url Cypress 【发布时间】:2020-08-15 07:32:11 【问题描述】:

我是赛普拉斯的新手。我的应用程序作为“路由系统”手动更改window.location.hash。 在某些时候,我单击了一个更改哈希的按钮,因此应该在测试期间更改页面。我可以在执行过程中看到一个“新 url”条目,但是如何让 cypress 访问该 url?

简而言之,问题是什么:您可以看到我输入了密码,然后输入了enter。运行测试可以看到地址栏的hash变化,但是页面并没有随着hash变化而变化。

这是测试代码

context("Workflow", () => 

    it("login", () => 

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demo").should("have.value", "demouser")
        cy.get("#password").type("demoenter").should("have.value", "demo") // this should redirect to "/#home"
        //cy.wait(10000)
        cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"
    )
)

编辑:经过无数次失败的尝试,我想出了一个部分有效、笨拙且笨拙的解决方案。我认为我不需要使用reload() 来解决这个问题(必须有更好的解决方案..),但要使其正常工作,我必须等待所有远程请求完成(否则reload() 会取消它们)。我说部分工作,因为如果我尝试先访问#login,然后按照#home 中的重定向,然后将页面更改为#browser,您可以从代码中的 cmets 看到,最后一个不起作用(我可以看到哈希更改为#browser,但页面仍然是#home)。

import 'cypress-wait-until';

let i = 0;

context("Workflow", () => 
    it("login", () => 
        cy.server( 
            onRequest: () => 
                i++;
            ,
            onResponse: () => 
                i--;
            
        );

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demouser").should("have.value", "demouser")
        cy.get("#password").type("demouser").should("have.value", "demouser")
        cy.get("form#formLogin").submit()

        cy.waitUntil(() => i > 0)
        cy.waitUntil(() => i === 0)
        cy.reload(); // it correctly change the hash AND the page to #home!

        cy.url().should("include", "#home") 
        cy.get(".version").contains( "v2.0.0-beta") // it works!!

        cy.get("a[data-id=browser]").click(force: true) // it correctly changes the hash to #browser
        cy.waitUntil(() => i > 0)
        cy.waitUntil(() => i === 0)
        cy.reload();

        // the hash in the address bar is #browser, but the web page is #home
    )
)

【问题讨论】:

你试过cy.visit()吗? cy.visit() 将 url 作为参数。我不需要那个。我只需要访问菜单按钮指向的页面。 所以你点击了一个按钮,它会手动更改锚点 AKA window.location.hash。当您手动点击网页中的按钮时,您是否重定向到锚点? 当然可以,网站本身也可以正常工作。整个问题是当我在 cypress 中运行它时,我使用 cy.find("#mybutton").click() 单击一个按钮,而 cypress 根本不会更改页面。 你说你点击了一个按钮,但上面的日志中没有显示。可能是因为cy.find("#mybutton") 是无效语法,请参阅here。显示测试代码会更有帮助。 【参考方案1】:

有一些方法可以做到这一点。其中一种基本方法是这样的:

  cy.visit(`your_login_page`)
  cy.get('[data-testid="input-username"]').type(`demo`,  force: true )
  cy.get('[data-testid="input-password"]')
    .type(`demo`, 
      force: true,
    )
    .wait(1000)
    .then(() => 
      cy.location().should((loc) => 
        expect(loc.pathname).to.eq(your_new_url)
      )
    )

您应该将data-testidfindByTestId 添加到具有唯一ID 的元素中。 访问新网址可以使用cy.visit(loc.pathname)

【讨论】:

谢谢,在我的情况下是expect(loc.hash).to.eq("#home"),就好像你只改变了hash pathname 是一样的。无论如何,这种断言不会失败,但赛普拉斯实际上并没有根据哈希变化来改变页面。所以如果我尝试在主页上搜索一个元素,比如cy.get(".subtitle"),它会失败【参考方案2】:

赛普拉斯有一个名为url:changed 的事件。请参阅关于事件 here

的文档

使用这个,像这样可能工作:

context("Workflow", () => 
    it("login", () => 

        cy.on('url:changed', url => 
            cy.location('hash').then(hash => 
                if (!url.endsWith(hash)) 
                    cy.visit(url);
                
            );
        );

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demo").should("have.value", "demouser")
        cy.get("#password").type("demoenter").should("have.value", "demo") // this should redirect to "/#home"
        cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"

    )
)

编辑:仅出于故障排除目的并专注于您的问题,您可以在没有cy.location() 的情况下尝试这样吗:

context("Workflow", () => 
    it("login", () => 

        cy.on('url:changed', url => 
            cy.visit(url);
        );

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demo").should("have.value", "demouser")
        cy.get("#password").type("demoenter").should("have.value", "demo") // this should redirect to "/#home"
        cy.get(".subtitle").should("have.value", "Welcome") //this line fails as ".subtitle" is an element of "/#home"

    )
)

编辑:你试过cy.reload()

context("Workflow", () => 

    it("login", () => 

        cy.visit("http://localhost:3000/src/#login")
        cy.get("#username").type("demo").should("have.value", "demouser")
        cy.get("#password").type("demoenter").should("have.value", "demo") // this should redirect to "/#home"
        cy.reload();
        cy.get(".subtitle").should("have.value", "Welcome");
    )
)

【讨论】:

你的代码抛出错误:Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise. The command that returned the promise was: > cy.visit() The cy command you invoked inside the promise was: > cy.location() 还有一件事要尝试:) 还有一个submit() 命令可以用于form 元素,例如:cy.get('form').submit() 您是否尝试在 Chrome 而不是 Electron 中运行 cypress 测试? 最后评论,我在 :) 之后放弃。我在使用 litElements 和 shadow DOM 搜索 cypress 时发现了这一点。 github.com/abramenal/cypress-shadow-dom【参考方案3】:

感谢所有解决问题的尝试,但对于“window.location.hash 更改时触发相关侦听器”这样简单的问题,它们都是棘手的解决方法。

问题的根源在于赛普拉斯中的错误window.location.hash 上的错误存在于 4.5.0 中,但它已在 4.5.04.12.1 之间的某个地方得到解决。

4.12.1 中问题已解决。

【讨论】:

以上是关于访问新网址赛普拉斯的主要内容,如果未能解决你的问题,请参考以下文章

赛普拉斯如何处理没有“目标”和“href”属性的新标签?

赛普拉斯获取 href 属性

赛普拉斯自定义命令无法识别

赛普拉斯与SystemJS

赛普拉斯可以运行在赛普拉斯文件夹之外导入的测试文件吗?

如何使用赛普拉斯访问React组件的本地状态?