J. *_*ers 5 javascript environment-variables add-custom-command cypress dotenv
我正在构建 Next.js 应用程序并使用 Cypress 编写我的测试。我在本地使用.env.local文件配置环境变量。在 CI 管道中,它们通常被定义。
我正在尝试在 Cypress 中编写一个自定义命令来加密cypress/support/command.ts.
import { encryptSession } from 'utils/sessions';
Cypress.Commands.add(
'loginWithCookie',
({
issuer = 'some-issuer',
publicAddress = 'some-address',
email = 'some-mail',
} = {}) => {
const session = { issuer, publicAddress, email };
return encryptSession(session).then(token => {
cy.setCookie('my-session-token', token);
return session;
});
},
);
Run Code Online (Sandbox Code Playgroud)
当此命令运行时,它会失败,因为encryptSession使用了TOKEN_SECRET赛普拉斯未加载的环境变量。
import Iron from '@hapi/iron';
const TOKEN_SECRET = process.env.TOKEN_SECRET || '';
export function encryptSession(session: Record<string, unknown>) {
return Iron.seal(session, TOKEN_SECRET, Iron.defaults);
}
Run Code Online (Sandbox Code Playgroud)
如何让赛普拉斯从该文件加载环境变量,如果它存在(= 仅在本地,因为变量是在 CI 中定义的 - 它应该正常检测管道中的其他变量,因此相当于检测具有已设置export MY_VAR=foo)?
小智 2
有Cypress.envprocess.env ,但您想要设置看起来与 Cypress 版本不完全协调的令牌。
我知道任何带有CYPRESS_process.env前缀的密钥都会以结尾,但您想朝相反的方向走。Cypress.env()
我将使用一个任务来让您访问文件系统,并且process.env,
/cypress/plugins/index.js
module.exports = (on, config) => {
on('task', {
checkEnvToken :() => {
const contents = fs.readFileSync('.env.local', 'utf8'); // get the whole file
const envVars = contents.split('\n').filter(v => v); // split by lines
// and remove blanks
envVars.forEach(v => {
const [key, value] = v.trim().split('='); // split the kv pair
if (!process.env[key]) { // check if already set in CI
process.env[key] = value;
}
})
return null; // required for a task
},
})
Run Code Online (Sandbox Code Playgroud)
在任何测试之前调用该任务,无论是在/cypress/support/index.js中,还是在before(), 或 在自定义命令中。
在自定义命令中
Cypress.Commands.add(
'loginWithCookie',
({
issuer = 'some-issuer',
publicAddress = 'some-address',
email = 'some-mail',
} = {}) => {
cy.task('checkEnvToken').then(() => { // wait for task to finish
const session = { issuer, publicAddress, email };
return encryptSession(session).then(token => {
cy.setCookie('my-session-token', token);
return session;
});
})
});
Run Code Online (Sandbox Code Playgroud)
深入研究 的代码@hapi/iron,有一个crypto对 Node 库的调用,因此您可能需要将整个encryptSession(session)调用移至一个任务中才能使其工作。
import { encryptSession } from 'utils/sessions';
module.exports = (on, config) => {
on('task', {
encryptSession: (session) => {
const contents = fs.readFileSync('.env.local', 'utf8'); // get the whole file
const envVars = contents.split('\n').filter(v => v); // split by lines
// and remove blanks
envVars.forEach(v => {
const [key, value] = v.trim().split('='); // split the kv pair
if (!process.env[key]) { // check if already set in CI
process.env[key] = value;
}
})
return encryptSession(session); // return the token
},
})
Run Code Online (Sandbox Code Playgroud)
致电
cy.task('encryptSession', { issuer, publicAddress, email })
.then(token => {
cy.setCookie('my-session-token', token);
});
Run Code Online (Sandbox Code Playgroud)
在哪里运行上面的 cy.task
我想您只需要在每个测试会话中运行一次(以便为多个规范文件设置),在这种情况下,调用它的位置位于before()/cypress/support/index.js内。
把它放在那里的缺点是它有点隐藏,所以我个人会把它放在before()每个规范文件顶部的 a 中。
时间开销很小,fs.readFileSync但与等待页面加载等相比,这是最小的。
| 归档时间: |
|
| 查看次数: |
1229 次 |
| 最近记录: |