This commit is contained in:
2026-08-14 16:06:30 +08:00
parent 1c1c48f8d3
commit d1b4a4d3f3
26 changed files with 187 additions and 29 deletions
+10
View File
@@ -1,6 +1,8 @@
import { defineComponent } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import AppDialog from './AppDialog.vue'
const ElDialogStub = defineComponent({
@@ -62,4 +64,12 @@ describe('AppDialog', () => {
const wrapper = mountDialog({ showFooter: false })
expect(wrapper.findAll('button')).toHaveLength(0)
})
it('keeps the dialog chrome fixed while long content scrolls in the body', () => {
const source = readFileSync(resolve(process.cwd(), 'src/shared/components/AppDialog.vue'), 'utf8')
expect(source).toContain(':global(.app-dialog.el-dialog) { display: flex;')
expect(source).toContain(':global(.app-dialog .el-dialog__body) { min-height: 0; overflow-y: auto;')
expect(source).toContain('max-height: calc(100svh - 20px)')
})
})
+4 -1
View File
@@ -88,8 +88,11 @@ function closeDialog() {
</template>
<style scoped>
:global(.app-dialog.el-dialog) { display: flex; max-height: min(90vh, 900px); flex-direction: column; overflow: hidden; }
:global(.app-dialog .el-dialog__header), :global(.app-dialog .el-dialog__footer) { flex: 0 0 auto; }
:global(.app-dialog .el-dialog__body) { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.app-dialog__body { min-height: 0; }
.app-dialog__footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
.app-dialog__footer :deep(.el-button) { margin-left: 0; }
@media (max-width: 720px) { .app-dialog__footer :deep(.el-button) { min-height: 44px; } }
@media (max-width: 720px) { :global(.app-dialog.el-dialog) { max-height: calc(100svh - 20px); margin-block: 10px !important; } .app-dialog__footer :deep(.el-button) { min-height: 44px; } }
</style>
+66
View File
@@ -0,0 +1,66 @@
import { defineComponent } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import AppDrawer from './AppDrawer.vue'
const ElDrawerStub = defineComponent({
props: {
modelValue: Boolean,
showClose: Boolean,
closeOnClickModal: Boolean,
closeOnPressEscape: Boolean,
},
template: '<section data-testid="drawer"><slot name="header" /><slot /><slot name="footer" /></section>',
})
const ElButtonStub = defineComponent({
props: { disabled: Boolean, loading: Boolean },
emits: ['click'],
template: '<button type="button" :disabled="disabled" @click="$emit(\'click\')"><slot /></button>',
})
function mountDrawer(props: Record<string, unknown> = {}) {
return mount(AppDrawer, {
props: { modelValue: true, title: '编辑资料', ...props },
slots: { default: '<p>抽屉内容</p>' },
global: {
stubs: { ElDrawer: ElDrawerStub, ElButton: ElButtonStub },
directives: { loading: {} },
},
})
}
describe('AppDrawer', () => {
it('provides default cancel and confirm actions', async () => {
const wrapper = mountDrawer()
const buttons = wrapper.findAll('button')
expect(buttons.map((button) => button.text())).toEqual(['取消', '确定'])
await buttons[1].trigger('click')
expect(wrapper.emitted('confirm')).toHaveLength(1)
await buttons[0].trigger('click')
expect(wrapper.emitted('cancel')).toHaveLength(1)
expect(wrapper.emitted('update:modelValue')).toEqual([[false]])
})
it('prevents accidental closing while confirmation is submitting', () => {
const wrapper = mountDrawer({ confirmLoading: true })
const drawer = wrapper.getComponent(ElDrawerStub)
const cancelButton = wrapper.findAll('button')[0]
expect(drawer.props('showClose')).toBe(false)
expect(drawer.props('closeOnClickModal')).toBe(false)
expect(drawer.props('closeOnPressEscape')).toBe(false)
expect(cancelButton.attributes('disabled')).toBeDefined()
})
it('keeps the drawer chrome fixed while long content scrolls in the body', () => {
const source = readFileSync(resolve(process.cwd(), 'src/shared/components/AppDrawer.vue'), 'utf8')
expect(source).toContain(':global(.app-drawer .el-drawer__body) { min-height: 0; overflow-y: auto;')
expect(source).toContain('max-width: 94vw')
})
})
+2
View File
@@ -88,6 +88,8 @@ function closeDrawer() {
<style scoped>
:global(.app-drawer) { max-width: calc(100vw - 20px); }
:global(.app-drawer .el-drawer__header), :global(.app-drawer .el-drawer__footer) { flex: 0 0 auto; }
:global(.app-drawer .el-drawer__body) { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.app-drawer__body { min-height: 0; }
.app-drawer__footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
.app-drawer__footer :deep(.el-button) { margin-left: 0; }