Skip to content

Commit

Permalink
Merge branch 'ent' into oxdcomponent
Browse files Browse the repository at this point in the history
  • Loading branch information
DanuAnjana authored Oct 29, 2024
2 parents e308a7e + 15975c3 commit 30df74b
Show file tree
Hide file tree
Showing 9 changed files with 769 additions and 18 deletions.
10 changes: 10 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2024-10-28 - e5840791366e3abbf3cb6b57f77ede4a8842fb79 - Icon/icons.ts - Add oxd-date-input, oxd-attachment-input,oxd-checkbox-input, oxd-checkbox-group-input, oxd-select-input, oxd-file-input, oxd-radio-input, oxd-radio-group-input, oxd-switch-input, oxd-time-input, oxd-text-input, oxd-password-input, oxd-circle-plus, oxd-textbox, oxd-text, oxd-divider, oxd-grid, oxd-grid-item, oxd-subform, oxd-masterdata, oxd-employee-autocomplete, oxd-status, oxd-required to OXD Icons

2024-10-26 - a7f234223a3a34e55a77e3c216733c9f01e5e3c9 - directives/focus-first-element/index.ts - Update the focus first directive to wait for animations to stop

2024-10-25 - 0ba4cd7666f48d5e702ff930ec39f43f203bc4bc -Input/PasswordInput.vue - Updating password Input field

2024-10-22 - 84b7f4bfe4893a54c8bd281e10feda17a2356abd -Icon/icons.ts - Added new icon as oxd-open-new-tab

2024-10-18 - 59c22c85b1256cc167408e93402f6fb85a3bb775 -Input/PasswordInput.vue - Updating password Input field

2024-10-11 - 6d028db15ec82666c290476cc656467c1e95b9aa - LinkWithPill.vue, link-with-pill.spec.ts, ProfilePicture.vue, ProfilePic.vue, profile-pic.spec.ts, ListSkeleton.story.vue - add onclick event to prevent default behaviour of link and execute a function

2024-10-03 - 15c4f9e5f2459055c23bae0bdc1afa6590321950 - Icon/icons.ts - Added preboarding feature related icons list
Expand Down
262 changes: 259 additions & 3 deletions components/src/core/components/Icon/icons.ts

Large diffs are not rendered by default.

132 changes: 129 additions & 3 deletions components/src/core/components/Input/PasswordInput.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,142 @@
<template>
<oxd-input type="password" />
<div :class="strengthClass">
<oxd-text class="password-strength-check" v-if="showStrength">
{{ strengthLabel }}
</oxd-text>
<oxd-input
v-bind="$attrs"
class="password-input"
:hasError="hasError"
:disabled="disabled"
:readonly="readonly"
:type="isPasswordVisible ? 'text' : 'password'"
></oxd-input>
<div
:class="[
'password-view-icon-container',
{'password-visible': isPasswordVisible},
]"
@click="togglePasswordVisibility"
>
<oxd-icon-button
class="oxd-password-view-icon"
:name="isPasswordVisible ? 'eye-slash-fill' : 'eye-fill'"
:iconStyles="isPasswordVisible ? {color: 'white'} : {}"
:tooltip="isPasswordVisible ? 'Hide Password' : 'Show Password'"
size="large"
/>
</div>
</div>
</template>

<script lang="ts">
import {defineComponent} from 'vue';
import {defineComponent, ref, computed} from 'vue';
import Input from '@orangehrm/oxd/core/components/Input/Input.vue';
import oxdText from '@orangehrm/oxd/core/components/Text/Text.vue';
import IconButton from '@orangehrm/oxd/core/components/Button/Icon.vue';
import useTranslate from '@orangehrm/oxd/composables/useTranslate';
export default defineComponent({
name: 'oxd-password-input',
components: {
'oxd-input': Input,
'oxd-text': oxdText,
'oxd-icon-button': IconButton,
},
props: {
strength: {
type: Number,
default: -1,
validator: (value: number) => [-1, 0, 1, 2, 3, 4, 5].includes(value),
},
hasError: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
readonly: {
type: Boolean,
default: false,
},
hasMinimumPasswordStrength: {
type: Boolean,
default: true,
},
},
setup(props) {
// Reactive reference for password visibility
const isPasswordVisible = ref(false);
const {$t} = useTranslate();
// Computed properties for strengthClass, strengthLabel, and showStrength
const strengthClass = computed(() => {
const strengthClasses = [
'very-weak-strength',
'weak-strength',
'better-strength',
'medium-strength',
'strong-strength',
'strongest-strength',
];
if (!props.hasMinimumPasswordStrength) {
return 'password-container below-minimum-strength';
}
if (
props.strength === -1 ||
props.hasError ||
props.disabled ||
props.readonly
) {
return 'password-container';
}
return `password-container ${strengthClasses[props.strength]}`;
});
const strengthLabel = computed(() => {
const strengthLabels = [
'Very Weak',
'Weak',
'Better',
'Medium',
'Strong',
'Strongest',
];
return $t(strengthLabels[props.strength]);
});
const showStrength = computed(() => {
if (!props.hasMinimumPasswordStrength && props.strength !== -1) {
return true;
}
return (
props.strength !== -1 &&
!props.hasError &&
!props.disabled &&
!props.readonly
);
});
// Method to toggle password visibility
const togglePasswordVisibility = () => {
isPasswordVisible.value = !isPasswordVisible.value;
};
return {
isPasswordVisible,
strengthClass,
strengthLabel,
showStrength,
togglePasswordVisibility,
};
},
});
</script>
<style src="./password-input.scss" lang="scss" scoped></style>
Original file line number Diff line number Diff line change
@@ -1,22 +1,67 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PasswordInput.vue renders OXD Input 1`] = `
<div class="input-outer-wrapper">
<div class="password-container" label="Input">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active" type="password" label="Input">
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active password-input" label="Input" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
exports[`PasswordInput.vue should renders OXD Input with custom color 1`] = `
<div class="input-outer-wrapper">
<div class="password-container" label="Input" style="background-color: aliceblue;">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active" style="background-color: aliceblue;" type="password" label="Input">
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active password-input" style="background-color: aliceblue;" label="Input" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
exports[`PasswordInput.vue should renders OXD Input with custom placeholder 1`] = `
<div class="password-container" label="Input" placeholder="Custom placeholder">
<!--v-if-->
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active password-input" label="Input" placeholder="Custom placeholder" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
exports[`PasswordInput.vue should renders OXD Input with error 1`] = `
<div class="input-outer-wrapper">
<div class="password-container" label="Input">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active oxd-input--error" type="password" label="Input">
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active oxd-input--error password-input" label="Input" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
exports[`PasswordInput.vue should renders OXD Input with error message 1`] = `
<div class="password-container" label="Input" errormessage="Error message">
<!--v-if-->
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active oxd-input--error password-input" label="Input" errormessage="Error message" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
exports[`PasswordInput.vue should renders OXD Input with strength meter 1`] = `
<div class="password-container weak-strength" label="Input">
<p class="oxd-text oxd-text--p password-strength-check">Weak</p>
<div class="input-outer-wrapper">
<!--v-if-->
<!--v-if--><input class="oxd-input oxd-input--active password-input" label="Input" type="password">
</div>
<div class="password-view-icon-container"><button type="button" class="oxd-icon-button oxd-password-view-icon" tooltip="Show Password" flow="top"><i class="oxd-icon oxd-icon--large bi-eye-fill"></i></button></div>
</div>
`;
152 changes: 152 additions & 0 deletions components/src/core/components/Input/__tests__/password-input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,156 @@ describe('PasswordInput.vue', () => {
});
expect(wrapper.html()).toMatchSnapshot();
});

it('should renders OXD Input with error message', () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, hasError: true, errorMessage: 'Error message'},
});
expect(wrapper.html()).toMatchSnapshot();
});

it('should renders OXD Input with custom placeholder', () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, placeholder: 'Custom placeholder'},
});
expect(wrapper.html()).toMatchSnapshot();
});

it('should renders OXD Input with strength meter', () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, strength: 1},
});
expect(wrapper.html()).toMatchSnapshot();
});
it('if stregth value is 1 then it should show medium', async () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, strength: 1},
});
await wrapper.find('.password-input').setValue('oldPass123');
expect(wrapper.html()).toContain('Weak');
});

it('if stregth value is 2 then it should show medium', async () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, strength: 2},
});
await wrapper.find('.password-input').setValue('oldPass123');
expect(wrapper.html()).toContain('Better');
});
it('if stregth value is 3 then it should show strong', async () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, strength: 3},
});
await wrapper.find('.password-input').setValue('oldPass123');
expect(wrapper.html()).toContain('Medium');
});
it('if stregth value is 4 then it should show very strong', async () => {
const value = 'Input';
const wrapper = mount(PasswordInput, {
props: {label: value, strength: 4},
});
await wrapper.find('.password-input').setValue('oldPass123');
expect(wrapper.html()).toContain('Strong');
});
it('on input', async () => {
const wrapper = mount(PasswordInput, {});
const input = wrapper.find('input');
await input.trigger('input');
expect(wrapper.emitted()).toHaveProperty('input');
});
it('should toggle password visibility when icon is clicked', async () => {
const wrapper = mount(PasswordInput);
expect(wrapper.vm.isPasswordVisible).toBe(false);
const toggleButton = wrapper.find('.password-view-icon-container');
await toggleButton.trigger('click');
expect(wrapper.vm.isPasswordVisible).toBe(true);
await toggleButton.trigger('click');
expect(wrapper.vm.isPasswordVisible).toBe(false);
});
it('should hide password strength when password is too short', async () => {
const wrapper = mount(PasswordInput, {
data() {
return {
password: 'short',
};
},
});

expect(wrapper.vm.showStrength).toBe(false);
});
it('should show password strength when password is long enough', async () => {
const wrapper = mount(PasswordInput, {
props: {
strength: 1,
hasError: false,
},
data() {
return {
password: 'longEnoughPassword',
};
},
});

expect(wrapper.vm.showStrength).toBe(true);
});
it('should hid password strength when password is too long ', async () => {
const wrapper = mount(PasswordInput, {
data() {
return {
password: 'a'.repeat(65),
};
},
});

expect(wrapper.vm.showStrength).toBe(false);
});
it('should hide password strength when component is disabled', async () => {
const wrapper = mount(PasswordInput, {
props: {
disabled: true,
},
});

expect(wrapper.vm.showStrength).toBe(false);
});
it('should hide password strength when component is readonly', async () => {
const wrapper = mount(PasswordInput, {
props: {
readonly: true,
},
});

expect(wrapper.vm.showStrength).toBe(false);
});
it('should hide password strength when component has an error', async () => {
const wrapper = mount(PasswordInput, {
props: {
hasError: true,
},
});

expect(wrapper.vm.showStrength).toBe(false);
});
it('should hide password strength when component has no strength prop', async () => {
const wrapper = mount(PasswordInput, {});
expect(wrapper.vm.showStrength).toBe(false);
});
it('should show password strength gray color when hasMinimumPasswordStrength is false', async () => {
const wrapper = mount(PasswordInput, {
props: {
hasMinimumPasswordStrength: false,
strength: 1,
},
});
expect(wrapper.vm.showStrength).toBe(true);
expect(wrapper.vm.strengthClass).toBe(
'password-container below-minimum-strength',
);
});
});
Loading

0 comments on commit 30df74b

Please sign in to comment.