0

I have angular controller, which should work with images. It have a watcher for property file in scope. If property will contain array of files, these files (only first file) should be read by FileReader and converted to base64 string and added to page. Something like this:

$scope.$watch('file', function (files) {
    if (files && files.length > 0) {
        if (files[0].type && files[0].type.match('image.*')) {
            var reader = new FileReader();
            reader.onload = function (e) {
                render(e.target.result);
            };
            reader.readAsDataURL(files[0]);
        }
    }
});

and render function:

function render (src) {
    var image = new Image();
    image.addEventListener('load', function () {
        if (image.width < MIN_SIZE || image.height < MIN_SIZE) {
            $scope.error = $filter('localize')('UploaderWindow_ImageSizeError');
            $scope.$apply();
        } else {
            new global.ICropper('original-image', {
                gap: 0,
                keepSquare: true,
                image: src,
                preview: ['cropped-image']
            });
        }
    });
    image.addEventListener('error', function () {
        $scope.error = $filter('localize')('UploaderWindow_SelectImage');
        $scope.$apply();
    });
    image.src = src;
};

ICropper should create img element in DOM with base64 in src attribute. The problem is, I have unit test for this functionality. Test case:

it('Should render new image from file input', function () {
    var imageData = image.split(',')[1],
        imageType = image.split(',')[0].replace('data:', '').replace(';base64', ''),
        file = base64toBlob(imageData, imageType);

    expect(originalImage.lastElementChild).toBe(null);
    runs(function () {
        $scope.file = [file];
        $scope.$apply();
    });
    waitsFor(function () {
        return originalImage.lastElementChild;
    }, 'waiting_original_form');
    runs(function () {
        expect(originalImage.lastElementChild.src).toBe(image);
    });
});

Variable image contains valid base64 string, originalImage.lastElementChild - img element, which should be created by ICropper. The body of base64toBlob function:

function base64toBlob (b64Data, contentType) {
    var binary = atob(b64Data.replace(/\s/g, '')),
        binaryLength = binary.length,
        buffer = new ArrayBuffer(binaryLength),
        view = new Uint8Array(buffer);

    for (var i = 0; i < binaryLength; i++) {
        view[i] = binary.charCodeAt(i);
    }

    return new Blob([view], {type: contentType});
}

This test successfully passed in Chrome, but not in PhantomJS:

timeout: timed out after 5000 msec waiting for waiting_original_form

I think, it's because load event for image not fired, error fired instead. But I don't understand why? I know, that Blob not defined in PhantomJS, so I use this polyfill: https://github.com/eligrey/Blob.js

Alex Skakun
  • 323
  • 1
  • 4
  • 10
  • Maybe the problem is unsupported FileReader. But I can't find some polyfills for FileReader for PhantomJS. – Alex Skakun Nov 05 '14 at 15:28
  • Possible duplicate of [Load file into IMAGE object using Phantom.js](http://stackoverflow.com/questions/26978246/load-file-into-image-object-using-phantom-js) – Paul Sweatte Oct 05 '15 at 22:24

0 Answers0