mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
- Add auto-complete quest command
- Change spec name - Add spec complete all quests - Add Icon (totem version) - Add some id for tests - Add answer.sh for all quests
This commit is contained in:
1 parent
dc1d3f6ce5
commit
7a3b6b1cfb
17 files changed
+241
-37
No files matched your search
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/icon_totem.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Linux Odyssey</title>
|
<title>Linux Odyssey</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="732"
|
||||||
|
height="732"
|
||||||
|
viewBox="0 0 732 732"
|
||||||
|
fill="none"
|
||||||
|
version="1.1"
|
||||||
|
id="svg10"
|
||||||
|
sodipodi:docname="icon_totem.svg"
|
||||||
|
inkscape:export-filename="/home/zeko/Documents/Linux專題/icon_totem_small.png"
|
||||||
|
inkscape:export-xdpi="200"
|
||||||
|
inkscape:export-ydpi="200"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview12"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
width="732px"
|
||||||
|
inkscape:zoom="0.56010929"
|
||||||
|
inkscape:cx="-207.99512"
|
||||||
|
inkscape:cy="549.89268"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1008"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg10" />
|
||||||
|
<path
|
||||||
|
d="M 47,0 H 685 V 732 H 47 Z"
|
||||||
|
fill="url(#pattern0)"
|
||||||
|
id="path2"
|
||||||
|
style="fill:url(#pattern1809)" />
|
||||||
|
<defs
|
||||||
|
id="defs8">
|
||||||
|
<pattern
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#pattern0"
|
||||||
|
id="pattern1809"
|
||||||
|
patternTransform="translate(47)" />
|
||||||
|
<pattern
|
||||||
|
id="pattern0"
|
||||||
|
patternContentUnits="objectBoundingBox"
|
||||||
|
width="1"
|
||||||
|
height="1">
|
||||||
|
<use
|
||||||
|
xlink:href="#image0_375_14"
|
||||||
|
transform="matrix(0.00126582 0 0 0.00110327 0 -0.000333748)"
|
||||||
|
id="use4" />
|
||||||
|
</pattern>
|
||||||
|
<image
|
||||||
|
id="image0_375_14"
|
||||||
|
width="790"
|
||||||
|
height="907"
|
||||||
|
xlink:href="data:image/png;base64,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 truncated
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 632 KiB |
@@ -89,7 +89,9 @@ const handleChange = () => {
|
|||||||
<div
|
<div
|
||||||
class="bg-bg border-8 border-bg-primary flex flex-1 flex-col items-center justify-center rounded-3xl p-10"
|
class="bg-bg border-8 border-bg-primary flex flex-1 flex-col items-center justify-center rounded-3xl p-10"
|
||||||
>
|
>
|
||||||
<h1 class="text-text-primary text-3xl font-black mb-2">{{ title }}</h1>
|
<h1 class="text-text-primary text-3xl font-black mb-2" id="title">
|
||||||
|
{{ title }}
|
||||||
|
</h1>
|
||||||
<div class="text-error inline-flex justify-center items-center md:hidden">
|
<div class="text-error inline-flex justify-center items-center md:hidden">
|
||||||
<font-awesome-icon
|
<font-awesome-icon
|
||||||
:icon="['fas', 'circle-exclamation']"
|
:icon="['fas', 'circle-exclamation']"
|
||||||
@@ -163,6 +165,7 @@ const handleChange = () => {
|
|||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
class="text-sm font-normal text-text-secondary"
|
class="text-sm font-normal text-text-secondary"
|
||||||
|
id="NameRules"
|
||||||
v-if="type === 'username' || type === 'register'"
|
v-if="type === 'username' || type === 'register'"
|
||||||
>
|
>
|
||||||
<p>可用小寫字母、數字、"_"和"-"</p>
|
<p>可用小寫字母、數字、"_"和"-"</p>
|
||||||
|
|||||||
@@ -79,14 +79,14 @@ onMounted(async () => {
|
|||||||
/>
|
/>
|
||||||
</button> -->
|
</button> -->
|
||||||
<button
|
<button
|
||||||
id="HeaderText"
|
id="GameTitle"
|
||||||
class="text-text-primary inline-block font-bold whitespace-nowrap"
|
class="text-text-primary inline-block font-bold whitespace-nowrap"
|
||||||
style="font-size: 2vh"
|
style="font-size: 2vh"
|
||||||
>
|
>
|
||||||
Linux Odyssey
|
Linux Odyssey
|
||||||
</button>
|
</button>
|
||||||
<p
|
<p
|
||||||
id="HeaderText"
|
id="QuestTitle"
|
||||||
class="text-text inline-block font-bold whitespace-nowrap"
|
class="text-text inline-block font-bold whitespace-nowrap"
|
||||||
style="font-size: 2vh"
|
style="font-size: 2vh"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
echo start
|
||||||
|
echo example
|
||||||
|
echo How are you
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
echo start
|
||||||
|
cat hello.txt
|
||||||
|
cat world.txt
|
||||||
|
echo continue
|
||||||
|
cp hello.txt hello2.txt
|
||||||
|
cat hello2.txt
|
||||||
|
cp world.txt world2.txt
|
||||||
|
cat world2.txt
|
||||||
|
cp -r notes notes2
|
||||||
|
ls notes2
|
||||||
|
cp hello.txt world.txt
|
||||||
|
cat world.txt
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
echo start
|
||||||
|
touch hello.txt
|
||||||
|
ls
|
||||||
|
cat hello.txt
|
||||||
|
touch world.txt
|
||||||
|
ls
|
||||||
|
mkdir notes
|
||||||
|
ls
|
||||||
|
cd notes
|
||||||
|
touch note.txt
|
||||||
|
ls
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
echo start
|
||||||
|
ls
|
||||||
|
cd folder1
|
||||||
|
ls
|
||||||
|
cd ..
|
||||||
|
cd folder2
|
||||||
|
ls
|
||||||
|
cd ..
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
echo start
|
||||||
|
echo hello
|
||||||
|
echo finish
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
echo help{enter}
|
echo help
|
||||||
ls {enter}
|
ls
|
||||||
cat forgotten_scroll.txt{enter}
|
cat forgotten_scroll.txt
|
||||||
echo Hello World!{enter}
|
echo Hello World
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
echo start
|
||||||
|
echo continue
|
||||||
|
mv hello.txt notes
|
||||||
|
ls
|
||||||
|
ls notes
|
||||||
|
echo continue
|
||||||
|
mv world.txt wow.txt
|
||||||
|
ls
|
||||||
|
mv notes docs
|
||||||
|
ls
|
||||||
|
echo hint
|
||||||
|
mv docs/hello.txt hi.txt
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
echo start
|
||||||
|
ls
|
||||||
|
cd folder1
|
||||||
|
cd ../folder2
|
||||||
|
ls ../folder1
|
||||||
|
pwd
|
||||||
|
ls ~
|
||||||
|
cd ~
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
echo start
|
||||||
|
ls
|
||||||
|
cat file1.txt
|
||||||
|
ls folder
|
||||||
|
cat folder/file1.txt
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
echo start
|
||||||
|
rm hello.txt
|
||||||
|
ls
|
||||||
|
rm world.txt wow.txt
|
||||||
|
ls
|
||||||
|
rmdir empty
|
||||||
|
ls
|
||||||
|
rmdir notes
|
||||||
|
rm notes/note.txt
|
||||||
|
rmdir notes
|
||||||
|
ls trash
|
||||||
|
rm -r trash
|
||||||
|
ls
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
export default function checkLoginUI() {
|
export default function checkLoginUI() {
|
||||||
cy.get('h1.text-text-primary')
|
cy.get('#title').should('contain', 'Linux Odyssey').and('be.visible')
|
||||||
.should('contain', 'Linux Odyssey')
|
|
||||||
.and('be.visible')
|
|
||||||
cy.CheckPlaceholder('#password', '密碼', 'Password')
|
cy.CheckPlaceholder('#password', '密碼', 'Password')
|
||||||
}
|
}
|
||||||
describe('example helloworld app', () => {
|
describe('example helloworld app', () => {
|
||||||
@@ -13,7 +11,7 @@ describe('example helloworld app', () => {
|
|||||||
it('Check Login Page Elements-Register', () => {
|
it('Check Login Page Elements-Register', () => {
|
||||||
checkLoginUI()
|
checkLoginUI()
|
||||||
cy.CheckPlaceholder('#username', '帳號名稱', 'Username')
|
cy.CheckPlaceholder('#username', '帳號名稱', 'Username')
|
||||||
cy.get('label.text-text-secondary').should('be.visible') // check the rules is displayed
|
cy.get('#NameRules').should('be.visible') // check the rules is displayed
|
||||||
cy.CheckPlaceholder('#email', '電子郵件', 'Email')
|
cy.CheckPlaceholder('#email', '電子郵件', 'Email')
|
||||||
cy.CheckTextElement(
|
cy.CheckTextElement(
|
||||||
'#CheckRegistered',
|
'#CheckRegistered',
|
||||||
@@ -79,15 +77,23 @@ describe('example helloworld app', () => {
|
|||||||
cy.PrepareForGame()
|
cy.PrepareForGame()
|
||||||
})
|
})
|
||||||
it('Check Header', () => {
|
it('Check Header', () => {
|
||||||
cy.get('#HeaderText').should('contain', 'Linux Odyssey').and('be.visible')
|
cy.get('#GameTitle').should('contain', 'Linux Odyssey').and('be.visible')
|
||||||
|
cy.get('#QuestTitle').should('contain', title).and('be.visible')
|
||||||
|
cy.get('#UsernameText')
|
||||||
|
.should('contain', Cypress.env('defaultAccount'))
|
||||||
|
.and('be.visible')
|
||||||
cy.findByRole('link', { name: 'Bug Report' }).should('be.visible')
|
cy.findByRole('link', { name: 'Bug Report' }).should('be.visible')
|
||||||
cy.findByRole('button', { name: 'Sign Out' }).should('be.visible')
|
cy.findByRole('button', { name: 'Sign Out' }).should('be.visible')
|
||||||
|
cy.findByRole('button', { name: 'Map' }).should('be.visible')
|
||||||
|
cy.findByRole('button', { name: 'LeaderBoard' }).should('be.visible')
|
||||||
|
cy.findByRole('link', { name: 'Survey' }).should('be.visible')
|
||||||
})
|
})
|
||||||
it('Check QuestInfo', () => {
|
it('Check QuestInfo', () => {
|
||||||
cy.get('#topic').should('contain', title)
|
cy.get('#topic').should('contain', title)
|
||||||
cy.get('#quest').find('p.text-text').should('have.length', 4)
|
cy.get('#topic').should('be.visible')
|
||||||
|
cy.get('#tasks').should('be.visible')
|
||||||
|
cy.get('#quest').find('p.text-text').should('have.length', 2)
|
||||||
cy.CheckTextElement('#tasks', '任務', 'Tasks:')
|
cy.CheckTextElement('#tasks', '任務', 'Tasks:')
|
||||||
cy.getQuestInfo('輸入 `echo help` 來朗誦咒語').should('be.visible')
|
|
||||||
})
|
})
|
||||||
it('Check Terminal', () => {
|
it('Check Terminal', () => {
|
||||||
cy.get('#terminal', { timeout: 20000 }).within(($terminal) => {
|
cy.get('#terminal', { timeout: 20000 }).within(($terminal) => {
|
||||||
@@ -114,6 +120,7 @@ describe('example helloworld app', () => {
|
|||||||
cy.CheckTextElement('#solution', '解答', 'Solution')
|
cy.CheckTextElement('#solution', '解答', 'Solution')
|
||||||
cy.CheckTextElement('#reset', '重來', 'Reset')
|
cy.CheckTextElement('#reset', '重來', 'Reset')
|
||||||
cy.CheckTextElement('#continue', '繼續', 'Continue')
|
cy.CheckTextElement('#continue', '繼續', 'Continue')
|
||||||
|
cy.CheckTextElement('#survey', '問卷', 'Survey')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('Game Play', () => {
|
describe('Game Play', () => {
|
||||||
@@ -126,42 +133,31 @@ describe('example helloworld app', () => {
|
|||||||
.should('contain', '12345')
|
.should('contain', '12345')
|
||||||
.and('contain', 'zsh: command not found: 12345', { timeout: 50000 })
|
.and('contain', 'zsh: command not found: 12345', { timeout: 50000 })
|
||||||
})
|
})
|
||||||
it('Complete the Game(relating UI)', () => {
|
it('Complete the First Quest(relating UI)', () => {
|
||||||
// Stage1
|
cy.checkTaskInit()
|
||||||
cy.log('Stage1')
|
cy.InitTerminal()
|
||||||
cy.typeInCommand('echo start{enter}')
|
cy.typeInCommand('echo start{enter}')
|
||||||
cy.checkPending()
|
cy.checkPending()
|
||||||
cy.waitUntilActive()
|
cy.waitUntilActive()
|
||||||
cy.get('#Lbutton').should('be.visible').and('be.disabled')
|
cy.get('#Lbutton').should('be.visible').and('be.disabled')
|
||||||
cy.get('#Rbutton').should('be.visible').and('be.disabled')
|
cy.get('#Rbutton').should('be.visible').and('be.disabled')
|
||||||
cy.checkHint(1, 1)
|
cy.checkHint(1, 1)
|
||||||
cy.getQuestInfo('✓ 輸入 `echo start` 來開始教程').should('be.visible')
|
cy.getQuestInfo('✓ 輸入 echo start 來開始教程').should('be.visible')
|
||||||
cy.getQuestInfo('➤ 在終端機輸入 `echo hello`').should('be.visible')
|
cy.getQuestInfo('➤ 在終端機輸入 echo hello').should('be.visible')
|
||||||
// Stage2
|
|
||||||
cy.log('Stage2')
|
|
||||||
cy.typeInCommand('echo hello{enter}')
|
cy.typeInCommand('echo hello{enter}')
|
||||||
cy.checkPending()
|
cy.checkPending()
|
||||||
cy.waitUntilActive()
|
cy.waitUntilActive()
|
||||||
// cy.get('#tree')
|
|
||||||
// .get('a')
|
|
||||||
// .should('contain', 'forgotten_scroll.txt')
|
|
||||||
// .and('be.visible')
|
|
||||||
cy.get('#Lbutton').should('be.visible').and('be.enabled')
|
cy.get('#Lbutton').should('be.visible').and('be.enabled')
|
||||||
cy.get('#Rbutton').should('be.visible').and('be.disabled')
|
cy.get('#Rbutton').should('be.visible').and('be.disabled')
|
||||||
cy.checkHint(2, 2)
|
cy.checkHint(2, 2)
|
||||||
cy.get('#Lbutton').click()
|
cy.get('#Lbutton').click()
|
||||||
cy.get('#Rbutton').should('be.enabled')
|
cy.get('#Rbutton').should('be.enabled')
|
||||||
cy.getQuestInfo('✓ 在終端機輸入 `echo hello`').should('be.visible')
|
cy.getQuestInfo('✓ 在終端機輸入 echo hello').should('be.visible')
|
||||||
cy.getQuestInfo('➤ 結束關卡').should('be.visible')
|
cy.getQuestInfo('➤ 結束關卡').should('be.visible')
|
||||||
// Stage3
|
|
||||||
cy.log('Stage3')
|
|
||||||
cy.typeInCommand('echo finish{enter}')
|
cy.typeInCommand('echo finish{enter}')
|
||||||
cy.checkPending()
|
|
||||||
cy.waitUntilActive()
|
|
||||||
cy.getQuestInfo('✓ 結束關卡').should('be.visible')
|
|
||||||
cy.CheckTextElement('#QuestCompleted', '關卡完成!', 'Quest Completed!')
|
cy.CheckTextElement('#QuestCompleted', '關卡完成!', 'Quest Completed!')
|
||||||
cy.get('div[class="modal"]').find('p').should('be.visible')
|
cy.get('div[class="modal"]').find('p').should('be.visible')
|
||||||
cy.findByRole('link', { name: '填寫問卷' }).should('be.visible')
|
cy.get('#BacktoMap').should('be.visible').and('contain', '回到地圖')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/// <reference types="cypress" />
|
||||||
|
describe('Complete quests with only commands', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.PrepareForGame()
|
||||||
|
})
|
||||||
|
it('Complete quest : get-started', () => {
|
||||||
|
cy.CompleteStageWithCommands('get-started')
|
||||||
|
})
|
||||||
|
it('Complete quest : cast', () => {
|
||||||
|
cy.CompleteStageWithCommands('cast')
|
||||||
|
})
|
||||||
|
it('Complete quest : explore', () => {
|
||||||
|
cy.CompleteStageWithCommands('explore')
|
||||||
|
})
|
||||||
|
it('Complete quest : path', () => {
|
||||||
|
cy.CompleteStageWithCommands('path')
|
||||||
|
})
|
||||||
|
it('Complete quest : read', () => {
|
||||||
|
cy.CompleteStageWithCommands('read')
|
||||||
|
})
|
||||||
|
it('Complete quest : create', () => {
|
||||||
|
cy.CompleteStageWithCommands('create')
|
||||||
|
})
|
||||||
|
it('Complete quest : copy', () => {
|
||||||
|
cy.CompleteStageWithCommands('copy')
|
||||||
|
})
|
||||||
|
it('Complete quest : move', () => {
|
||||||
|
cy.CompleteStageWithCommands('move')
|
||||||
|
})
|
||||||
|
it('Complete quest : remove', () => {
|
||||||
|
cy.CompleteStageWithCommands('remove')
|
||||||
|
})
|
||||||
|
it('Complete quest : helloworld', () => {
|
||||||
|
cy.CompleteStageWithCommands('helloworld')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -25,15 +25,20 @@ Cypress.Commands.add('PrepareForGame', () => {
|
|||||||
cy.get('.xterm-screen', { timeout: 10000 })
|
cy.get('.xterm-screen', { timeout: 10000 })
|
||||||
.as('Terminaltextbox')
|
.as('Terminaltextbox')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
|
cy.checkTaskInit()
|
||||||
cy.CheckTextElement('#reset', '重來', 'Reset').click()
|
cy.CheckTextElement('#reset', '重來', 'Reset').click()
|
||||||
cy.typeInCommand('clear{enter}')
|
cy.checkTaskInit()
|
||||||
|
cy.InitTerminal()
|
||||||
|
})
|
||||||
|
Cypress.Commands.add('InitTerminal', () => {
|
||||||
cy.get('@Terminaltextbox', { timeout: 150000 }).should(
|
cy.get('@Terminaltextbox', { timeout: 150000 }).should(
|
||||||
'contain',
|
'contain',
|
||||||
'commander:~ $'
|
'commander:~ $'
|
||||||
)
|
)
|
||||||
|
cy.log('Check terminal init done')
|
||||||
})
|
})
|
||||||
Cypress.Commands.add('typeInCommand', (command) => {
|
Cypress.Commands.add('typeInCommand', (command) => {
|
||||||
cy.get('.xterm-screen', { timeout: 150000 }).type(command)
|
cy.get('.xterm-screen', { timeout: 150000 }).type(command, { delay: 10 })
|
||||||
})
|
})
|
||||||
Cypress.Commands.add('getQuestInfo', (id) => {
|
Cypress.Commands.add('getQuestInfo', (id) => {
|
||||||
return cy
|
return cy
|
||||||
@@ -48,6 +53,9 @@ Cypress.Commands.add('checkHint', (index, total) => {
|
|||||||
.contains(`${index}/${total}`)
|
.contains(`${index}/${total}`)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
})
|
})
|
||||||
|
Cypress.Commands.add('checkTaskInit', () => {
|
||||||
|
cy.get('#tasks').next().children().should('be.visible')
|
||||||
|
})
|
||||||
Cypress.Commands.add('waitUntilActive', () => {
|
Cypress.Commands.add('waitUntilActive', () => {
|
||||||
cy.get('input[id="currentStatus"]', { timeout: 1000000 })
|
cy.get('input[id="currentStatus"]', { timeout: 1000000 })
|
||||||
.invoke('val')
|
.invoke('val')
|
||||||
@@ -66,8 +74,25 @@ Cypress.Commands.add('checkPending', () => {
|
|||||||
'pending'
|
'pending'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
Cypress.Commands.add('Complete the Stage (only command)', () => {
|
Cypress.Commands.add('CompleteStageWithCommands', (stagename) => {
|
||||||
cy.log('')
|
cy.visit(`/game/${stagename}`)
|
||||||
|
cy.url().should('include', `/game/${stagename}`)
|
||||||
|
cy.log(`Completing stage :${stagename}`)
|
||||||
|
cy.checkTaskInit()
|
||||||
|
cy.CheckTextElement('#reset', '重來', 'Reset').click()
|
||||||
|
cy.checkTaskInit()
|
||||||
|
cy.InitTerminal()
|
||||||
|
cy.readFile(`../quests/${stagename}/answer.sh`, 'utf-8').as('answers')
|
||||||
|
cy.get('@answers').then((answers) => {
|
||||||
|
const answerarr = answers.split('\n')
|
||||||
|
for (const element of answerarr) {
|
||||||
|
cy.typeInCommand(`${element}{enter}`)
|
||||||
|
if (answerarr.indexOf(element) + 1 !== answerarr.length) {
|
||||||
|
cy.checkPending()
|
||||||
|
cy.waitUntilActive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
Cypress.Commands.add('CheckTextElement', (id, chText, enText) => {
|
Cypress.Commands.add('CheckTextElement', (id, chText, enText) => {
|
||||||
cy.get(id).within(($element) => {
|
cy.get(id).within(($element) => {
|
||||||
@@ -89,3 +114,6 @@ Cypress.Commands.add('CheckPlaceholder', (id, chText, enText) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Cypress.Commands.add('CheckTreeElement', (element) => {
|
||||||
|
cy.get('#tree').get('a').should('contain', `${element}`).and('be.visible')
|
||||||
|
})
|
||||||
Reference in new issue
Block a user