test: add unit test for input-group
This commit is contained in:
parent
ccc920ef58
commit
dbf3e09331
|
@ -1 +1,22 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"@types/lodash": "^4.14.182",
|
||||
"@types/node": "^18.7.16",
|
||||
"esbuild-register": "^3.3.0",
|
||||
"eslint": "^8.23.0",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"husky": "^8.0.0",
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
|
||||
|
||||
|
||||
|
||||
extends: [
|
||||
'plugin:vue/vue3-recommended',
|
||||
'airbnb-base',
|
||||
|
@ -20,7 +16,7 @@ module.exports = {
|
|||
jsx: true,
|
||||
tsx: true,
|
||||
},
|
||||
extraFileExtensions: ['.vue'],
|
||||
extraFileExtensions: ['.vue']
|
||||
},
|
||||
|
||||
plugins: ['@typescript-eslint'],
|
||||
|
@ -35,6 +31,7 @@ module.exports = {
|
|||
rules: {
|
||||
'accessor-pairs': 'off',
|
||||
'array-callback-return': 'off',
|
||||
"arrow-body-style":'off',
|
||||
'curly': 'error',
|
||||
'class-methods-use-this': 'off',
|
||||
'complexity': [
|
||||
|
@ -111,7 +108,7 @@ module.exports = {
|
|||
// typescript-eslint
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
|
@ -121,7 +118,6 @@ module.exports = {
|
|||
'@typescript-eslint/no-useless-constructor': 'off',
|
||||
'@typescript-eslint/no-parameter-properties': 'off',
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/dot-notation': 'off',
|
||||
'@typescript-eslint/indent': [
|
||||
'error',
|
||||
|
@ -142,12 +138,11 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
'@typescript-eslint/no-misused-new': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||
'@typescript-eslint/prefer-function-type': 'error',
|
||||
'@typescript-eslint/semi': ['error', 'always'],
|
||||
'@typescript-eslint/type-annotation-spacing': 'error',
|
||||
'@typescript-eslint/unified-signatures': 'error',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/member-ordering': 'off',
|
||||
'@typescript-eslint/no-this-alias': 'off',
|
||||
// eslint-plugin-vue
|
||||
|
@ -170,5 +165,5 @@ module.exports = {
|
|||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.36.1",
|
||||
"@typescript-eslint/eslint-plugin-tslint": "^5.36.1",
|
||||
"@typescript-eslint/parser": "^5.36.1",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import type { App } from 'vue';
|
||||
import InputGroup from './src/input-group.component';
|
||||
|
||||
export * from './src/input-group.props';
|
||||
|
||||
export { InputGroup };
|
||||
|
||||
export default {
|
||||
install(app: App): void {
|
||||
app.component("inputGroup2", InputGroup);
|
||||
}
|
||||
};
|
||||
install(app: App): void {
|
||||
app.component(InputGroup.name, InputGroup);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import { InputGroup } from '..';
|
||||
|
||||
describe('f-input-group', () => {
|
||||
it('variant', () => {
|
||||
const wrapper = mount({
|
||||
setup() {
|
||||
return () => {
|
||||
return <InputGroup editable={false}></InputGroup>;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find('.f-cmp-inputgroup').exists()).toBeTruthy();
|
||||
expect(wrapper.find('div').find('div').find('input').find('[readlony]').exists).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,101 +1,106 @@
|
|||
|
||||
import { defineComponent, computed } from "vue";
|
||||
import { InputGroupProps, props } from './input-group.props';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import type { SetupContext } from 'vue';
|
||||
import { InputGroupProps, inputGroupProps } from './input-group.props';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'input-group3',
|
||||
props,
|
||||
setup(props: InputGroupProps) {
|
||||
const textBoxTitle = computed(() => (props.enableTitle ? props.value : ''));
|
||||
name: 'FInputGroup',
|
||||
props: inputGroupProps,
|
||||
setup(props: InputGroupProps, context: SetupContext) {
|
||||
const textBoxTitle = computed(() => (props.enableTitle ? props.value : ''));
|
||||
|
||||
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
|
||||
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
|
||||
|
||||
const isTextBoxReadonly = computed(() => {
|
||||
return props.readonly || !props.editable;
|
||||
});
|
||||
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
|
||||
|
||||
const inputGroupClass = computed(() => ({
|
||||
'input-group': true,
|
||||
'f-state-disable': props.disable,
|
||||
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
||||
'f-state-readonly': props.readonly && !props.disable
|
||||
}));
|
||||
const inputGroupClass = computed(() => ({
|
||||
'input-group': true,
|
||||
'f-state-disable': props.disable,
|
||||
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
||||
'f-state-readonly': props.readonly && !props.disable,
|
||||
}));
|
||||
|
||||
const textBoxClass = computed(() => ({
|
||||
'text-left': props.textAlign === 'left',
|
||||
'text-center': props.textAlign === 'center',
|
||||
'text-right': props.textAlign === 'right',
|
||||
'form-control': true,
|
||||
'f-utils-fill': true
|
||||
}));
|
||||
const textBoxClass = computed(() => ({
|
||||
'text-left': props.textAlign === 'left',
|
||||
'text-center': props.textAlign === 'center',
|
||||
'text-right': props.textAlign === 'right',
|
||||
'form-control': true,
|
||||
'f-utils-fill': true,
|
||||
}));
|
||||
|
||||
const inputGroupAppendClass = computed(() => ({
|
||||
'input-group-append': true,
|
||||
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable)
|
||||
const inputGroupAppendClass = computed(() => ({
|
||||
'input-group-append': true,
|
||||
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||
}));
|
||||
|
||||
}));
|
||||
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
||||
|
||||
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
||||
|
||||
function onBlur($event: Event) {
|
||||
console.log('on blur');
|
||||
}
|
||||
function onClearValue($event: Event) {
|
||||
console.log('on onClearValue');
|
||||
}
|
||||
function onEnter($event: KeyboardEvent) {
|
||||
console.log('on onEnter');
|
||||
}
|
||||
function onClickHandle(event: Event) {
|
||||
console.log('on onClickHandle');
|
||||
}
|
||||
function onIconMouseEnter(e: MouseEvent) {
|
||||
console.log('on onIconMouseEnter');
|
||||
}
|
||||
function onIconMouseLeave(e: MouseEvent) {
|
||||
console.log('on onIconMouseLeave');
|
||||
}
|
||||
function onInputClick($event: Event) {
|
||||
console.log('on onInputClick');
|
||||
}
|
||||
function onInputFocus($event: Event) {
|
||||
console.log('on onInputFocus');
|
||||
}
|
||||
function onMouseDown($event: MouseEvent) {
|
||||
console.log('on onMousedown');
|
||||
}
|
||||
function onMouseOverInExtentInfo($event: Event) {
|
||||
console.log('on onMouseOverInExtentInfo');
|
||||
}
|
||||
function onValueChange(val: string, emit = true) {
|
||||
console.log('on onValueChange');
|
||||
}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div class="f-cmp-inputgroup" id={props.id}>
|
||||
<div class={[props.customClass, inputGroupClass.value]}>
|
||||
<input name="input-group-value" autocomplete={'' + props.autoComplete} class={textBoxClass.value} disabled={props.disable}
|
||||
maxlength={props.maxLength} minlength={props.minLength} placeholder={textBoxPlaceholder.value}
|
||||
readonly={isTextBoxReadonly.value} tabindex={props.tabIndex} title={textBoxTitle.value} type={props.inputType}
|
||||
onBlur={onBlur} onClick={onInputClick} onFocus={onInputFocus} onKeydown={onEnter}
|
||||
onMousedown={onMouseDown} />
|
||||
<div class={inputGroupAppendClass.value}>
|
||||
{
|
||||
showClearButton.value &&
|
||||
<span class="input-group-text input-group-clear">
|
||||
<i class="f-icon modal_close"></i>
|
||||
</span>
|
||||
}
|
||||
{
|
||||
props.groupText &&
|
||||
<span class="input-group-text" v-html={props.groupText}>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function onBlur($event: Event) {
|
||||
console.log('on blur');
|
||||
}
|
||||
})
|
||||
function onClearValue($event: Event) {
|
||||
console.log('on onClearValue');
|
||||
}
|
||||
function onEnter($event: KeyboardEvent) {
|
||||
console.log('on onEnter');
|
||||
}
|
||||
function onClickHandle(event: Event) {
|
||||
console.log('on onClickHandle');
|
||||
}
|
||||
function onIconMouseEnter(e: MouseEvent) {
|
||||
console.log('on onIconMouseEnter');
|
||||
}
|
||||
function onIconMouseLeave(e: MouseEvent) {
|
||||
console.log('on onIconMouseLeave');
|
||||
}
|
||||
function onInputClick($event: Event) {
|
||||
console.log('on onInputClick');
|
||||
}
|
||||
function onInputFocus($event: Event) {
|
||||
console.log('on onInputFocus');
|
||||
}
|
||||
function onMouseDown($event: MouseEvent) {
|
||||
console.log('on onMousedown');
|
||||
}
|
||||
function onMouseOverInExtentInfo($event: Event) {
|
||||
console.log('on onMouseOverInExtentInfo');
|
||||
}
|
||||
function onValueChange(val: string, emit = true) {
|
||||
console.log('on onValueChange');
|
||||
}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div class="f-cmp-inputgroup" id={props.id}>
|
||||
<div class={[props.customClass, inputGroupClass.value]}>
|
||||
<input
|
||||
name="input-group-value"
|
||||
autocomplete={'' + props.autoComplete}
|
||||
class={textBoxClass.value}
|
||||
disabled={props.disable}
|
||||
maxlength={props.maxLength}
|
||||
minlength={props.minLength}
|
||||
placeholder={textBoxPlaceholder.value}
|
||||
readonly={isTextBoxReadonly.value}
|
||||
tabindex={props.tabIndex}
|
||||
title={textBoxTitle.value}
|
||||
type={props.inputType}
|
||||
onBlur={onBlur}
|
||||
onClick={onInputClick}
|
||||
onFocus={onInputFocus}
|
||||
onKeydown={onEnter}
|
||||
onMousedown={onMouseDown}
|
||||
/>
|
||||
<div class={inputGroupAppendClass.value}>
|
||||
{showClearButton.value && (
|
||||
<span class="input-group-text input-group-clear">
|
||||
<i class="f-icon modal_close"></i>
|
||||
</span>
|
||||
)}
|
||||
{props.groupText && <span class="input-group-text" v-html={props.groupText}></span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
import { ExtractPropTypes } from 'vue';
|
||||
export const props = {
|
||||
id: String,
|
||||
customClass: { type: String, default: '' },
|
||||
disable: { type: Boolean, default: false },
|
||||
editable: { type: Boolean, default: true },
|
||||
readonly: { type: Boolean, default: false },
|
||||
textAlign: { type: String, default: 'left' },
|
||||
showButtonWhenDisabled: { type: Boolean, default: false },
|
||||
enableClear: { type: Boolean, default: false },
|
||||
groupText: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
||||
enableTitle: { type: Boolean, default: false },
|
||||
inputType: { type: String, default: 'text' },
|
||||
forcePlaceholder: { type: Boolean, default: false },
|
||||
placeholder: { type: String, default: '' },
|
||||
autoComplete: { type: Boolean, default: false },
|
||||
value: { type: String, default: '' },
|
||||
minLength: Number,
|
||||
maxLength: Number,
|
||||
tabIndex: Number
|
||||
|
||||
export const inputGroupProps = {
|
||||
id: String,
|
||||
customClass: { type: String, default: '' },
|
||||
disable: { type: Boolean, default: false },
|
||||
editable: { type: Boolean, default: true },
|
||||
readonly: { type: Boolean, default: false },
|
||||
textAlign: { type: String, default: 'left' },
|
||||
showButtonWhenDisabled: { type: Boolean, default: false },
|
||||
enableClear: { type: Boolean, default: false },
|
||||
groupText: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
||||
enableTitle: { type: Boolean, default: false },
|
||||
inputType: { type: String, default: 'text' },
|
||||
forcePlaceholder: { type: Boolean, default: false },
|
||||
placeholder: { type: String, default: '' },
|
||||
autoComplete: { type: Boolean, default: false },
|
||||
value: { type: String, default: '' },
|
||||
minLength: Number,
|
||||
maxLength: Number,
|
||||
tabIndex: Number
|
||||
};
|
||||
export type InputGroupProps = ExtractPropTypes<typeof props>;
|
||||
|
||||
export type InputGroupProps = ExtractPropTypes<typeof inputGroupProps>;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
module.exports = {
|
||||
// Automatically clear mock calls and instances between every test
|
||||
clearMocks: true,
|
||||
|
||||
// A map from regular expressions to paths to transformers
|
||||
transform: {
|
||||
'^.+\\.(ts|tsx|js|jsx)$': [
|
||||
'babel-jest',
|
||||
{
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }], ['@babel/preset-typescript']],
|
||||
plugins: ['@vue/babel-plugin-jsx'],
|
||||
},
|
||||
],
|
||||
},
|
||||
transformIgnorePatterns: ['node_modules/?!(lodash-es)'],
|
||||
// The glob patterns Jest uses to detect test files
|
||||
testMatch: ['**/**/*.spec.(ts|tsx)'],
|
||||
|
||||
// An array of file extensions your modules use
|
||||
moduleFileExtensions: ['js', 'json', 'ts', 'tsx'],
|
||||
|
||||
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
|
||||
moduleNameMapper: {
|
||||
'\\.(css|less|scss|sass)$': '<rootDir>/__mocks__/style-mock.ts',
|
||||
'\\.(gif|ttf|eot|svg|jpg|png)$': '<rootDir>/__mocks__/file-mock.ts',
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
||||
testPathIgnorePatterns: ['/node_modules/'],
|
||||
|
||||
// The test environment that will be used for testing
|
||||
testEnvironment: 'jest-environment-jsdom',
|
||||
setupFiles: ['<rootDir>/jest.setup.js'],
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import { config } from '@vue/test-utils';
|
||||
|
||||
import InputGroup from './components/input-group/src/input-group.component';
|
||||
|
||||
config.global.components = {
|
||||
'f-input-group': InputGroup
|
||||
};
|
|
@ -2,14 +2,20 @@
|
|||
"name": "@farris/ui-vue",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"test": "jest --config jest.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.2.37"
|
||||
"vue": "^3.2.37",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@vue/shared": "^3.2.0",
|
||||
"@vueuse/core": "9.2.0",
|
||||
"async-validator": "^4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^3.1.0",
|
||||
|
@ -17,6 +23,36 @@
|
|||
"@vue/babel-plugin-jsx": "^1.1.1",
|
||||
"typescript": "^4.6.4",
|
||||
"vite": "^3.1.0",
|
||||
"vue-tsc": "^0.40.4"
|
||||
"vue-tsc": "^0.40.4",
|
||||
"@vue/test-utils": "^2.0.0",
|
||||
"@babel/parser": "^7.19.0",
|
||||
"@babel/preset-env": "^7.19.0",
|
||||
"@babel/preset-typescript": "^7.18.0",
|
||||
"@babel/traverse": "^7.19.0",
|
||||
"@commitlint/cli": "^17.1.0",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"@types/chalk": "^2.2.0",
|
||||
"@types/commander": "^2.12.2",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/ora": "^3.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
||||
"@typescript-eslint/parser": "^5.37.0",
|
||||
"@vue/compiler-sfc": "^3.2.0",
|
||||
"@vuedx/typecheck": "^0.7.5",
|
||||
"@vuedx/typescript-plugin-vue": "^0.7.5",
|
||||
"babel-jest": "^29.0.3",
|
||||
"chalk": "^5.0.0",
|
||||
"commander": "^9.4.0",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"inquirer": "^9.1.1",
|
||||
"jest": "^29.0.0",
|
||||
"ora": "^6.1.2",
|
||||
"patch-vue-directive-ssr": "^0.0.1",
|
||||
"sass": "^1.32.2",
|
||||
"shelljs": "^0.8.4",
|
||||
"vite-plugin-md": "^0.20.0",
|
||||
"vite-svg-loader": "^3.6.0",
|
||||
"vitepress": "0.20.1",
|
||||
"vitepress-theme-demoblock": "1.3.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
// This starter template is using Vue 3 <script setup> SFCs
|
||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||
import { ref } from "vue";
|
||||
import HelloWorld from './components/HelloWorld.vue'
|
||||
import HelloWorld from './components/hello-world.vue'
|
||||
import InputGroup from "../components/input-group/src/input-group.component";
|
||||
|
||||
let canEdit = ref(true);
|
||||
let canAutoComplete = ref(false);
|
||||
const canEdit = ref(true);
|
||||
const canAutoComplete = ref(false);
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import App from './App.vue'
|
||||
import App from './app.vue'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
|
|
7138
yarn-error.log
7138
yarn-error.log
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue