test: add unit test for input-group

This commit is contained in:
Sagi 2022-09-15 09:48:05 +08:00
parent ccc920ef58
commit dbf3e09331
16 changed files with 3762 additions and 7524 deletions

21
.gitignore vendored
View File

@ -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?

View File

@ -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",

View File

@ -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',
},
},
],
]
};

View File

@ -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",

View File

@ -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);
},
};

View File

@ -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();
});
});

View File

@ -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>
);
};
},
});

View File

@ -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>;

View File

@ -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'],
};

View File

@ -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
};

View File

@ -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"
}
}

View File

@ -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>

View File

@ -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')

File diff suppressed because it is too large Load Diff

3758
yarn.lock

File diff suppressed because it is too large Load Diff