简体   繁体   English

在 Cypress 中设置本地存储

[英]Set local storage in Cypress

For one of our applications, I need to set local storage in order to bypass the login page process.对于我们的一个应用程序,我需要设置本地存储以绕过登录页面过程。

I have the following function that will return the accessToken that I need to set.我有以下函数将返回我需要设置的 accessToken。 This function works when running in node.此功能在节点中运行时有效。

async function getAccessToken(email, pwd) {
    const form = {email: email, password: pwd};
    let config = {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }
    };
    const accessToken = await axios.post(`${process.env.API_URL}/loginWithToken`, qs.stringify(form), config);
    console.log(accessToken.data.accessToken);
    return accessToken.data.accessToken
}

I'm trying to create a cypress command that will set local storage, then visit the application.我正在尝试创建一个 cypress 命令来设置本地存储,然后访问该应用程序。 When running, I get an error that I returned a promise from a command while also invoking one or more cy commands in that promise.运行时,我收到一个错误,我从命令返回了一个承诺,同时还调用了该承诺中的一个或多个 cy 命令。

Cypress.Commands.add("logInAs", async(Useremail, Userpwd, TMURL) => {
    var accessToken = cy.task('getAccessToken', {email: Useremail, pwd: Userpwd
    }).then(Visit =>{
        window.localStorage.setItem("accessToken", accessToken);
        window.localStorage.setItem("refreshToken", accessToken);
        cy.visit(`${process.env.TM_API_URL}/`+TMURL+``);
    });
});

I've also tried the following cypress command我还尝试了以下 cypress 命令

require('dotenv').config();

Cypress.Commands.add('logInAs3', (Useremail, Userpwd, TMURL) => {
        cy.request({
            method: 'POST',
            url: `${process.env.API_URL}/loginWithToken`,
            body: {
                user: {
                    email: Useremail,
                    password: Userpwd,
                }
            }
        })
            .then((resp) => {
                window.localStorage.setItem('accessToken', resp.body.data.data.accessToken);
                window.localStorage.setItem('refreshToken', resp.body.data.data.accessToken);
                cy.visit(`${process.env.TM_API_URL}/`+TMURL+``, {failOnStatusCode: false})
            })
    });

But I get the following error.但我收到以下错误。 The URL I need to post to in order to get the access token, is a different domain than the base url.我需要发布以获取访问令牌的 URL 与基本 URL 是不同的域。 So using the base in the post will not work for me.所以在帖子中使用基础对我不起作用。

cy.request() must be provided a fully qualified url - one that begins with 'http'. cy.request() 必须提供一个完全限定的 url - 一个以“http”开头的。 By default cy.request() will use either the current window's origin or the 'baseUrl' in cypress.json.默认情况下,cy.request() 将使用当前窗口的原点或 cypress.json 中的“baseUrl”。 Neither of those values were present.这些值都不存在。

Try this one:试试这个:

In cypress.jsoncypress.json

{
  "env": {
    "EXTERNAL_API": "https://jsonplaceholder.typicode.com/todos/1"
  }
}

In support/commands.jssupport/commands.js

Cypress.Commands.add('logInAs3', (Useremail, Userpwd, TMURL) => {
  cy.request({
    method: 'POST',
    url: `${Cypress.env('EXTERNAL_API')}/loginWithToken`,
    body: {
      user: {
        email: Useremail,
        password: Userpwd,
      }
    }
  })
    .its('body')
    .then((body) => {
      window.localStorage.setItem('accessToken', body.data.data.accessToken);
      window.localStorage.setItem('refreshToken', body.data.data.accessToken);
    })
});

Inside your test在你的测试中

beforeEach(() => {
  cy.logInAs3()
})

it('check localStorage token', () => {
  cy.visit()
  expect(localStorage.getItem('accessToken')).not.null
  expect(localStorage.getItem('refreshToken')).not.null
})

Based on the @Danny answer, you can use the cypress-localstorage-commands package to persist localStorage and reuse same user session for all tests in a block:根据@Danny 的回答,您可以使用cypress-localstorage-commands包来持久化 localStorage 并为块中的所有测试重用相同的用户会话:

In cypress.jsoncypress.json

{
  "env": {
    "EXTERNAL_API": "https://jsonplaceholder.typicode.com/"
  }
}

In support/commands.jssupport/commands.js

import "cypress-localstorage-commands";

Cypress.Commands.add('logInAs', (UserEmail, UserPwd) => {
  cy.request({
    method: 'POST',
    url: `${Cypress.env('EXTERNAL_API')}/loginWithToken`,
    body: {
      user: {
        email: UserEmail,
        password: UserPwd,
      }
    }
  })
    .its('body')
    .then((body) => {
      cy.setLocalStorage("accessToken", body.data.accessToken);
      cy.setLocalStorage("refreshToken", body.data.refreshToken);
    });
});

Inside your tests:在您的测试中:

describe("when user FOO is logged in", ()=> {
  before(() => {
    cy.logInAs("foo@foo.com", "fooPassword");
    cy.saveLocalStorage();
  });

  beforeEach(() => {
    cy.restoreLocalStorage();
    cy.visit("");
  });

  it('should exist accessToken in localStorage', () => {
    cy.getLocalStorage("accessToken").should("exist");
  });

  it('should exist refreshToken in localStorage', () => {
    cy.getLocalStorage("refreshToken").should("exist");
  });
});

Hitting login API every time a Test Run's cost resources at both(Server and Client)每次测试运行(服务器和客户端)的成本资源时都点击登录 API

here is optimized way:这是优化的方式:

Just store login/auth API Success response in Cypress Env and reuse it in command function只需在 Cypress Env 中存储 login/auth API Success 响应并在命令函数中重用它

In cypress.jsoncypress.json

{
  "myenv": {
    "authResponse": {
      "apiToken": "jwt_token_received_from_server",
      "refreshToken": "refresh_token_received_from_server"
    }
  }
}

In support/commands.jssupport/commands.js

Cypress.Commands.add('setSession', () => {
  const accessToken = `${Cypress.env('myenv')['authResponse']['apiToken']}`
  const refreshToken = `${Cypress.env('myenv')['authResponse']['refreshToken']}`
  window.localStorage.setItem('accessToken', accessToken);
  window.localStorage.setItem('refreshToken', responseToken);
  })
});

Inside your test在你的测试中

beforeEach(() => {
  cy.setSession();
})

it('Test Ui Components for Authorized User', () => {

})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM