mirror of
https://github.com/igorski/bitmappery.git
synced 2026-06-17 03:34:56 +02:00
Pass, oh tests
This commit is contained in:
61
src/services/resource-service.js
Normal file
61
src/services/resource-service.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Igor Zinken 2020 - https://www.igorski.nl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import { createCanvas } from './canvas-util';
|
||||
|
||||
const { URL } = window;
|
||||
|
||||
/**
|
||||
* Creates a Blob URL for the resource represented by given imageElement.
|
||||
* By treating referenced Image resources as URLs to binary content, the browser
|
||||
* can use its internal loading/caching mechanism when working with these resources.
|
||||
* NOTE: When done using the image, don't forget to call dispose() to free allocated memory.
|
||||
*
|
||||
* @param {HTMLImageElement} imageElement fully loaded image
|
||||
* @param {String=} type optional mime type, defaults to JPEG for photographic content
|
||||
* @param {Number=} optQuality optional JPEG compression to use (when mime is JPEG) between 0 - 1
|
||||
* @return {String} Blob URL
|
||||
*/
|
||||
export const imageToResource = ( imageElement, type = "image/jpeg", optQuality = .9 ) => {
|
||||
const { cvs, ctx } = createCanvas();
|
||||
|
||||
cvs.width = imageElement.naturalWidth || imageElement.width;
|
||||
cvs.height = imageElement.naturalHeight || imageElement.height;
|
||||
|
||||
ctx.drawImage( imageElement, 0, 0 );
|
||||
|
||||
return new Promise(( resolve, reject ) => {
|
||||
try {
|
||||
cvs.toBlob(( blob ) => {
|
||||
resolve( URL.createObjectURL( blob ));
|
||||
}, type, optQuality );
|
||||
} catch ( error ) {
|
||||
reject( error );
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const disposeResource = imageBlobURL => {
|
||||
URL.revokeObjectURL( imageBlobURL );
|
||||
};
|
||||
|
||||
export const verifyIfResource = imageElement => imageElement.src.startsWith( "blob:" );
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
import Vue from "vue";
|
||||
import {
|
||||
imageToResource, disposeResource, verifyIfResource
|
||||
imageToResource, disposeResource, isResource
|
||||
} from "@/utils/resource-manager";
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
* converted to binary as registered as a Blob URL.
|
||||
*/
|
||||
async addImage({ state }, { file, image, size }) {
|
||||
const isValidResource = verifyIfResource( image ) || image.src.startsWith( "http" );
|
||||
const isValidResource = isResource( image ) || image.src.startsWith( "http" );
|
||||
|
||||
const source = isValidResource ? image.src : await imageToResource( image, file.type );
|
||||
const imageData = { file, size, source };
|
||||
|
||||
@@ -58,4 +58,4 @@ export const disposeResource = imageBlobURL => {
|
||||
URL.revokeObjectURL( imageBlobURL );
|
||||
};
|
||||
|
||||
export const verifyIfResource = imageElement => imageElement.src.startsWith( "blob:" );
|
||||
export const isResource = imageElement => imageElement.src.startsWith( "blob:" );
|
||||
|
||||
@@ -6,6 +6,7 @@ let mockUpdateFn;
|
||||
jest.mock("@/utils/resource-manager", () => ({
|
||||
imageToResource: (...args) => mockUpdateFn?.( "imageToResource", ...args ),
|
||||
disposeResource: (...args) => mockUpdateFn?.( "disposeResource", ...args ),
|
||||
isResource: (...args) => mockUpdateFn?.( "isResource", ...args ),
|
||||
}));
|
||||
|
||||
describe( "Vuex image module", () => {
|
||||
@@ -41,6 +42,7 @@ describe( "Vuex image module", () => {
|
||||
image: { src: "blob:http://foo" },
|
||||
size: { width: 100, height: 100 },
|
||||
};
|
||||
mockUpdateFn = jest.fn(fn => fn === "isResource" ? true : false );
|
||||
const image = await actions.addImage({ state }, input );
|
||||
// assert image has been added to list
|
||||
expect( state.images ).toEqual([ { file: input.file, size: input.size, source: input.image.src } ]);
|
||||
@@ -70,14 +72,13 @@ describe( "Vuex image module", () => {
|
||||
const state = { images: [] };
|
||||
const input = {
|
||||
file: { type: "image/png" },
|
||||
image: new Image(),
|
||||
image: { src: "base64" },
|
||||
size: { width: 100, height: 100 },
|
||||
};
|
||||
const blobURL = "blob:http://foo";
|
||||
mockUpdateFn = jest.fn(() => blobURL );
|
||||
mockUpdateFn = jest.fn( fn => fn === "isResource" ? false : "" );
|
||||
const image = await actions.addImage({ state }, input );
|
||||
// assert image has been added to list
|
||||
expect( state.images ).toEqual([ { file: input.file, size: input.size, source: blobURL } ]);
|
||||
expect( state.images ).toEqual([ { file: input.file, size: input.size, source: expect.any( String ) } ]);
|
||||
// assert image data has been allocated as Blob
|
||||
expect( mockUpdateFn ).toHaveBeenCalledWith( "imageToResource", input.image, input.file.type );
|
||||
// assert return data contains allocated Blob resource
|
||||
|
||||
Reference in New Issue
Block a user