ai 6.0.33 → 6.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/docs/02-foundations/03-prompts.mdx +2 -2
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/28-output.mdx +1 -1
- package/package.json +6 -4
- package/src/agent/agent.ts +116 -0
- package/src/agent/create-agent-ui-stream-response.test.ts +258 -0
- package/src/agent/create-agent-ui-stream-response.ts +50 -0
- package/src/agent/create-agent-ui-stream.ts +73 -0
- package/src/agent/index.ts +33 -0
- package/src/agent/infer-agent-tools.ts +7 -0
- package/src/agent/infer-agent-ui-message.test-d.ts +54 -0
- package/src/agent/infer-agent-ui-message.ts +11 -0
- package/src/agent/pipe-agent-ui-stream-to-response.ts +52 -0
- package/src/agent/tool-loop-agent-on-finish-callback.ts +31 -0
- package/src/agent/tool-loop-agent-on-step-finish-callback.ts +11 -0
- package/src/agent/tool-loop-agent-settings.ts +182 -0
- package/src/agent/tool-loop-agent.test-d.ts +114 -0
- package/src/agent/tool-loop-agent.test.ts +442 -0
- package/src/agent/tool-loop-agent.ts +114 -0
- package/src/embed/__snapshots__/embed-many.test.ts.snap +191 -0
- package/src/embed/__snapshots__/embed.test.ts.snap +81 -0
- package/src/embed/embed-many-result.ts +53 -0
- package/src/embed/embed-many.test.ts +653 -0
- package/src/embed/embed-many.ts +378 -0
- package/src/embed/embed-result.ts +50 -0
- package/src/embed/embed.test.ts +298 -0
- package/src/embed/embed.ts +211 -0
- package/src/embed/index.ts +4 -0
- package/src/error/index.ts +34 -0
- package/src/error/invalid-argument-error.ts +34 -0
- package/src/error/invalid-stream-part-error.ts +28 -0
- package/src/error/invalid-tool-approval-error.ts +26 -0
- package/src/error/invalid-tool-input-error.ts +33 -0
- package/src/error/no-image-generated-error.ts +39 -0
- package/src/error/no-object-generated-error.ts +70 -0
- package/src/error/no-output-generated-error.ts +26 -0
- package/src/error/no-speech-generated-error.ts +18 -0
- package/src/error/no-such-tool-error.ts +35 -0
- package/src/error/no-transcript-generated-error.ts +20 -0
- package/src/error/tool-call-not-found-for-approval-error.ts +32 -0
- package/src/error/tool-call-repair-error.ts +30 -0
- package/src/error/unsupported-model-version-error.ts +23 -0
- package/src/error/verify-no-object-generated-error.ts +27 -0
- package/src/generate-image/generate-image-result.ts +42 -0
- package/src/generate-image/generate-image.test.ts +1420 -0
- package/src/generate-image/generate-image.ts +360 -0
- package/src/generate-image/index.ts +18 -0
- package/src/generate-object/__snapshots__/generate-object.test.ts.snap +133 -0
- package/src/generate-object/__snapshots__/stream-object.test.ts.snap +297 -0
- package/src/generate-object/generate-object-result.ts +67 -0
- package/src/generate-object/generate-object.test-d.ts +49 -0
- package/src/generate-object/generate-object.test.ts +1191 -0
- package/src/generate-object/generate-object.ts +518 -0
- package/src/generate-object/index.ts +9 -0
- package/src/generate-object/inject-json-instruction.test.ts +181 -0
- package/src/generate-object/inject-json-instruction.ts +30 -0
- package/src/generate-object/output-strategy.ts +415 -0
- package/src/generate-object/parse-and-validate-object-result.ts +111 -0
- package/src/generate-object/repair-text.ts +12 -0
- package/src/generate-object/stream-object-result.ts +120 -0
- package/src/generate-object/stream-object.test-d.ts +74 -0
- package/src/generate-object/stream-object.test.ts +1950 -0
- package/src/generate-object/stream-object.ts +986 -0
- package/src/generate-object/validate-object-generation-input.ts +144 -0
- package/src/generate-speech/generate-speech-result.ts +30 -0
- package/src/generate-speech/generate-speech.test.ts +300 -0
- package/src/generate-speech/generate-speech.ts +190 -0
- package/src/generate-speech/generated-audio-file.ts +65 -0
- package/src/generate-speech/index.ts +3 -0
- package/src/generate-text/__snapshots__/generate-text.test.ts.snap +1872 -0
- package/src/generate-text/__snapshots__/stream-text.test.ts.snap +1255 -0
- package/src/generate-text/collect-tool-approvals.test.ts +553 -0
- package/src/generate-text/collect-tool-approvals.ts +116 -0
- package/src/generate-text/content-part.ts +25 -0
- package/src/generate-text/execute-tool-call.ts +129 -0
- package/src/generate-text/extract-reasoning-content.ts +17 -0
- package/src/generate-text/extract-text-content.ts +15 -0
- package/src/generate-text/generate-text-result.ts +168 -0
- package/src/generate-text/generate-text.test-d.ts +68 -0
- package/src/generate-text/generate-text.test.ts +7011 -0
- package/src/generate-text/generate-text.ts +1223 -0
- package/src/generate-text/generated-file.ts +70 -0
- package/src/generate-text/index.ts +57 -0
- package/src/generate-text/is-approval-needed.ts +29 -0
- package/src/generate-text/output-utils.ts +23 -0
- package/src/generate-text/output.test.ts +698 -0
- package/src/generate-text/output.ts +590 -0
- package/src/generate-text/parse-tool-call.test.ts +570 -0
- package/src/generate-text/parse-tool-call.ts +188 -0
- package/src/generate-text/prepare-step.ts +103 -0
- package/src/generate-text/prune-messages.test.ts +720 -0
- package/src/generate-text/prune-messages.ts +167 -0
- package/src/generate-text/reasoning-output.ts +20 -0
- package/src/generate-text/reasoning.ts +8 -0
- package/src/generate-text/response-message.ts +10 -0
- package/src/generate-text/run-tools-transformation.test.ts +1143 -0
- package/src/generate-text/run-tools-transformation.ts +420 -0
- package/src/generate-text/smooth-stream.test.ts +2101 -0
- package/src/generate-text/smooth-stream.ts +162 -0
- package/src/generate-text/step-result.ts +238 -0
- package/src/generate-text/stop-condition.ts +29 -0
- package/src/generate-text/stream-text-result.ts +463 -0
- package/src/generate-text/stream-text.test-d.ts +200 -0
- package/src/generate-text/stream-text.test.ts +19979 -0
- package/src/generate-text/stream-text.ts +2505 -0
- package/src/generate-text/to-response-messages.test.ts +922 -0
- package/src/generate-text/to-response-messages.ts +163 -0
- package/src/generate-text/tool-approval-request-output.ts +21 -0
- package/src/generate-text/tool-call-repair-function.ts +27 -0
- package/src/generate-text/tool-call.ts +47 -0
- package/src/generate-text/tool-error.ts +34 -0
- package/src/generate-text/tool-output-denied.ts +21 -0
- package/src/generate-text/tool-output.ts +7 -0
- package/src/generate-text/tool-result.ts +36 -0
- package/src/generate-text/tool-set.ts +14 -0
- package/src/global.ts +24 -0
- package/src/index.ts +50 -0
- package/src/logger/index.ts +6 -0
- package/src/logger/log-warnings.test.ts +351 -0
- package/src/logger/log-warnings.ts +119 -0
- package/src/middleware/__snapshots__/simulate-streaming-middleware.test.ts.snap +64 -0
- package/src/middleware/add-tool-input-examples-middleware.test.ts +476 -0
- package/src/middleware/add-tool-input-examples-middleware.ts +90 -0
- package/src/middleware/default-embedding-settings-middleware.test.ts +126 -0
- package/src/middleware/default-embedding-settings-middleware.ts +22 -0
- package/src/middleware/default-settings-middleware.test.ts +388 -0
- package/src/middleware/default-settings-middleware.ts +33 -0
- package/src/middleware/extract-json-middleware.test.ts +827 -0
- package/src/middleware/extract-json-middleware.ts +197 -0
- package/src/middleware/extract-reasoning-middleware.test.ts +1028 -0
- package/src/middleware/extract-reasoning-middleware.ts +238 -0
- package/src/middleware/index.ts +10 -0
- package/src/middleware/simulate-streaming-middleware.test.ts +911 -0
- package/src/middleware/simulate-streaming-middleware.ts +79 -0
- package/src/middleware/wrap-embedding-model.test.ts +358 -0
- package/src/middleware/wrap-embedding-model.ts +86 -0
- package/src/middleware/wrap-image-model.test.ts +423 -0
- package/src/middleware/wrap-image-model.ts +85 -0
- package/src/middleware/wrap-language-model.test.ts +518 -0
- package/src/middleware/wrap-language-model.ts +104 -0
- package/src/middleware/wrap-provider.test.ts +120 -0
- package/src/middleware/wrap-provider.ts +51 -0
- package/src/model/as-embedding-model-v3.test.ts +319 -0
- package/src/model/as-embedding-model-v3.ts +24 -0
- package/src/model/as-image-model-v3.test.ts +409 -0
- package/src/model/as-image-model-v3.ts +24 -0
- package/src/model/as-language-model-v3.test.ts +508 -0
- package/src/model/as-language-model-v3.ts +103 -0
- package/src/model/as-provider-v3.ts +36 -0
- package/src/model/as-speech-model-v3.test.ts +356 -0
- package/src/model/as-speech-model-v3.ts +24 -0
- package/src/model/as-transcription-model-v3.test.ts +529 -0
- package/src/model/as-transcription-model-v3.ts +24 -0
- package/src/model/resolve-model.test.ts +244 -0
- package/src/model/resolve-model.ts +126 -0
- package/src/prompt/call-settings.ts +148 -0
- package/src/prompt/content-part.ts +209 -0
- package/src/prompt/convert-to-language-model-prompt.test.ts +2018 -0
- package/src/prompt/convert-to-language-model-prompt.ts +442 -0
- package/src/prompt/create-tool-model-output.test.ts +508 -0
- package/src/prompt/create-tool-model-output.ts +34 -0
- package/src/prompt/data-content.test.ts +15 -0
- package/src/prompt/data-content.ts +134 -0
- package/src/prompt/index.ts +27 -0
- package/src/prompt/invalid-data-content-error.ts +29 -0
- package/src/prompt/invalid-message-role-error.ts +27 -0
- package/src/prompt/message-conversion-error.ts +28 -0
- package/src/prompt/message.ts +68 -0
- package/src/prompt/prepare-call-settings.test.ts +159 -0
- package/src/prompt/prepare-call-settings.ts +108 -0
- package/src/prompt/prepare-tools-and-tool-choice.test.ts +461 -0
- package/src/prompt/prepare-tools-and-tool-choice.ts +86 -0
- package/src/prompt/prompt.ts +43 -0
- package/src/prompt/split-data-url.ts +17 -0
- package/src/prompt/standardize-prompt.test.ts +82 -0
- package/src/prompt/standardize-prompt.ts +99 -0
- package/src/prompt/wrap-gateway-error.ts +29 -0
- package/src/registry/custom-provider.test.ts +211 -0
- package/src/registry/custom-provider.ts +155 -0
- package/src/registry/index.ts +7 -0
- package/src/registry/no-such-provider-error.ts +41 -0
- package/src/registry/provider-registry.test.ts +691 -0
- package/src/registry/provider-registry.ts +328 -0
- package/src/rerank/index.ts +2 -0
- package/src/rerank/rerank-result.ts +70 -0
- package/src/rerank/rerank.test.ts +516 -0
- package/src/rerank/rerank.ts +237 -0
- package/src/telemetry/assemble-operation-name.ts +21 -0
- package/src/telemetry/get-base-telemetry-attributes.ts +53 -0
- package/src/telemetry/get-tracer.ts +20 -0
- package/src/telemetry/noop-tracer.ts +69 -0
- package/src/telemetry/record-span.ts +63 -0
- package/src/telemetry/select-telemetry-attributes.ts +78 -0
- package/src/telemetry/select-temetry-attributes.test.ts +114 -0
- package/src/telemetry/stringify-for-telemetry.test.ts +114 -0
- package/src/telemetry/stringify-for-telemetry.ts +33 -0
- package/src/telemetry/telemetry-settings.ts +44 -0
- package/src/test/mock-embedding-model-v2.ts +35 -0
- package/src/test/mock-embedding-model-v3.ts +48 -0
- package/src/test/mock-image-model-v2.ts +28 -0
- package/src/test/mock-image-model-v3.ts +28 -0
- package/src/test/mock-language-model-v2.ts +72 -0
- package/src/test/mock-language-model-v3.ts +77 -0
- package/src/test/mock-provider-v2.ts +68 -0
- package/src/test/mock-provider-v3.ts +80 -0
- package/src/test/mock-reranking-model-v3.ts +25 -0
- package/src/test/mock-server-response.ts +69 -0
- package/src/test/mock-speech-model-v2.ts +24 -0
- package/src/test/mock-speech-model-v3.ts +24 -0
- package/src/test/mock-tracer.ts +156 -0
- package/src/test/mock-transcription-model-v2.ts +24 -0
- package/src/test/mock-transcription-model-v3.ts +24 -0
- package/src/test/mock-values.ts +4 -0
- package/src/test/not-implemented.ts +3 -0
- package/src/text-stream/create-text-stream-response.test.ts +38 -0
- package/src/text-stream/create-text-stream-response.ts +18 -0
- package/src/text-stream/index.ts +2 -0
- package/src/text-stream/pipe-text-stream-to-response.test.ts +38 -0
- package/src/text-stream/pipe-text-stream-to-response.ts +26 -0
- package/src/transcribe/index.ts +2 -0
- package/src/transcribe/transcribe-result.ts +60 -0
- package/src/transcribe/transcribe.test.ts +313 -0
- package/src/transcribe/transcribe.ts +173 -0
- package/src/types/embedding-model-middleware.ts +3 -0
- package/src/types/embedding-model.ts +18 -0
- package/src/types/image-model-middleware.ts +3 -0
- package/src/types/image-model-response-metadata.ts +16 -0
- package/src/types/image-model.ts +19 -0
- package/src/types/index.ts +29 -0
- package/src/types/json-value.ts +15 -0
- package/src/types/language-model-middleware.ts +3 -0
- package/src/types/language-model-request-metadata.ts +6 -0
- package/src/types/language-model-response-metadata.ts +21 -0
- package/src/types/language-model.ts +104 -0
- package/src/types/provider-metadata.ts +16 -0
- package/src/types/provider.ts +55 -0
- package/src/types/reranking-model.ts +6 -0
- package/src/types/speech-model-response-metadata.ts +21 -0
- package/src/types/speech-model.ts +6 -0
- package/src/types/transcription-model-response-metadata.ts +16 -0
- package/src/types/transcription-model.ts +9 -0
- package/src/types/usage.ts +200 -0
- package/src/types/warning.ts +7 -0
- package/src/ui/__snapshots__/append-response-messages.test.ts.snap +416 -0
- package/src/ui/__snapshots__/convert-to-model-messages.test.ts.snap +419 -0
- package/src/ui/__snapshots__/process-chat-text-response.test.ts.snap +142 -0
- package/src/ui/call-completion-api.ts +157 -0
- package/src/ui/chat-transport.ts +83 -0
- package/src/ui/chat.test-d.ts +233 -0
- package/src/ui/chat.test.ts +2695 -0
- package/src/ui/chat.ts +716 -0
- package/src/ui/convert-file-list-to-file-ui-parts.ts +36 -0
- package/src/ui/convert-to-model-messages.test.ts +2775 -0
- package/src/ui/convert-to-model-messages.ts +373 -0
- package/src/ui/default-chat-transport.ts +36 -0
- package/src/ui/direct-chat-transport.test.ts +446 -0
- package/src/ui/direct-chat-transport.ts +118 -0
- package/src/ui/http-chat-transport.test.ts +185 -0
- package/src/ui/http-chat-transport.ts +292 -0
- package/src/ui/index.ts +71 -0
- package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +44 -0
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.test.ts +371 -0
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +39 -0
- package/src/ui/process-text-stream.test.ts +38 -0
- package/src/ui/process-text-stream.ts +16 -0
- package/src/ui/process-ui-message-stream.test.ts +8052 -0
- package/src/ui/process-ui-message-stream.ts +713 -0
- package/src/ui/text-stream-chat-transport.ts +23 -0
- package/src/ui/transform-text-to-ui-message-stream.test.ts +124 -0
- package/src/ui/transform-text-to-ui-message-stream.ts +27 -0
- package/src/ui/ui-messages.test.ts +48 -0
- package/src/ui/ui-messages.ts +534 -0
- package/src/ui/use-completion.ts +84 -0
- package/src/ui/validate-ui-messages.test.ts +1428 -0
- package/src/ui/validate-ui-messages.ts +476 -0
- package/src/ui-message-stream/create-ui-message-stream-response.test.ts +266 -0
- package/src/ui-message-stream/create-ui-message-stream-response.ts +32 -0
- package/src/ui-message-stream/create-ui-message-stream.test.ts +639 -0
- package/src/ui-message-stream/create-ui-message-stream.ts +124 -0
- package/src/ui-message-stream/get-response-ui-message-id.test.ts +55 -0
- package/src/ui-message-stream/get-response-ui-message-id.ts +24 -0
- package/src/ui-message-stream/handle-ui-message-stream-finish.test.ts +429 -0
- package/src/ui-message-stream/handle-ui-message-stream-finish.ts +135 -0
- package/src/ui-message-stream/index.ts +13 -0
- package/src/ui-message-stream/json-to-sse-transform-stream.ts +12 -0
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.test.ts +90 -0
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +40 -0
- package/src/ui-message-stream/read-ui-message-stream.test.ts +122 -0
- package/src/ui-message-stream/read-ui-message-stream.ts +87 -0
- package/src/ui-message-stream/ui-message-chunks.test-d.ts +18 -0
- package/src/ui-message-stream/ui-message-chunks.ts +344 -0
- package/src/ui-message-stream/ui-message-stream-headers.ts +7 -0
- package/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +32 -0
- package/src/ui-message-stream/ui-message-stream-response-init.ts +5 -0
- package/src/ui-message-stream/ui-message-stream-writer.ts +24 -0
- package/src/util/as-array.ts +3 -0
- package/src/util/async-iterable-stream.test.ts +241 -0
- package/src/util/async-iterable-stream.ts +94 -0
- package/src/util/consume-stream.ts +29 -0
- package/src/util/cosine-similarity.test.ts +57 -0
- package/src/util/cosine-similarity.ts +47 -0
- package/src/util/create-resolvable-promise.ts +30 -0
- package/src/util/create-stitchable-stream.test.ts +239 -0
- package/src/util/create-stitchable-stream.ts +112 -0
- package/src/util/data-url.ts +17 -0
- package/src/util/deep-partial.ts +84 -0
- package/src/util/detect-media-type.test.ts +670 -0
- package/src/util/detect-media-type.ts +184 -0
- package/src/util/download/download-function.ts +45 -0
- package/src/util/download/download.test.ts +69 -0
- package/src/util/download/download.ts +46 -0
- package/src/util/error-handler.ts +1 -0
- package/src/util/fix-json.test.ts +279 -0
- package/src/util/fix-json.ts +401 -0
- package/src/util/get-potential-start-index.test.ts +34 -0
- package/src/util/get-potential-start-index.ts +30 -0
- package/src/util/index.ts +11 -0
- package/src/util/is-deep-equal-data.test.ts +119 -0
- package/src/util/is-deep-equal-data.ts +48 -0
- package/src/util/is-non-empty-object.ts +5 -0
- package/src/util/job.ts +1 -0
- package/src/util/log-v2-compatibility-warning.ts +21 -0
- package/src/util/merge-abort-signals.test.ts +155 -0
- package/src/util/merge-abort-signals.ts +43 -0
- package/src/util/merge-objects.test.ts +118 -0
- package/src/util/merge-objects.ts +79 -0
- package/src/util/now.ts +4 -0
- package/src/util/parse-partial-json.test.ts +80 -0
- package/src/util/parse-partial-json.ts +30 -0
- package/src/util/prepare-headers.test.ts +51 -0
- package/src/util/prepare-headers.ts +14 -0
- package/src/util/prepare-retries.test.ts +10 -0
- package/src/util/prepare-retries.ts +47 -0
- package/src/util/retry-error.ts +41 -0
- package/src/util/retry-with-exponential-backoff.test.ts +446 -0
- package/src/util/retry-with-exponential-backoff.ts +154 -0
- package/src/util/serial-job-executor.test.ts +162 -0
- package/src/util/serial-job-executor.ts +36 -0
- package/src/util/simulate-readable-stream.test.ts +98 -0
- package/src/util/simulate-readable-stream.ts +39 -0
- package/src/util/split-array.test.ts +60 -0
- package/src/util/split-array.ts +20 -0
- package/src/util/value-of.ts +65 -0
- package/src/util/write-to-server-response.test.ts +266 -0
- package/src/util/write-to-server-response.ts +49 -0
- package/src/version.ts +5 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
audioMediaTypeSignatures,
|
|
4
|
+
detectMediaType,
|
|
5
|
+
imageMediaTypeSignatures,
|
|
6
|
+
} from './detect-media-type';
|
|
7
|
+
import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils';
|
|
8
|
+
|
|
9
|
+
describe('detectMediaType', () => {
|
|
10
|
+
describe('GIF', () => {
|
|
11
|
+
it('should detect GIF from bytes', () => {
|
|
12
|
+
const gifBytes = new Uint8Array([0x47, 0x49, 0x46, 0xff, 0xff]);
|
|
13
|
+
expect(
|
|
14
|
+
detectMediaType({
|
|
15
|
+
data: gifBytes,
|
|
16
|
+
signatures: imageMediaTypeSignatures,
|
|
17
|
+
}),
|
|
18
|
+
).toBe('image/gif');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should detect GIF from base64', () => {
|
|
22
|
+
const gifBase64 = 'R0lGabc123'; // Base64 string starting with GIF signature
|
|
23
|
+
expect(
|
|
24
|
+
detectMediaType({
|
|
25
|
+
data: gifBase64,
|
|
26
|
+
signatures: imageMediaTypeSignatures,
|
|
27
|
+
}),
|
|
28
|
+
).toBe('image/gif');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('PNG', () => {
|
|
33
|
+
it('should detect PNG from bytes', () => {
|
|
34
|
+
const pngBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0xff, 0xff]);
|
|
35
|
+
expect(
|
|
36
|
+
detectMediaType({
|
|
37
|
+
data: pngBytes,
|
|
38
|
+
signatures: imageMediaTypeSignatures,
|
|
39
|
+
}),
|
|
40
|
+
).toBe('image/png');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should detect PNG from base64', () => {
|
|
44
|
+
const pngBase64 = 'iVBORwabc123'; // Base64 string starting with PNG signature
|
|
45
|
+
expect(
|
|
46
|
+
detectMediaType({
|
|
47
|
+
data: pngBase64,
|
|
48
|
+
signatures: imageMediaTypeSignatures,
|
|
49
|
+
}),
|
|
50
|
+
).toBe('image/png');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('JPEG', () => {
|
|
55
|
+
it('should detect JPEG from bytes', () => {
|
|
56
|
+
const jpegBytes = new Uint8Array([0xff, 0xd8, 0xff, 0xff]);
|
|
57
|
+
expect(
|
|
58
|
+
detectMediaType({
|
|
59
|
+
data: jpegBytes,
|
|
60
|
+
signatures: imageMediaTypeSignatures,
|
|
61
|
+
}),
|
|
62
|
+
).toBe('image/jpeg');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should detect JPEG from base64', () => {
|
|
66
|
+
const jpegBase64 = '/9j/abc123'; // Base64 string starting with JPEG signature
|
|
67
|
+
expect(
|
|
68
|
+
detectMediaType({
|
|
69
|
+
data: jpegBase64,
|
|
70
|
+
signatures: imageMediaTypeSignatures,
|
|
71
|
+
}),
|
|
72
|
+
).toBe('image/jpeg');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('WebP', () => {
|
|
77
|
+
it('should detect WebP from bytes (positive webp image uint8)', () => {
|
|
78
|
+
// WebP format: RIFF + 4 bytes file size + WEBP
|
|
79
|
+
const webpBytes = new Uint8Array([
|
|
80
|
+
0x52,
|
|
81
|
+
0x49,
|
|
82
|
+
0x46,
|
|
83
|
+
0x46, // "RIFF"
|
|
84
|
+
0x24,
|
|
85
|
+
0x00,
|
|
86
|
+
0x00,
|
|
87
|
+
0x00, // file size (example: 36 bytes)
|
|
88
|
+
0x57,
|
|
89
|
+
0x45,
|
|
90
|
+
0x42,
|
|
91
|
+
0x50, // "WEBP"
|
|
92
|
+
0x56,
|
|
93
|
+
0x50,
|
|
94
|
+
0x38,
|
|
95
|
+
0x20, // VP8 chunk (additional WebP data)
|
|
96
|
+
]);
|
|
97
|
+
expect(
|
|
98
|
+
detectMediaType({
|
|
99
|
+
data: webpBytes,
|
|
100
|
+
signatures: imageMediaTypeSignatures,
|
|
101
|
+
}),
|
|
102
|
+
).toBe('image/webp');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should detect WebP from base64 (positive webp image base64)', () => {
|
|
106
|
+
// WebP: RIFF + file size + WEBP encoded to base64
|
|
107
|
+
const webpBytes = new Uint8Array([
|
|
108
|
+
0x52,
|
|
109
|
+
0x49,
|
|
110
|
+
0x46,
|
|
111
|
+
0x46, // "RIFF"
|
|
112
|
+
0x24,
|
|
113
|
+
0x00,
|
|
114
|
+
0x00,
|
|
115
|
+
0x00, // file size
|
|
116
|
+
0x57,
|
|
117
|
+
0x45,
|
|
118
|
+
0x42,
|
|
119
|
+
0x50, // "WEBP"
|
|
120
|
+
0x56,
|
|
121
|
+
0x50,
|
|
122
|
+
0x38,
|
|
123
|
+
0x20, // VP8 chunk
|
|
124
|
+
]);
|
|
125
|
+
const webpBase64 = convertUint8ArrayToBase64(webpBytes);
|
|
126
|
+
expect(
|
|
127
|
+
detectMediaType({
|
|
128
|
+
data: webpBase64,
|
|
129
|
+
signatures: imageMediaTypeSignatures,
|
|
130
|
+
}),
|
|
131
|
+
).toBe('image/webp');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should NOT detect RIFF audio as WebP from bytes (negative riff audio uint8)', () => {
|
|
135
|
+
// WAV format: RIFF + file size + WAVE (not WEBP)
|
|
136
|
+
const wavBytes = new Uint8Array([
|
|
137
|
+
0x52,
|
|
138
|
+
0x49,
|
|
139
|
+
0x46,
|
|
140
|
+
0x46, // "RIFF"
|
|
141
|
+
0x24,
|
|
142
|
+
0x00,
|
|
143
|
+
0x00,
|
|
144
|
+
0x00, // file size
|
|
145
|
+
0x57,
|
|
146
|
+
0x41,
|
|
147
|
+
0x56,
|
|
148
|
+
0x45, // "WAVE" (not "WEBP")
|
|
149
|
+
0x66,
|
|
150
|
+
0x6d,
|
|
151
|
+
0x74,
|
|
152
|
+
0x20, // fmt chunk
|
|
153
|
+
]);
|
|
154
|
+
expect(
|
|
155
|
+
detectMediaType({
|
|
156
|
+
data: wavBytes,
|
|
157
|
+
signatures: imageMediaTypeSignatures,
|
|
158
|
+
}),
|
|
159
|
+
).toBeUndefined(); // Should not detect as WebP
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should NOT detect RIFF audio as WebP from base64 (negative riff audio base64)', () => {
|
|
163
|
+
// WAV format encoded to base64
|
|
164
|
+
const wavBytes = new Uint8Array([
|
|
165
|
+
0x52,
|
|
166
|
+
0x49,
|
|
167
|
+
0x46,
|
|
168
|
+
0x46, // "RIFF"
|
|
169
|
+
0x24,
|
|
170
|
+
0x00,
|
|
171
|
+
0x00,
|
|
172
|
+
0x00, // file size
|
|
173
|
+
0x57,
|
|
174
|
+
0x41,
|
|
175
|
+
0x56,
|
|
176
|
+
0x45, // "WAVE" (not "WEBP")
|
|
177
|
+
0x66,
|
|
178
|
+
0x6d,
|
|
179
|
+
0x74,
|
|
180
|
+
0x20, // fmt chunk
|
|
181
|
+
]);
|
|
182
|
+
const wavBase64 = convertUint8ArrayToBase64(wavBytes);
|
|
183
|
+
expect(
|
|
184
|
+
detectMediaType({
|
|
185
|
+
data: wavBase64,
|
|
186
|
+
signatures: imageMediaTypeSignatures,
|
|
187
|
+
}),
|
|
188
|
+
).toBeUndefined(); // Should not detect as WebP
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('BMP', () => {
|
|
193
|
+
it('should detect BMP from bytes', () => {
|
|
194
|
+
const bmpBytes = new Uint8Array([0x42, 0x4d, 0xff, 0xff]);
|
|
195
|
+
expect(
|
|
196
|
+
detectMediaType({
|
|
197
|
+
data: bmpBytes,
|
|
198
|
+
signatures: imageMediaTypeSignatures,
|
|
199
|
+
}),
|
|
200
|
+
).toBe('image/bmp');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should detect BMP from base64', () => {
|
|
204
|
+
const bmpBytes = new Uint8Array([0x42, 0x4d, 0xff, 0xff]);
|
|
205
|
+
expect(
|
|
206
|
+
detectMediaType({
|
|
207
|
+
data: convertUint8ArrayToBase64(bmpBytes),
|
|
208
|
+
signatures: imageMediaTypeSignatures,
|
|
209
|
+
}),
|
|
210
|
+
).toBe('image/bmp');
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('TIFF', () => {
|
|
215
|
+
it('should detect TIFF (little endian) from bytes', () => {
|
|
216
|
+
const tiffLEBytes = new Uint8Array([0x49, 0x49, 0x2a, 0x00, 0xff]);
|
|
217
|
+
expect(
|
|
218
|
+
detectMediaType({
|
|
219
|
+
data: tiffLEBytes,
|
|
220
|
+
signatures: imageMediaTypeSignatures,
|
|
221
|
+
}),
|
|
222
|
+
).toBe('image/tiff');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should detect TIFF (little endian) from base64', () => {
|
|
226
|
+
const tiffLEBase64 = 'SUkqAAabc123'; // Base64 string starting with TIFF LE signature
|
|
227
|
+
expect(
|
|
228
|
+
detectMediaType({
|
|
229
|
+
data: tiffLEBase64,
|
|
230
|
+
signatures: imageMediaTypeSignatures,
|
|
231
|
+
}),
|
|
232
|
+
).toBe('image/tiff');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should detect TIFF (big endian) from bytes', () => {
|
|
236
|
+
const tiffBEBytes = new Uint8Array([0x4d, 0x4d, 0x00, 0x2a, 0xff]);
|
|
237
|
+
expect(
|
|
238
|
+
detectMediaType({
|
|
239
|
+
data: tiffBEBytes,
|
|
240
|
+
signatures: imageMediaTypeSignatures,
|
|
241
|
+
}),
|
|
242
|
+
).toBe('image/tiff');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should detect TIFF (big endian) from base64', () => {
|
|
246
|
+
const tiffBEBase64 = 'TU0AKgabc123'; // Base64 string starting with TIFF BE signature
|
|
247
|
+
expect(
|
|
248
|
+
detectMediaType({
|
|
249
|
+
data: tiffBEBase64,
|
|
250
|
+
signatures: imageMediaTypeSignatures,
|
|
251
|
+
}),
|
|
252
|
+
).toBe('image/tiff');
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe('AVIF', () => {
|
|
257
|
+
it('should detect AVIF from bytes', () => {
|
|
258
|
+
const avifBytes = new Uint8Array([
|
|
259
|
+
0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66,
|
|
260
|
+
0xff,
|
|
261
|
+
]);
|
|
262
|
+
expect(
|
|
263
|
+
detectMediaType({
|
|
264
|
+
data: avifBytes,
|
|
265
|
+
signatures: imageMediaTypeSignatures,
|
|
266
|
+
}),
|
|
267
|
+
).toBe('image/avif');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should detect AVIF from base64', () => {
|
|
271
|
+
const avifBase64 = 'AAAAIGZ0eXBhdmlmabc123'; // Base64 string starting with AVIF signature
|
|
272
|
+
expect(
|
|
273
|
+
detectMediaType({
|
|
274
|
+
data: avifBase64,
|
|
275
|
+
signatures: imageMediaTypeSignatures,
|
|
276
|
+
}),
|
|
277
|
+
).toBe('image/avif');
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
describe('HEIC', () => {
|
|
282
|
+
it('should detect HEIC from bytes', () => {
|
|
283
|
+
const heicBytes = new Uint8Array([
|
|
284
|
+
0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63,
|
|
285
|
+
0xff,
|
|
286
|
+
]);
|
|
287
|
+
expect(
|
|
288
|
+
detectMediaType({
|
|
289
|
+
data: heicBytes,
|
|
290
|
+
signatures: imageMediaTypeSignatures,
|
|
291
|
+
}),
|
|
292
|
+
).toBe('image/heic');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should detect HEIC from base64', () => {
|
|
296
|
+
const heicBase64 = 'AAAAIGZ0eXBoZWljabc123'; // Base64 string starting with HEIC signature
|
|
297
|
+
expect(
|
|
298
|
+
detectMediaType({
|
|
299
|
+
data: heicBase64,
|
|
300
|
+
signatures: imageMediaTypeSignatures,
|
|
301
|
+
}),
|
|
302
|
+
).toBe('image/heic');
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
describe('MP3', () => {
|
|
307
|
+
it('should detect MP3 from bytes', () => {
|
|
308
|
+
const mp3Bytes = new Uint8Array([0xff, 0xfb]);
|
|
309
|
+
expect(
|
|
310
|
+
detectMediaType({
|
|
311
|
+
data: mp3Bytes,
|
|
312
|
+
signatures: audioMediaTypeSignatures,
|
|
313
|
+
}),
|
|
314
|
+
).toBe('audio/mpeg');
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should detect MP3 from base64', () => {
|
|
318
|
+
const mp3Base64 = '//s='; // Base64 string starting with MP3 signature
|
|
319
|
+
expect(
|
|
320
|
+
detectMediaType({
|
|
321
|
+
data: mp3Base64,
|
|
322
|
+
signatures: audioMediaTypeSignatures,
|
|
323
|
+
}),
|
|
324
|
+
).toBe('audio/mpeg');
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should detect MP3 with ID3v2 tags from bytes', () => {
|
|
328
|
+
const mp3WithID3Bytes = new Uint8Array([
|
|
329
|
+
0x49,
|
|
330
|
+
0x44,
|
|
331
|
+
0x33, // 'ID3'
|
|
332
|
+
0x03,
|
|
333
|
+
0x00, // version
|
|
334
|
+
0x00, // flags
|
|
335
|
+
0x00,
|
|
336
|
+
0x00,
|
|
337
|
+
0x00,
|
|
338
|
+
0x0a, // size (10 bytes)
|
|
339
|
+
// 10 bytes of ID3 data
|
|
340
|
+
0x00,
|
|
341
|
+
0x00,
|
|
342
|
+
0x00,
|
|
343
|
+
0x00,
|
|
344
|
+
0x00,
|
|
345
|
+
0x00,
|
|
346
|
+
0x00,
|
|
347
|
+
0x00,
|
|
348
|
+
0x00,
|
|
349
|
+
0x00,
|
|
350
|
+
// MP3 frame header
|
|
351
|
+
0xff,
|
|
352
|
+
0xfb,
|
|
353
|
+
0x00,
|
|
354
|
+
0x00,
|
|
355
|
+
]);
|
|
356
|
+
expect(
|
|
357
|
+
detectMediaType({
|
|
358
|
+
data: mp3WithID3Bytes,
|
|
359
|
+
signatures: audioMediaTypeSignatures,
|
|
360
|
+
}),
|
|
361
|
+
).toBe('audio/mpeg');
|
|
362
|
+
});
|
|
363
|
+
it('should detect MP3 with ID3v2 tags from base64', () => {
|
|
364
|
+
const mp3WithID3Bytes = new Uint8Array([
|
|
365
|
+
0x49,
|
|
366
|
+
0x44,
|
|
367
|
+
0x33, // 'ID3'
|
|
368
|
+
0x03,
|
|
369
|
+
0x00, // version
|
|
370
|
+
0x00, // flags
|
|
371
|
+
0x00,
|
|
372
|
+
0x00,
|
|
373
|
+
0x00,
|
|
374
|
+
0x0a, // size (10 bytes)
|
|
375
|
+
// 10 bytes of ID3 data
|
|
376
|
+
0x00,
|
|
377
|
+
0x00,
|
|
378
|
+
0x00,
|
|
379
|
+
0x00,
|
|
380
|
+
0x00,
|
|
381
|
+
0x00,
|
|
382
|
+
0x00,
|
|
383
|
+
0x00,
|
|
384
|
+
0x00,
|
|
385
|
+
0x00,
|
|
386
|
+
// MP3 frame header
|
|
387
|
+
0xff,
|
|
388
|
+
0xfb,
|
|
389
|
+
0x00,
|
|
390
|
+
0x00,
|
|
391
|
+
]);
|
|
392
|
+
const mp3WithID3Base64 = convertUint8ArrayToBase64(mp3WithID3Bytes);
|
|
393
|
+
expect(
|
|
394
|
+
detectMediaType({
|
|
395
|
+
data: mp3WithID3Base64,
|
|
396
|
+
signatures: audioMediaTypeSignatures,
|
|
397
|
+
}),
|
|
398
|
+
).toBe('audio/mpeg');
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
describe('WAV', () => {
|
|
403
|
+
// WebP format: RIFF + 4 bytes file size + WEBP
|
|
404
|
+
const webpBytes = new Uint8Array([
|
|
405
|
+
0x52,
|
|
406
|
+
0x49,
|
|
407
|
+
0x46,
|
|
408
|
+
0x46, // "RIFF"
|
|
409
|
+
0x24,
|
|
410
|
+
0x00,
|
|
411
|
+
0x00,
|
|
412
|
+
0x00, // file size (example: 36 bytes)
|
|
413
|
+
0x57,
|
|
414
|
+
0x45,
|
|
415
|
+
0x42,
|
|
416
|
+
0x50, // "WEBP"
|
|
417
|
+
0x56,
|
|
418
|
+
0x50,
|
|
419
|
+
0x38,
|
|
420
|
+
0x20, // VP8 chunk (additional WebP data)
|
|
421
|
+
]);
|
|
422
|
+
|
|
423
|
+
const wavBytes = new Uint8Array([
|
|
424
|
+
0x52,
|
|
425
|
+
0x49,
|
|
426
|
+
0x46,
|
|
427
|
+
0x46, // "RIFF"
|
|
428
|
+
0x24,
|
|
429
|
+
0x00,
|
|
430
|
+
0x00,
|
|
431
|
+
0x00, // file size (example: 36 bytes)
|
|
432
|
+
0x57,
|
|
433
|
+
0x41,
|
|
434
|
+
0x56,
|
|
435
|
+
0x45, // "WAVE" (not "WEBP")
|
|
436
|
+
0x66,
|
|
437
|
+
0x6d,
|
|
438
|
+
0x74,
|
|
439
|
+
0x20, // fmt chunk
|
|
440
|
+
]);
|
|
441
|
+
|
|
442
|
+
it('should detect WAV from bytes', () => {
|
|
443
|
+
expect(
|
|
444
|
+
detectMediaType({
|
|
445
|
+
data: wavBytes,
|
|
446
|
+
signatures: audioMediaTypeSignatures,
|
|
447
|
+
}),
|
|
448
|
+
).toBe('audio/wav');
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should detect WAV from base64', () => {
|
|
452
|
+
expect(
|
|
453
|
+
detectMediaType({
|
|
454
|
+
data: convertUint8ArrayToBase64(wavBytes),
|
|
455
|
+
signatures: audioMediaTypeSignatures,
|
|
456
|
+
}),
|
|
457
|
+
).toBe('audio/wav');
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('should NOT detect WebP as WAV from bytes (negative webp image uint8)', () => {
|
|
461
|
+
expect(
|
|
462
|
+
detectMediaType({
|
|
463
|
+
data: webpBytes,
|
|
464
|
+
signatures: audioMediaTypeSignatures,
|
|
465
|
+
}),
|
|
466
|
+
).toBeUndefined(); // Should not detect as WAV
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it('should NOT detect WebP as WAV from base64 (negative webp image base64)', () => {
|
|
470
|
+
expect(
|
|
471
|
+
detectMediaType({
|
|
472
|
+
data: convertUint8ArrayToBase64(webpBytes),
|
|
473
|
+
signatures: audioMediaTypeSignatures,
|
|
474
|
+
}),
|
|
475
|
+
).toBeUndefined(); // Should not detect as WAV
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
describe('OGG', () => {
|
|
480
|
+
it('should detect OGG from bytes', () => {
|
|
481
|
+
const oggBytes = new Uint8Array([0x4f, 0x67, 0x67, 0x53]);
|
|
482
|
+
expect(
|
|
483
|
+
detectMediaType({
|
|
484
|
+
data: oggBytes,
|
|
485
|
+
signatures: audioMediaTypeSignatures,
|
|
486
|
+
}),
|
|
487
|
+
).toBe('audio/ogg');
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it('should detect OGG from base64', () => {
|
|
491
|
+
const oggBase64 = 'T2dnUw'; // Base64 string starting with OGG signature
|
|
492
|
+
expect(
|
|
493
|
+
detectMediaType({
|
|
494
|
+
data: oggBase64,
|
|
495
|
+
signatures: audioMediaTypeSignatures,
|
|
496
|
+
}),
|
|
497
|
+
).toBe('audio/ogg');
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
describe('FLAC', () => {
|
|
502
|
+
it('should detect FLAC from bytes', () => {
|
|
503
|
+
const flacBytes = new Uint8Array([0x66, 0x4c, 0x61, 0x43]);
|
|
504
|
+
expect(
|
|
505
|
+
detectMediaType({
|
|
506
|
+
data: flacBytes,
|
|
507
|
+
signatures: audioMediaTypeSignatures,
|
|
508
|
+
}),
|
|
509
|
+
).toBe('audio/flac');
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
it('should detect FLAC from base64', () => {
|
|
513
|
+
const flacBase64 = 'ZkxhQw'; // Base64 string starting with FLAC signature
|
|
514
|
+
expect(
|
|
515
|
+
detectMediaType({
|
|
516
|
+
data: flacBase64,
|
|
517
|
+
signatures: audioMediaTypeSignatures,
|
|
518
|
+
}),
|
|
519
|
+
).toBe('audio/flac');
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
describe('AAC', () => {
|
|
524
|
+
it('should detect AAC from bytes', () => {
|
|
525
|
+
const aacBytes = new Uint8Array([0x40, 0x15, 0x00, 0x00]);
|
|
526
|
+
expect(
|
|
527
|
+
detectMediaType({
|
|
528
|
+
data: aacBytes,
|
|
529
|
+
signatures: audioMediaTypeSignatures,
|
|
530
|
+
}),
|
|
531
|
+
).toBe('audio/aac');
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
it('should detect AAC from base64', () => {
|
|
535
|
+
const aacBytes = new Uint8Array([0x40, 0x15, 0x00, 0x00]);
|
|
536
|
+
expect(
|
|
537
|
+
detectMediaType({
|
|
538
|
+
data: convertUint8ArrayToBase64(aacBytes),
|
|
539
|
+
signatures: audioMediaTypeSignatures,
|
|
540
|
+
}),
|
|
541
|
+
).toBe('audio/aac');
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
describe('MP4', () => {
|
|
546
|
+
it('should detect MP4 from bytes', () => {
|
|
547
|
+
const mp4Bytes = new Uint8Array([0x66, 0x74, 0x79, 0x70]);
|
|
548
|
+
expect(
|
|
549
|
+
detectMediaType({
|
|
550
|
+
data: mp4Bytes,
|
|
551
|
+
signatures: audioMediaTypeSignatures,
|
|
552
|
+
}),
|
|
553
|
+
).toBe('audio/mp4');
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
it('should detect MP4 from base64', () => {
|
|
557
|
+
const mp4Base64 = 'ZnR5cA'; // Base64 string starting with MP4 signature
|
|
558
|
+
expect(
|
|
559
|
+
detectMediaType({
|
|
560
|
+
data: mp4Base64,
|
|
561
|
+
signatures: audioMediaTypeSignatures,
|
|
562
|
+
}),
|
|
563
|
+
).toBe('audio/mp4');
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
describe('WEBM', () => {
|
|
568
|
+
it('should detect WEBM from bytes', () => {
|
|
569
|
+
const webmBytes = new Uint8Array([0x1a, 0x45, 0xdf, 0xa3]);
|
|
570
|
+
expect(
|
|
571
|
+
detectMediaType({
|
|
572
|
+
data: webmBytes,
|
|
573
|
+
signatures: audioMediaTypeSignatures,
|
|
574
|
+
}),
|
|
575
|
+
).toBe('audio/webm');
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
it('should detect WEBM from base64', () => {
|
|
579
|
+
const webmBase64 = 'GkXfow=='; // Base64 string starting with WEBM signature
|
|
580
|
+
expect(
|
|
581
|
+
detectMediaType({
|
|
582
|
+
data: webmBase64,
|
|
583
|
+
signatures: audioMediaTypeSignatures,
|
|
584
|
+
}),
|
|
585
|
+
).toBe('audio/webm');
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
describe('error cases', () => {
|
|
590
|
+
it('should return undefined for unknown image formats', () => {
|
|
591
|
+
const unknownBytes = new Uint8Array([0x00, 0x01, 0x02, 0x03]);
|
|
592
|
+
expect(
|
|
593
|
+
detectMediaType({
|
|
594
|
+
data: unknownBytes,
|
|
595
|
+
signatures: imageMediaTypeSignatures,
|
|
596
|
+
}),
|
|
597
|
+
).toBeUndefined();
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it('should return undefined for unknown audio formats', () => {
|
|
601
|
+
const unknownBytes = new Uint8Array([0x00, 0x01, 0x02, 0x03]);
|
|
602
|
+
expect(
|
|
603
|
+
detectMediaType({
|
|
604
|
+
data: unknownBytes,
|
|
605
|
+
signatures: audioMediaTypeSignatures,
|
|
606
|
+
}),
|
|
607
|
+
).toBeUndefined();
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('should return undefined for empty arrays for image', () => {
|
|
611
|
+
const emptyBytes = new Uint8Array([]);
|
|
612
|
+
expect(
|
|
613
|
+
detectMediaType({
|
|
614
|
+
data: emptyBytes,
|
|
615
|
+
signatures: imageMediaTypeSignatures,
|
|
616
|
+
}),
|
|
617
|
+
).toBeUndefined();
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
it('should return undefined for empty arrays for audio', () => {
|
|
621
|
+
const emptyBytes = new Uint8Array([]);
|
|
622
|
+
expect(
|
|
623
|
+
detectMediaType({
|
|
624
|
+
data: emptyBytes,
|
|
625
|
+
signatures: audioMediaTypeSignatures,
|
|
626
|
+
}),
|
|
627
|
+
).toBeUndefined();
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('should return undefined for arrays shorter than signature length for image', () => {
|
|
631
|
+
const shortBytes = new Uint8Array([0x89, 0x50]); // Incomplete PNG signature
|
|
632
|
+
expect(
|
|
633
|
+
detectMediaType({
|
|
634
|
+
data: shortBytes,
|
|
635
|
+
signatures: imageMediaTypeSignatures,
|
|
636
|
+
}),
|
|
637
|
+
).toBeUndefined();
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it('should return undefined for arrays shorter than signature length for audio', () => {
|
|
641
|
+
const shortBytes = new Uint8Array([0x4f, 0x67]); // Incomplete OGG signature
|
|
642
|
+
expect(
|
|
643
|
+
detectMediaType({
|
|
644
|
+
data: shortBytes,
|
|
645
|
+
signatures: audioMediaTypeSignatures,
|
|
646
|
+
}),
|
|
647
|
+
).toBeUndefined();
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
it('should return undefined for invalid base64 strings for image', () => {
|
|
651
|
+
const invalidBase64 = 'invalid123';
|
|
652
|
+
expect(
|
|
653
|
+
detectMediaType({
|
|
654
|
+
data: invalidBase64,
|
|
655
|
+
signatures: imageMediaTypeSignatures,
|
|
656
|
+
}),
|
|
657
|
+
).toBeUndefined();
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it('should return undefined for invalid base64 strings for audio', () => {
|
|
661
|
+
const invalidBase64 = 'invalid123';
|
|
662
|
+
expect(
|
|
663
|
+
detectMediaType({
|
|
664
|
+
data: invalidBase64,
|
|
665
|
+
signatures: audioMediaTypeSignatures,
|
|
666
|
+
}),
|
|
667
|
+
).toBeUndefined();
|
|
668
|
+
});
|
|
669
|
+
});
|
|
670
|
+
});
|