diff --git a/src/components/feature-board-file-element/content/alert/FileAlerts.unit.ts b/src/components/feature-board-file-element/content/alert/FileAlerts.unit.ts index abcd4d9161..dcf394742f 100644 --- a/src/components/feature-board-file-element/content/alert/FileAlerts.unit.ts +++ b/src/components/feature-board-file-element/content/alert/FileAlerts.unit.ts @@ -32,6 +32,18 @@ describe("FileAlerts", () => { }); }); + describe("when alerts contains FileAlert.AUDIO_FORMAT_ERROR", () => { + it("should render FileAlert.AUDIO_FORMAT_ERROR", () => { + const { wrapper } = setup([FileAlert.AUDIO_FORMAT_ERROR]); + + const infoAlert = wrapper.findComponent(InfoAlert); + + expect(infoAlert.text()).toBe( + "components.cardElement.fileElement.audioFormatError" + ); + }); + }); + describe("when alerts contains FileAlert.AWAITING_SCAN_STATUS", () => { it("should render FileAlert.AWAITING_SCAN_STATUS", () => { const { wrapper } = setup([FileAlert.AWAITING_SCAN_STATUS]); diff --git a/src/components/feature-board-file-element/content/alert/FileAlerts.vue b/src/components/feature-board-file-element/content/alert/FileAlerts.vue index bc14cbd193..81a43c7deb 100644 --- a/src/components/feature-board-file-element/content/alert/FileAlerts.vue +++ b/src/components/feature-board-file-element/content/alert/FileAlerts.vue @@ -4,6 +4,10 @@ {{ t("components.cardElement.fileElement.videoFormatError") }} + + {{ t("components.cardElement.fileElement.audioFormatError") }} + +
{{ t("components.cardElement.fileElement.awaitingScan") }} diff --git a/src/components/feature-board-file-element/content/display/FileDisplay.unit.ts b/src/components/feature-board-file-element/content/display/FileDisplay.unit.ts index 385beeafbd..3e8e6bfb04 100644 --- a/src/components/feature-board-file-element/content/display/FileDisplay.unit.ts +++ b/src/components/feature-board-file-element/content/display/FileDisplay.unit.ts @@ -1,7 +1,8 @@ -import { isVideoMimeType } from "@/utils/fileHelper"; +import { isAudioMimeType, isVideoMimeType } from "@/utils/fileHelper"; import { fileElementResponseFactory } from "@@/tests/test-utils"; import createComponentMocks from "@@/tests/test-utils/componentMocks"; import { shallowMount } from "@vue/test-utils"; +import AudioDisplay from "./audio-display/AudioDisplay.vue"; import FileDescription from "./file-description/FileDescription.vue"; import FileDisplay from "./FileDisplay.vue"; import ImageDisplay from "./image-display/ImageDisplay.vue"; @@ -9,6 +10,7 @@ import VideoDisplay from "./video-display/VideoDisplay.vue"; jest.mock("@/utils/fileHelper"); const isVideoMimeTypeMock = jest.mocked(isVideoMimeType); +const isAudioMimeTypeMock = jest.mocked(isAudioMimeType); describe("FileDisplay", () => { describe("when previewUrl is defined", () => { @@ -65,12 +67,12 @@ describe("FileDisplay", () => { expect(props.element).toBeDefined(); }); - it("should render file description display component", () => { + it("should pass showTitle true to file description", () => { const { wrapper } = setup(); - const fileDescription = wrapper.findComponent(FileDescription); + const props = wrapper.findComponent(FileDescription).attributes(); - expect(fileDescription.exists()).toBe(true); + expect(props.showtitle).toBeFalsy(); }); }); @@ -95,6 +97,9 @@ describe("FileDisplay", () => { isVideoMimeTypeMock.mockReset(); isVideoMimeTypeMock.mockReturnValueOnce(true); + isAudioMimeTypeMock.mockReset(); + isAudioMimeTypeMock.mockReturnValueOnce(false); + const wrapper = shallowMount(FileDisplay, { propsData, ...createComponentMocks({}), @@ -135,6 +140,14 @@ describe("FileDisplay", () => { expect(fileDescription.exists()).toBe(true); }); + + it("should pass showTitle true to file description", () => { + const { wrapper } = setup(); + + const props = wrapper.findComponent(FileDescription).attributes(); + + expect(props.showtitle).toBeFalsy(); + }); }); }); @@ -160,6 +173,9 @@ describe("FileDisplay", () => { isVideoMimeTypeMock.mockReset(); isVideoMimeTypeMock.mockReturnValueOnce(true); + isAudioMimeTypeMock.mockReset(); + isAudioMimeTypeMock.mockReturnValueOnce(false); + const wrapper = shallowMount(FileDisplay, { propsData, ...createComponentMocks({}), @@ -189,9 +205,17 @@ describe("FileDisplay", () => { expect(props.src).toBe(url); expect(props.name).toBe(fileNameProp); }); + + it("should pass showTitle false to file description", () => { + const { wrapper } = setup(); + + const props = wrapper.findComponent(FileDescription).attributes(); + + expect(props.showtitle).toBeFalsy(); + }); }); - describe("when mimeType is not a video type", () => { + describe("when mimeType is a audio type", () => { const setup = () => { document.body.setAttribute("data-app", "true"); @@ -201,7 +225,6 @@ describe("FileDisplay", () => { name: "test", size: 100, url: "test", - previewUrl: undefined, previewStatus: "test", isDownloadAllowed: true, element, @@ -212,6 +235,9 @@ describe("FileDisplay", () => { isVideoMimeTypeMock.mockReset(); isVideoMimeTypeMock.mockReturnValueOnce(false); + isAudioMimeTypeMock.mockReset(); + isAudioMimeTypeMock.mockReturnValueOnce(true); + const wrapper = shallowMount(FileDisplay, { propsData, ...createComponentMocks({}), @@ -220,16 +246,75 @@ describe("FileDisplay", () => { return { wrapper, fileNameProp: propsData.fileProperties.name, - previewUrlProp: propsData.fileProperties.previewUrl, + srcProp: propsData.fileProperties.url, }; }; - it("should render file description display component", () => { + it("should be found in dom", () => { const { wrapper } = setup(); - const fileDescription = wrapper.findComponent(FileDescription); + const fileDisplay = wrapper.findComponent(FileDisplay); - expect(fileDescription.exists()).toBe(true); + expect(fileDisplay.exists()).toBe(true); + }); + + it("should pass correct props to audio display component", () => { + const { wrapper, srcProp } = setup(); + console.log(wrapper.html()); + const props = wrapper.findComponent(AudioDisplay).attributes(); + + expect(props.src).toBe(srcProp); + }); + + it("should pass showTitle false to file description", () => { + const { wrapper } = setup(); + + const props = wrapper.findComponent(FileDescription).attributes(); + + expect(props.showtitle).toBeFalsy(); + }); + }); + + describe("when mimeType is not a video or audio type", () => { + const setup = () => { + document.body.setAttribute("data-app", "true"); + + const element = fileElementResponseFactory.build(); + const propsData = { + fileProperties: { + name: "test", + size: 100, + url: "test", + previewUrl: undefined, + previewStatus: "test", + isDownloadAllowed: true, + element, + }, + isEditMode: true, + }; + + isVideoMimeTypeMock.mockReset(); + isVideoMimeTypeMock.mockReturnValueOnce(false); + + isAudioMimeTypeMock.mockReset(); + isAudioMimeTypeMock.mockReturnValueOnce(false); + + const wrapper = shallowMount(FileDisplay, { + propsData, + ...createComponentMocks({}), + }); + + return { + wrapper, + }; + }; + + it("should pass showTitle true to file description", () => { + const { wrapper } = setup(); + + const props = wrapper.findComponent(FileDescription).attributes(); + + expect(props.showtitle).toBeTruthy(); }); it("should not render image display component", () => { @@ -239,6 +324,22 @@ describe("FileDisplay", () => { expect(imageDisplay.exists()).toBe(false); }); + + it("should not render audio display component", () => { + const { wrapper } = setup(); + + const audioDisplay = wrapper.findComponent(AudioDisplay); + + expect(audioDisplay.exists()).toBe(false); + }); + + it("should not render video display component", () => { + const { wrapper } = setup(); + + const videoDisplay = wrapper.findComponent(VideoDisplay); + + expect(videoDisplay.exists()).toBe(false); + }); }); }); }); diff --git a/src/components/feature-board-file-element/content/display/FileDisplay.vue b/src/components/feature-board-file-element/content/display/FileDisplay.vue index 4c1428bbf3..c2aafb7725 100644 --- a/src/components/feature-board-file-element/content/display/FileDisplay.vue +++ b/src/components/feature-board-file-element/content/display/FileDisplay.vue @@ -18,6 +18,13 @@ > + + + + diff --git a/src/components/feature-board-file-element/shared/types/FileAlert.enum.ts b/src/components/feature-board-file-element/shared/types/FileAlert.enum.ts index 9f9aab29d5..5fe8746ec7 100644 --- a/src/components/feature-board-file-element/shared/types/FileAlert.enum.ts +++ b/src/components/feature-board-file-element/shared/types/FileAlert.enum.ts @@ -1,5 +1,6 @@ export enum FileAlert { VIDEO_FORMAT_ERROR, + AUDIO_FORMAT_ERROR, AWAITING_SCAN_STATUS, SCAN_STATUS_WONT_CHECK, SCAN_STATUS_BLOCKED, diff --git a/src/components/ui-board/content-element/ContentElementBar.unit.ts b/src/components/ui-board/content-element/ContentElementBar.unit.ts index adaed2147e..353260bc22 100644 --- a/src/components/ui-board/content-element/ContentElementBar.unit.ts +++ b/src/components/ui-board/content-element/ContentElementBar.unit.ts @@ -7,18 +7,20 @@ describe("ContentElementBar", () => { icon?: string; hasGreyBackground?: boolean; title?: string; + element?: string; menu?: string; subtitle?: string; }) => { document.body.setAttribute("data-app", "true"); - const { icon, hasGreyBackground, title, menu, subtitle } = props; + const { icon, hasGreyBackground, title, menu, subtitle, element } = props; const propsData = { icon, hasGreyBackground, }; const slots = { title: title ?? "", + element: element ?? "", menu: menu ?? "", subtitle: subtitle ?? "", }; @@ -33,6 +35,7 @@ describe("ContentElementBar", () => { icon, hasGreyBackground, title, + element, menu, subtitle, }; @@ -84,6 +87,18 @@ describe("ContentElementBar", () => { }); }); + describe("when element slot is defined", () => { + it("should render element slot", () => { + const { wrapper, element: elementSlot } = setup({ + element: "test element slot", + }); + + const element = wrapper.text(); + + expect(element).toBe(elementSlot); + }); + }); + describe("when menu slot is defined", () => { it("should render menu slot", () => { const { wrapper, menu } = setup({ diff --git a/src/components/ui-board/content-element/ContentElementBar.vue b/src/components/ui-board/content-element/ContentElementBar.vue index 097c3bbaae..9e3e1b32f9 100644 --- a/src/components/ui-board/content-element/ContentElementBar.vue +++ b/src/components/ui-board/content-element/ContentElementBar.vue @@ -11,6 +11,8 @@ + + diff --git a/src/locales/de.json b/src/locales/de.json index d6e30a7953..f1dc917495 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -827,6 +827,7 @@ "components.cardElement.fileElement.reloadStatus": "Status aktualisieren", "components.cardElement.fileElement.caption": "Beschreibung", "components.cardElement.fileElement.videoFormatError": "Das Videoformat wird von diesem Browser / Betriebssystem nicht unterstützt.", + "components.cardElement.fileElement.audioFormatError": "Das Audioformat wird von diesem Browser / Betriebssystem nicht unterstützt.", "components.cardElement.richTextElement": "Textelement", "components.cardElement.richTextElement.placeholder": "Text hinzufügen", "components.cardElement.submissionElement": "Abgabe", diff --git a/src/locales/en.json b/src/locales/en.json index d6a7846d6d..b5dce737f4 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -825,6 +825,7 @@ "components.cardElement.fileElement.scanWontCheck": "Due to the size, no preview can be generated.", "components.cardElement.fileElement.caption": "Caption", "components.cardElement.fileElement.videoFormatError": "The video format is not supported by this browser/operating system.", + "components.cardElement.fileElement.audioFormatError": "The audio format is not supported by this browser/operating system.", "components.cardElement.richTextElement": "Text element", "components.cardElement.richTextElement.placeholder": "Add text", "components.cardElement.submissionElement": "Submission", diff --git a/src/locales/es.json b/src/locales/es.json index 9c5208bd18..036dde82de 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -835,6 +835,7 @@ "components.cardElement.fileElement.reloadStatus": "Estado de actualización", "components.cardElement.fileElement.caption": "Descripción", "components.cardElement.fileElement.videoFormatError": "El formato de vídeo no es compatible con este navegador / sistema operativo.", + "components.cardElement.fileElement.audioFormatError": "El formato de audio no es compatible con este navegador / sistema operativo.", "components.cardElement.richTextElement": "Elemento texto", "components.cardElement.richTextElement.placeholder": "Añadir texto", "components.cardElement.submissionElement": "Envío", diff --git a/src/locales/uk.json b/src/locales/uk.json index 786dd23af7..7b7bc2aa91 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -332,6 +332,7 @@ "components.cardElement.fileElement.reloadStatus": "Статус оновлення", "components.cardElement.fileElement.caption": "опис", "components.cardElement.fileElement.videoFormatError": "Формат відео не підтримується цим браузером / операційною системою.", + "components.cardElement.fileElement.audioFormatError": "Формат аудіо не підтримується цим браузером / операційною системою.", "components.cardElement.richTextElement": "Текстовий елемент", "components.cardElement.richTextElement.placeholder": "додати текст", "components.cardElement.submissionElement": "Подання", diff --git a/src/utils/fileHelper.ts b/src/utils/fileHelper.ts index a05f24f05f..fb18d57216 100644 --- a/src/utils/fileHelper.ts +++ b/src/utils/fileHelper.ts @@ -80,3 +80,7 @@ export function isVideoMimeType(mimeType: string): boolean { mimeType === "application/ogg" ); } + +export function isAudioMimeType(mimeType: string): boolean { + return mimeType.startsWith("audio/"); +} diff --git a/src/utils/fileHelper.unit.ts b/src/utils/fileHelper.unit.ts index 02ca1683a1..bcb121cbbe 100644 --- a/src/utils/fileHelper.unit.ts +++ b/src/utils/fileHelper.unit.ts @@ -8,6 +8,7 @@ import { convertFileSize, downloadFile, getFileExtension, + isAudioMimeType, isDownloadAllowed, isPreviewPossible, isVideoMimeType, @@ -378,4 +379,54 @@ describe("@/utils/fileHelper", () => { }); }); }); + + describe("isAudioMimeType", () => { + describe("when file has audio mime type", () => { + describe("when file mime type has audio/ prefix", () => { + it("should return true", () => { + const result = isAudioMimeType("audio/mp4"); + + expect(result).toBe(true); + }); + + it("should return true", () => { + const result = isAudioMimeType("audio/"); + + expect(result).toBe(true); + }); + + it("should return true", () => { + const result = isAudioMimeType("audio/ "); + + expect(result).toBe(true); + }); + }); + }); + + describe("when file has no audio mime type", () => { + it("should return false", () => { + const result = isAudioMimeType("image/png"); + + expect(result).toBe(false); + }); + + it("should return false", () => { + const result = isAudioMimeType("application/"); + + expect(result).toBe(false); + }); + + it("should return false", () => { + const result = isAudioMimeType(" "); + + expect(result).toBe(false); + }); + + it("should return false", () => { + const result = isAudioMimeType(""); + + expect(result).toBe(false); + }); + }); + }); });