Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions REGRESSION/resources/scenarios/ui/web/var/self/otp/scenario.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<scenario xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.knubisoft.com/testlum/testing/model/scenario"
xsi:schemaLocation="http://www.knubisoft.com/testlum/testing/model/scenario scenario.xsd">

<overview>
<name>Var - OTP</name>
<description>
This scenario verifies OTP value generation and input usage.

Test flow:
1. Navigate to OTP test page.
2. Generate OTP value.
3. Input generated value.
4. Verify that input contains generated value.

This scenario validates:
- OTP generation
- variable injection into input
- correct value application
</description>
</overview>

<settings>
<tags>web</tags>
</settings>

<web comment="Start WEB script">

<navigate comment="Navigate to OTP Test page"
command="to"
path="/otp-test"/>

<wait comment="Wait for page load"
time="2"/>

<var comment="Generate OTP value"
name="otpValue">
<otp secretKey="JBSWY3DPEHPK3PXP"/>
</var>

<input comment="Input generated OTP"
locator="xpath=//input[@placeholder='6-digit code']"
value="{{otpValue}}"
highlight="true"/>

<assert comment="Verify input contains generated value">
<attribute comment="Check input value"
name="value"
locator="xpath=//input[@placeholder='6-digit code']">
<content>{{otpValue}}</content>
</attribute>
</assert>

<click comment="Click Verify button"
locator="xpath=//button[@type='submit']"/>

<wait comment="Wait for validation" time="1"/>

<assert comment="Verify success message is displayed">
<attribute comment="Check success message"
name="text"
locator="xpath=//span[@id='resultMessage']">
<content>Success!</content>
</attribute>
</assert>

</web>

</scenario>
43 changes: 43 additions & 0 deletions REGRESSION/resources/scenarios/variable/general/otp/scenario.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<scenario xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.knubisoft.com/testlum/testing/model/scenario"
xsi:schemaLocation="http://www.knubisoft.com/testlum/testing/model/scenario scenario.xsd">

<overview>
<description>Test otp variable creation and usage</description>
<name>Variable(otp) Test</name>
<developer>Anatoliy</developer>
</overview>

<settings>
<tags>var</tags>
</settings>

<var comment="Create OTP variable" name="myOtp">
<otp secretKey="JBSWY3DPEHPK3PXP"/>
</var>

<condition comment="Check if OTP is 6 digits" name="otpCondition" spel="'{{myOtp}}'.length() == 6 and '{{myOtp}}'.matches('^[0-9]+$')"/>

<assert comment="Check if the condition for OTP is true">
<equal comment="Check if the condition for OTP is true">
<content>{{otpCondition}}</content>
<content>true</content>
</equal>
</assert>

<wait comment="Wait 31 seconds for the TOTP window to change" time="31"/>

<var comment="Create new OTP variable after time passed" name="myOtpNew">
<otp secretKey="JBSWY3DPEHPK3PXP"/>
</var>

<condition comment="Check if new OTP is different from the old one" name="otpChangedCondition" spel="'{{myOtp}}' != '{{myOtpNew}}'"/>

<assert comment="Check if the condition for OTP change is true">
<equal comment="Check if the condition for OTP change is true">
<content>{{otpChangedCondition}}</content>
<content>true</content>
</equal>
</assert>

</scenario>
6 changes: 6 additions & 0 deletions REGRESSION/schema/shared-restrictions.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
</x:restriction>
</x:simpleType>

<x:simpleType name="base32String">
<x:restriction base="x:string">
<x:pattern value="[a-zA-Z2-7=]+"/>
</x:restriction>
</x:simpleType>

<x:simpleType name="nonEmptyString">
<x:restriction base="x:string">
<x:minLength value="1"/>
Expand Down
5 changes: 5 additions & 0 deletions REGRESSION/schema/var.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,14 @@
<x:element name="sql" type="tns:fromSQL"/>
<x:element name="generate" type="tns:fromRandomGenerate"/>
<x:element name="date" type="tns:fromDate"/>
<x:element name="otp" type="tns:fromOtp"/>
</x:choice>
</x:group>

<x:complexType name="fromOtp">
<x:attribute name="secretKey" type="tns:base32String" use="required"/>
</x:complexType>

<x:complexType name="fromFile">
<x:attribute name="fileName" type="tns:nonEmptyString" use="required"/>
</x:complexType>
Expand Down
38 changes: 38 additions & 0 deletions TEST-UI/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion TEST-UI/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@tailwindcss/aspect-ratio": "^0.4.0",
"@tailwindcss/forms": "^0.4.0",
"@tailwindcss/typography": "^0.5.2",

"otpauth": "^9.5.1",
"vue": "^3.2.6",
"vue-backtotop": "^1.6.1",
"vue-router": "^4.2.2",
Expand Down
7 changes: 7 additions & 0 deletions TEST-UI/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Modal from './views/Modal.vue';
import Card from './views/Card.vue';
import Blank from './views/Blank.vue';
import ScrollTest from "./views/ScrollTest.vue";
import OtpTestPage from "./views/OtpTestPage.vue";

const routes: RouteRecordRaw[] = [
{
Expand Down Expand Up @@ -56,6 +57,12 @@ const routes: RouteRecordRaw[] = [
path: '/scroll-test',
name: 'ScrollTest',
component: ScrollTest,
},
{
path: '/otp-test',
name: 'OtpTestPage',
component: OtpTestPage,
meta: { layout: 'empty' },
}
];

Expand Down
65 changes: 65 additions & 0 deletions TEST-UI/src/views/OtpTestPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<div class="flex items-center justify-center h-screen px-6 bg-gray-200">
<div class="w-full max-w-sm p-6 bg-white rounded-md shadow-md">
<h2 class="text-2xl font-semibold text-center text-gray-700">2FA Test Page</h2>
<p class="mt-2 text-sm text-center text-gray-600">Enter your Google Authenticator code</p>

<form class="mt-4" @submit.prevent="verifyOtp">
<label class="block mt-3">
<span class="text-sm text-gray-700">OTP Code</span>
<input
type="text"
class="block w-full mt-1 border-gray-200 rounded-md focus:border-indigo-600 focus:ring focus:ring-opacity-40 focus:ring-indigo-500"
v-model="otpCode"
placeholder="6-digit code"
/>
</label>

<div class="mt-6">
<button
type="submit"
class="w-full px-4 py-2 text-sm text-center text-white bg-indigo-600 rounded-md focus:outline-none hover:bg-indigo-500"
>
Verify
</button>
</div>
</form>

<div v-if="message" :class="['mt-4 text-center font-bold', isSuccess ? 'text-green-600' : 'text-red-600']">
<span id="resultMessage">{{ message }}</span>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import * as OTPAuth from "otpauth";

const otpCode = ref("");
const message = ref("");
const isSuccess = ref(false);

const SECRET = "JBSWY3DPEHPK3PXP";

function verifyOtp() {
let totp = new OTPAuth.TOTP({
issuer: "Demo",
label: "user@demo.com",
algorithm: "SHA1",
digits: 6,
period: 30,
secret: OTPAuth.Secret.fromBase32(SECRET)
});

let delta = totp.validate({ token: otpCode.value, window: 1 });

if (delta !== null) {
message.value = "Success!";
isSuccess.value = true;
} else {
message.value = "Invalid Code!";
isSuccess.value = false;
}
}
</script>