// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2006-2011 Strobe Inc. and contributors. // portions copyright @2011 Apple Inc. // License: Licensed under MIT license (see license.js) // ========================================================================== /*global module test ok equals stop */ (function () { var logoURL = sc_static('test-image.png'); var pane = SC.ControlTestPane.design() .add("image_loaded", SC.ImageView, { value: logoURL, layout : { width: 200, height: 300 }, useImageQueue: NO, useCanvas: NO }) .add('sprite_image', SC.ImageView, { layout: { width: 200, height: 300 }, value: 'sprite-class', useCanvas: NO }) .add('sprite_image_canvas', SC.ImageView, { layout: { width: 200, height: 300 }, value: 'sprite-class' // Must use default calculated-property version of useCanvas. }) .add('image_canvas', SC.ImageView, { layout: { width: 200, height: 300 }, useCanvas: YES, value: logoURL }) .add('canvas_not_loaded', SC.ImageView, { layout: { width: 200, height: 300 }, useCanvas: YES }) .add("image_not_loaded", SC.ImageView, { value: null, layout : { width: 200, height: 300 }, useCanvas: NO }) .add("empty_image", SC.ImageView, { value: null, layout : { width: 200, height: 300 } }) .add('image_holder', SC.View, { layout: { width: 200, height: 200 } }); module('SC.ImageView ui', pane.standardSetup()); test("Verify that all the rendering properties of an image that is being loaded are correct", function () { var imageView = pane.view('image_not_loaded'), url; ok(imageView.get('isVisibleInWindow'), 'image_not_loaded is visible in window'); SC.run(function () { imageView.set('value', logoURL); }); ok(imageView.get('status') !== SC.IMAGE_STATE_LOADED, 'PRECOND - status should not be loaded (status=%@)'.fmt(imageView.get('status'))); ok(imageView.get('status') === SC.IMAGE_STATE_LOADING, 'PRECOND - status should be loading (status=%@)'.fmt(imageView.get('status'))); url = imageView.$('img').attr('src'); ok((url.indexOf('base64')!=-1) || (url.indexOf('blank.gif')!=-1), "The src should be blank URL. url = %@".fmt(url)); }); test("Verify that all the rendering properties of an image that is loaded are correct", function () { var imageView = pane.view('image_loaded'), imgEl; ok(imageView.get('isVisibleInWindow'), 'image_loaded is visible in window'); imageView.addObserver('status', this, function () { equals(SC.IMAGE_STATE_LOADED, imageView.get('status'), 'status should be loaded'); // Status has changed, but the observer fires immediately, so pause in order to have the DOM updated setTimeout(function () { imgEl = imageView.$('img'); ok(imgEl.attr('src').indexOf(logoURL) !== 0, "img src should be set to logoURL"); window.start(); // continue the tests }, 100); }); stop(); }); test("Verify that the tooltip is correctly being set as both the title and attribute (disabling localization for this test)", function () { var imageView = pane.view('image_loaded'), testToolTip = 'This is a test tooltip', imgEl; SC.run(function () { imageView.set('localization', NO); imageView.set('toolTip', testToolTip); }); imageView.addObserver('status', this, function () { setTimeout(function () { imgEl = imageView.$('img'); equals(imgEl.attr('title'), testToolTip, "title attribute"); equals(imgEl.attr('alt'), testToolTip, "alt attribute"); window.start(); // continue the tests }, 100); }); stop(); }); test("Verify canvas rendering and properties", function () { var view = pane.view('image_canvas'), canvasEl = view.$(); equals(canvasEl.attr('width'), 200, "The width of the canvas element should be set"); equals(canvasEl.attr('height'), 300, "The height of the canvas element should be set"); }); test("Using imageQueue", function () { var imageHolder = pane.view('image_holder'), imageView1, imageView2, lastMod1, lastMod2; stop(); // Only allow 1 image at a time SC.imageQueue.loadLimit = 1; // Add a random value so that the images appear as unique lastMod1 = Math.round(Math.random() * 100000); lastMod2 = Math.round(Math.random() * 100000); // Set the first view to load in the background (ie. it should load last although it was created first) imageView1 = SC.ImageView.create({ value: logoURL + "?lastmod=" + lastMod1, canLoadInBackground: YES }); imageView2 = SC.ImageView.create({ value: logoURL + "?lastmod=" + lastMod2, canLoadInBackground: NO }); // The second image should load first and the first not be loaded yet imageView2.addObserver('status', this, function () { equals(imageView2.get('status'), SC.IMAGE_STATE_LOADED, 'imageView2 status on imageView2 status change'); equals(imageView1.get('status'), SC.IMAGE_STATE_LOADING, 'imageView1 status on imageView2 status change'); }); imageView1.addObserver('status', this, function () { equals(imageView2.get('status'), SC.IMAGE_STATE_LOADED, 'imageView2 status on imageView1 status change'); equals(imageView1.get('status'), SC.IMAGE_STATE_LOADED, 'imageView1 status on imageView1 status change'); window.start(); // starts the test runner }); imageHolder.appendChild(imageView1); imageHolder.appendChild(imageView2); }); function testScale(imageView, isImg) { stop(); // Default is SC.FILL imageView.addObserver('status', this, function () { // Status has changed, but the observer fires immediately, so pause in order to have the DOM updated setTimeout(function () { var imgEl, innerFrame, testImg = !imageView.get('useCanvas'); // Default is SC.FILL innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 588, "SC.FILL width"); equals(innerFrame.height, 90, "SC.FILL height"); if (testImg) { imgEl = imageView.$('img'); equals(imgEl.css('width'), "588px", "SC.FILL width"); equals(imgEl.css('height'), "90px", "SC.FILL height"); } SC.run(function () { imageView.set('scale', SC.SCALE_NONE); }); innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 271, "SC.SCALE_NONE width"); equals(innerFrame.height, 60, "SC.SCALE_NONE height"); if (testImg) { equals(imgEl.css('width'), "271px", "SC.SCALE_NONE width"); equals(imgEl.css('height'), "60px", "SC.SCALE_NONE height"); } SC.run(function () { imageView.set('scale', SC.BEST_FILL); }); innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 588, "SC.BEST_FILL width"); equals(innerFrame.height, 130, "SC.BEST_FILL height"); if (testImg) { equals(imgEl.css('width'), "588px", "SC.BEST_FILL width"); equals(imgEl.css('height'), "130px", "SC.BEST_FILL height"); } SC.run(function () { imageView.set('scale', SC.BEST_FIT); }); innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 407, "SC.BEST_FIT width"); equals(innerFrame.height, 90, "SC.BEST_FIT height"); if (testImg) { equals(imgEl.css('width'), "407px", "SC.BEST_FIT width"); equals(imgEl.css('height'), "90px", "SC.BEST_FIT height"); } SC.run(function () { imageView.set('scale', SC.BEST_FIT_DOWN_ONLY); }); innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 271, "SC.BEST_FIT_DOWN_ONLY width (larger frame)"); equals(innerFrame.height, 60, "SC.BEST_FIT_DOWN_ONLY height (larger frame)"); if (testImg) { equals(imgEl.css('width'), "271px", "SC.BEST_FIT_DOWN_ONLY width (larger frame)"); equals(imgEl.css('height'), "60px", "SC.BEST_FIT_DOWN_ONLY height (larger frame)"); } SC.run(function () { if (!imageView.get('useStaticLayout')) { imageView.set('layout', { top: 0, left: 0, width: 147, height: 90 }); innerFrame = imageView.get('innerFrame'); equals(innerFrame.width, 147, "SC.BEST_FIT_DOWN_ONLY width (smaller size frame)"); equals(innerFrame.height, 33, "SC.BEST_FIT_DOWN_ONLY height (smaller size frame)"); if (testImg) { equals(imgEl.css('width'), "147px", "SC.BEST_FIT_DOWN_ONLY width (smaller size frame)"); equals(imgEl.css('height'), "33px", "SC.BEST_FIT_DOWN_ONLY height (smaller size frame)"); } } }); window.start(); // starts the test runner }, 150); }); } test("Scaling images (img)", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 271x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 90 }, useCanvas: NO }); testScale(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Scaling images (img) with static layout", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 271x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), // layout: { top: 0, left: 0, width: 588, height: 90 }, useCanvas: NO, useStaticLayout: YES, render: function (context) { context.setStyle({ width: 588, height: 90 }); sc_super(); } }); testScale(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Scaling images (canvas)", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 271x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 90 } }); testScale(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Scaling images (canvas) with static layout", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 271x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), useStaticLayout: YES, render: function (context) { context.setStyle({ width: 588, height: 90 }); sc_super(); } }); testScale(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); function testAlign(imageView) { stop(); // Default is SC.FILL imageView.addObserver('status', this, function () { // Status has changed, but the observer fires immediately, so pause in order to have the DOM updated setTimeout(function () { var imgEl, innerFrame, testImg = !imageView.get('useCanvas'); // Default is SC.ALIGN_CENTER innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 30, "SC.ALIGN_CENTER top"); equals(innerFrame.x, 158.5, "SC.ALIGN_CENTER left"); if (testImg) { imgEl = imageView.$('img'); equals(imgEl.css('top'), "30px", "SC.ALIGN_CENTER top"); equals(imgEl.css('left'), "159px", "SC.ALIGN_CENTER left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_TOP_LEFT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 0, "SC.ALIGN_TOP_LEFT top"); equals(innerFrame.x, 0, "SC.ALIGN_TOP_LEFT left"); if (testImg) { equals(imgEl.css('top'), "0px", "SC.ALIGN_TOP_LEFT top"); equals(imgEl.css('left'), "0px", "SC.ALIGN_TOP_LEFT left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_TOP); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 0, "SC.ALIGN_TOP top"); equals(innerFrame.x, 158.5, "SC.ALIGN_TOP left"); if (testImg) { equals(imgEl.css('top'), "0px", "SC.ALIGN_TOP top"); equals(imgEl.css('left'), "159px", "SC.ALIGN_TOP left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_TOP_RIGHT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 0, "SC.ALIGN_TOP_RIGHT top"); equals(innerFrame.x, 317, "SC.ALIGN_TOP_RIGHT left"); if (testImg) { equals(imgEl.css('top'), "0px", "SC.ALIGN_TOP_RIGHT top"); equals(imgEl.css('left'), "317px", "SC.ALIGN_TOP_RIGHT left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_RIGHT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 30, "SC.ALIGN_RIGHT top"); equals(innerFrame.x, 317, "SC.ALIGN_RIGHT left"); if (testImg) { equals(imgEl.css('top'), "30px", "SC.ALIGN_RIGHT top"); equals(imgEl.css('left'), "317px", "SC.ALIGN_RIGHT left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_BOTTOM_RIGHT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 60, "SC.ALIGN_BOTTOM_RIGHT top"); equals(innerFrame.x, 317, "SC.ALIGN_BOTTOM_RIGHT left"); if (testImg) { equals(imgEl.css('top'), "60px", "SC.ALIGN_BOTTOM_RIGHT top"); equals(imgEl.css('left'), "317px", "SC.ALIGN_BOTTOM_RIGHT left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_BOTTOM); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 60, "SC.ALIGN_BOTTOM top"); equals(innerFrame.x, 158.5, "SC.ALIGN_BOTTOM left"); if (testImg) { equals(imgEl.css('top'), "60px", "SC.ALIGN_BOTTOM top"); equals(imgEl.css('left'), "159px", "SC.ALIGN_BOTTOM left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_BOTTOM_LEFT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 60, "SC.ALIGN_BOTTOM_LEFT top"); equals(innerFrame.x, 0, "SC.ALIGN_BOTTOM_LEFT left"); if (testImg) { equals(imgEl.css('top'), "60px", "SC.ALIGN_BOTTOM_LEFT top"); equals(imgEl.css('left'), "0px", "SC.ALIGN_BOTTOM_LEFT left"); } SC.RunLoop.begin(); imageView.set('align', SC.ALIGN_LEFT); SC.RunLoop.end(); innerFrame = imageView.get('innerFrame'); equals(innerFrame.y, 30, "SC.ALIGN_LEFT top"); equals(innerFrame.x, 0, "SC.ALIGN_LEFT left"); if (testImg) { equals(imgEl.css('top'), "30px", "SC.ALIGN_LEFT top"); equals(imgEl.css('left'), "0px", "SC.ALIGN_LEFT left"); } window.start(); // starts the test runner }, 100); }); } test("Aligning images (img)", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 294x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 120 }, useCanvas: NO, scale: SC.SCALE_NONE }); testAlign(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Aligning images (img) with static layout", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 294x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 120 }, useCanvas: NO, useStaticLayout: YES, scale: SC.SCALE_NONE }); testAlign(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Aligning images (canvas)", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 294x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 120 }, scale: SC.SCALE_NONE }); testAlign(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("Aligning images (canvas) with static layout", function () { var imageHolder = pane.view('image_holder'), imageView; // The logo is 294x60 imageView = SC.ImageView.create({ value: logoURL + "?lastmod=" + Math.round(Math.random() * 100000), layout: { top: 0, left: 0, width: 588, height: 120 }, useStaticLayout: YES, scale: SC.SCALE_NONE }); testAlign(imageView); SC.run(function () { imageHolder.appendChild(imageView); }); }); test("CSS class is applied for ImageView using a sprite for value", function () { var view = pane.view('sprite_image'), viewElem = view.$('img'); ok(viewElem.hasClass('sprite-class'), "element given correct class"); SC.run(function () { view.set('value', 'another-sprite'); }); ok(!viewElem.hasClass('sprite-class'), "When value changed, element has old class removed"); ok(viewElem.hasClass('another-sprite'), "When value changed, element has new class added"); SC.run(function () { view.set('value', null); }); viewElem = view.$('img'); ok(!viewElem.hasClass('another-sprite'), "When value removed, element has old class removed"); }); test("CSS class is applied for ImageView using a sprite for value while using canvas", function () { var view = pane.view('sprite_image_canvas'), viewElem = view.$(); ok(viewElem.hasClass('sprite-class'), "element given correct class"); SC.run(function () { view.set('value', 'another-sprite'); }); ok(!viewElem.hasClass('sprite-class'), "When value changed, element has old class removed"); ok(viewElem.hasClass('another-sprite'), "When value changed, element has new class added"); SC.run(function () { view.set('value', null); }); viewElem = view.$(); ok(!viewElem.hasClass('another-sprite'), "When value removed, element has old class removed"); }); test("Changing the type of image view updates the layer appropriately (with canvas)", function () { var view = pane.view('canvas_not_loaded'), jqEl = view.$(), el = jqEl[0], jqImgEl, imgEl; equals(el.innerHTML, '', "The empty image should have no inner HTML."); equals(el.tagName, 'CANVAS', "The empty image should be a CANVAS"); // Set a sprite value. SC.run(function () { view.set('value', 'sprite-class'); }); jqEl = view.$(); ok(jqEl.hasClass('sprite-class'), "The sprite image should have sprite-class class."); equals(el.innerHTML, '', "The sprite image should have no inner HTML."); // Set a URL value. SC.run(function () { view.set('value', logoURL); }); jqEl = view.$(); el = jqEl[0]; ok(!jqEl.hasClass('sprite-class'), "The url image should no longer have sprite-class class."); equals(el.innerHTML, '', "The url image should have no inner HTML."); equals(el.tagName, 'CANVAS', "The url image should be a CANVAS"); }); test("Changing the type of image view updates the layer appropriately (without canvas)", function () { var view = pane.view('image_not_loaded'), jqEl = view.$('img'), el = jqEl[0], jqImgEl, imgEl; ok(!jqEl.attr('class'), "The empty image should have no class."); equals(el.tagName, 'IMG', "The empty image should be a IMG"); // Set a sprite value. SC.run(function () { view.set('value', 'sprite-class'); }); jqEl = view.$('img'); ok(jqEl.hasClass('sprite-class'), "The sprite image should have sprite-class class."); // Set a URL value. SC.run(function () { view.set('value', logoURL); }); jqEl = view.$('img'); ok(!jqEl.hasClass('sprite-class'), "The url image should no longer have sprite-class class."); }); })();