feat(11-04): mobile-safe modals and form baseline verification
- Add max-h-[90vh] overflow-y-auto to ShareModal, CloudCredentialModal, FolderDeleteModal, and DocumentView cloud-delete modal panels - Add responsive px-4 sm:px-6 to DocumentPreviewModal header for narrow viewports - Add data-test attributes to all modal panels for testability - Confirm @tailwindcss/forms active in tailwind.config.js (no drift found) - Audit forms: focus:outline-none focus:ring-2 pattern is consistent throughout - Add 4 test files covering mobile-safe modal classes and form baseline: ShareModal.mobile.test.js, CloudCredentialModal.mobile.test.js, FolderDeleteModal.mobile.test.js, DocumentPreviewModal.mobile.test.js VISUAL-02, RESP-04
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
|
||||
vi.mock('../../../api/client.js', () => ({
|
||||
fetchDocumentContent: vi.fn().mockResolvedValue({ ok: true, blob: () => Promise.resolve(new Blob()) }),
|
||||
}))
|
||||
|
||||
import DocumentPreviewModal from '../DocumentPreviewModal.vue'
|
||||
|
||||
const globalStubs = {
|
||||
AppIcon: true,
|
||||
}
|
||||
|
||||
const testDoc = { id: 'doc-1', filename: 'test.pdf', original_name: 'test.pdf' }
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
// Mock URL.createObjectURL since it's not available in jsdom
|
||||
vi.stubGlobal('URL', {
|
||||
createObjectURL: vi.fn().mockReturnValue('blob:mock-url'),
|
||||
revokeObjectURL: vi.fn(),
|
||||
})
|
||||
})
|
||||
|
||||
describe('RESP-04: DocumentPreviewModal mobile-safe sizing', () => {
|
||||
it('renders full-screen overlay (fixed inset-0)', () => {
|
||||
const wrapper = mount(DocumentPreviewModal, {
|
||||
props: { doc: testDoc },
|
||||
global: { stubs: globalStubs },
|
||||
})
|
||||
const overlay = wrapper.find('[data-test="document-preview-modal"]')
|
||||
expect(overlay.exists()).toBe(true)
|
||||
expect(overlay.classes()).toContain('fixed')
|
||||
expect(overlay.classes()).toContain('inset-0')
|
||||
})
|
||||
|
||||
it('header has responsive horizontal padding (px-4 at mobile, sm:px-6 at >=640px)', () => {
|
||||
const wrapper = mount(DocumentPreviewModal, {
|
||||
props: { doc: testDoc },
|
||||
global: { stubs: globalStubs },
|
||||
})
|
||||
const header = wrapper.find('[data-test="preview-modal-header"]')
|
||||
expect(header.exists()).toBe(true)
|
||||
expect(header.classes()).toContain('px-4')
|
||||
expect(header.classes()).toContain('sm:px-6')
|
||||
})
|
||||
|
||||
it('header filename is truncated with truncate class to prevent overflow', () => {
|
||||
const wrapper = mount(DocumentPreviewModal, {
|
||||
props: { doc: testDoc },
|
||||
global: { stubs: globalStubs },
|
||||
})
|
||||
const header = wrapper.find('[data-test="preview-modal-header"]')
|
||||
// The filename span should have truncate class
|
||||
const filenameSpan = header.find('span.truncate')
|
||||
expect(filenameSpan.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user