From 84869d071317e0678d7943e6d7b21905f091fd47 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 25 Mar 2024 13:34:48 -0600 Subject: [PATCH] Styles for error state and test for max file size --- .../ImageFileUpload/ImageFileUpload.mdx | 8 +- .../ImageFileUpload.stories.ts | 7 + .../ImageFileUpload/ImageFileUpload.vue | 52 +- .../__tests__/ImageFileUpload.spec.ts | 28 + .../ImageFileUpload.spec.ts.snap | 972 +++++++++++++++++- 5 files changed, 1037 insertions(+), 30 deletions(-) diff --git a/src/components/ImageFileUpload/ImageFileUpload.mdx b/src/components/ImageFileUpload/ImageFileUpload.mdx index 699631194..0e8aca849 100644 --- a/src/components/ImageFileUpload/ImageFileUpload.mdx +++ b/src/components/ImageFileUpload/ImageFileUpload.mdx @@ -1,5 +1,5 @@ import { Canvas, ArgTypes, PRIMARY_STORY } from '@storybook/addon-docs'; -import { Default } from './ImageFileUpload.stories'; +import { Default, FileSizeError } from './ImageFileUpload.stories'; # Image File Upload @@ -16,6 +16,12 @@ will be obscured by the choose button. +## Max File Size Error + +Choose any image file larger than 1 byte to see the error state when the file size exceeds the configured `maxFileSize`. + + + ## Props diff --git a/src/components/ImageFileUpload/ImageFileUpload.stories.ts b/src/components/ImageFileUpload/ImageFileUpload.stories.ts index 0b3137653..8cb9a63d8 100644 --- a/src/components/ImageFileUpload/ImageFileUpload.stories.ts +++ b/src/components/ImageFileUpload/ImageFileUpload.stories.ts @@ -21,3 +21,10 @@ export const Default: Story = { name: 'demo' } }; + +export const FileSizeError: Story = { + args: { + name: 'demo-filesize-error', + maxFileSize: 1 + } +}; diff --git a/src/components/ImageFileUpload/ImageFileUpload.vue b/src/components/ImageFileUpload/ImageFileUpload.vue index 6544d881c..fe04b1f22 100644 --- a/src/components/ImageFileUpload/ImageFileUpload.vue +++ b/src/components/ImageFileUpload/ImageFileUpload.vue @@ -13,7 +13,8 @@ { 'uic-img-upload--basic': props.mode === 'basic', 'uic-img-upload--advanced': props.mode === 'advanced', - 'uic-img-upload--preview': state.files?.length > 0 + 'uic-img-upload--preview': state.files?.length > 0, + 'uic-img-upload--with-messages': state.messages?.length > 0 } ] }; @@ -108,6 +109,27 @@ return { class: ['uic-img-upload__file'] }; + }, + message: function () { + return { + root( + _: MessagePassThroughMethodOptions + ) { + return { + class: ['uic-img-upload__message'] + }; + }, + icon() { + return { + class: ['uic-img-upload__message-icon'] + }; + }, + closeButton() { + return { + class: ['uic-img-upload__message-close-btn'] + }; + } + }; } }" @select="($event) => onSelectFile($event)" @@ -128,6 +150,8 @@ import FileUpload, { FileUploadSelectEvent } from 'primevue/fileupload'; // eslint-disable-next-line no-unused-vars import type { FileUploadPassThroughMethodOptions } from 'primevue/fileupload'; +// eslint-disable-next-line no-unused-vars +import type { MessagePassThroughMethodOptions } from 'primevue/message'; export interface ImageFileUploadProps { /** @@ -160,7 +184,7 @@ export interface ImageFileUploadProps { export interface FileSelectedEvent { originalEvent: Event; - file: File; + file?: File; } /* eslint-disable no-unused-vars */ @@ -171,7 +195,7 @@ export interface ImageFileEmits { * | Event Property | Type | Description | * | --------------- | ------- | ----------- | * | originalEvent | Event | The original event. | - * | file | File | The selected file. | + * | file | File / `undefined` | The selected file or `undefined` if the selected file exceeds the maxFileSize or is an invalid file type. | * * @event fileSelected */ @@ -218,6 +242,16 @@ function onSelectFile($event: FileUploadSelectEvent) { } } + &--with-messages { + #{$root}__choose-btn { + @apply hidden; + } + + #{$root}__content { + @apply flex flex-col items-center; + } + } + & > input[type='file'] { @apply hidden; } @@ -277,5 +311,17 @@ function onSelectFile($event: FileUploadSelectEvent) { &__badge { @apply hidden; } + + &__message { + @apply flex justify-center w-full; + + & > div { + @apply flex flex-row-reverse gap-2; + } + + #{$root}__message-icon { + @apply my-auto text-red-500; + } + } } diff --git a/src/components/ImageFileUpload/__tests__/ImageFileUpload.spec.ts b/src/components/ImageFileUpload/__tests__/ImageFileUpload.spec.ts index 4081a6db1..1e7de0195 100644 --- a/src/components/ImageFileUpload/__tests__/ImageFileUpload.spec.ts +++ b/src/components/ImageFileUpload/__tests__/ImageFileUpload.spec.ts @@ -135,6 +135,34 @@ describe('ImageFileUpload', () => { }); }); + it('should display an error when the file size exceeds the maxFileSize prop', async () => { + const { baseElement, getByRole, container, emitted } = renderComponent({ + props: { ...initialProps, maxFileSize: 1 } + }); + + const fileInput = container.querySelector('input[type="file"]'); + + expect(fileInput).toBeInTheDocument(); + + const file = new File(['(⌐□_□)'], 'chucknorris.png', { + type: 'image/png' + }); + + userEvent.upload(fileInput as HTMLElement, file); + + await waitFor(() => { + const error = getByRole('alert'); + expect(error).toBeInTheDocument(); + expect(error).toHaveTextContent( + 'Invalid file size, file size should be smaller than 1 B' + ); + expect(emitted()).toHaveProperty('fileSelected'); + const [fileSelectedEvent] = emitted().fileSelected as [FileSelectedEvent]; + expect(fileSelectedEvent.file).toBeUndefined(); + expect(baseElement).toMatchSnapshot(); + }); + }); + it('should emit the fileSelected event when a file is selected', async () => { const { container, emitted } = renderComponent({ props: initialProps }); diff --git a/src/components/ImageFileUpload/__tests__/__snapshots__/ImageFileUpload.spec.ts.snap b/src/components/ImageFileUpload/__tests__/__snapshots__/ImageFileUpload.spec.ts.snap index 05e8f8a33..16d3d5a74 100644 --- a/src/components/ImageFileUpload/__tests__/__snapshots__/ImageFileUpload.spec.ts.snap +++ b/src/components/ImageFileUpload/__tests__/__snapshots__/ImageFileUpload.spec.ts.snap @@ -1,20 +1,857 @@ // Vitest Snapshot v1 +exports[`ImageFileUpload > should display an error when the file size exceeds the maxFileSize prop 1`] = ` + +
+
+ +
+ + + + + + + Upload + + + + + +
+
+ + + + + + + + + + + +
+ +

+ +

+
+
+
+ +`; + +exports[`ImageFileUpload > should display an error when the file size exceeds the maxFileSize prop 2`] = ` + +
+
+ +
+ + + + + + + Upload + + + + + +
+
+ + + + + + + + + + + +
+ +

+ +

+
+
+
+ +`; + exports[`ImageFileUpload > should render correctly 1`] = `
+ +
+ + + + + + + Upload + + + + + +
+
+ + + + + + + + +
+ +

+ +

+
+
+
+ +`; + +exports[`ImageFileUpload > should render the preview when a file is selected 1`] = ` + +
+
+ +
+ + + + + + + Upload + + + + + +
+
+ +
+
+ +
+ +
+ + + +
+ chucknorris.png +
+
+ chucknorris.png +
+ + 12 B + + + + Pending + + +
+
+ +
+
+ + + + + +
+
+
+ +`; + +exports[`ImageFileUpload > should render the preview when a file is selected 2`] = ` + +
+
@@ -38,10 +875,9 @@ exports[`ImageFileUpload > should render correctly 1`] = ` +
+ + + + +
`; -exports[`ImageFileUpload > should render the preview when a file is selected 1`] = ` +exports[`ImageFileUpload > should render the preview when a file is selected 3`] = `
should render the preview when a file is selected 1`] xmlns="http://www.w3.org/2000/svg" > should render the preview when a file is selected 1`] should render the preview when a file is selected 1`] class="p-fileupload-file-thumbnail" data-pc-section="thumbnail" role="presentation" - src="blob:nodedata:0b53d927-be7a-4302-90ce-7d1bf3a2b295" + src="blob:nodedata:46508c64-e118-41e4-88a3-7b5cb0ef2ccf" width="50" />
should render the preview when a file is selected 1`] `; -exports[`ImageFileUpload > should render the preview when a file is selected 2`] = ` +exports[`ImageFileUpload > should render the preview when a file is selected 4`] = `
should render the preview when a file is selected 2`] xmlns="http://www.w3.org/2000/svg" > should render the preview when a file is selected 2`] should render the preview when a file is selected 2`] class="p-fileupload-file-thumbnail" data-pc-section="thumbnail" role="presentation" - src="blob:nodedata:b2e83de3-9073-4f55-9d2b-08ada0ae9e18" + src="blob:nodedata:8204d6f4-7270-4554-8938-3436b6512431" width="50" />
should render the preview when a file is selected 2`] `; -exports[`ImageFileUpload > should render the preview when a file is selected 3`] = ` +exports[`ImageFileUpload > should render the preview when a file is selected 5`] = `
should render the preview when a file is selected 3`] class="p-fileupload-file-thumbnail" data-pc-section="thumbnail" role="presentation" - src="blob:nodedata:46508c64-e118-41e4-88a3-7b5cb0ef2ccf" + src="blob:nodedata:b8b01849-aae3-4698-b9fa-f775c1de3c01" width="50" />