]>
git.proxmox.com Git - mirror_novnc.git/blob - tests/test.display.js
1 // requires local modules: util, base64, display
2 /* jshint expr: true */
3 var expect
= chai
.expect
;
5 chai
.use(function (_chai
, utils
) {
6 _chai
.Assertion
.addMethod('displayed', function (target_data
) {
8 var data_cl
= obj
._drawCtx
.getImageData(0, 0, obj
._viewportLoc
.w
, obj
._viewportLoc
.h
).data
;
9 // NB(directxman12): PhantomJS 1.x doesn't implement Uint8ClampedArray, so work around that
10 var data
= new Uint8Array(data_cl
);
11 this.assert(utils
.eql(data
, target_data
),
12 "expected #{this} to have displayed the image #{exp}, but instead it displayed #{act}",
13 "expected #{this} not to have displayed the image #{act}",
19 describe('Display/Canvas Helper', function () {
21 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
22 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
23 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
24 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
26 checked_data
= new Uint8Array(checked_data
);
28 var basic_data
= [0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0xff, 0xff, 0xff, 255];
29 basic_data
= new Uint8Array(basic_data
);
31 function make_image_canvas (input_data
) {
32 var canvas
= document
.createElement('canvas');
35 var ctx
= canvas
.getContext('2d');
36 var data
= ctx
.createImageData(4, 4);
37 for (var i
= 0; i
< checked_data
.length
; i
++) { data
.data
[i
] = input_data
[i
]; }
38 ctx
.putImageData(data
, 0, 0);
42 describe('viewport handling', function () {
44 beforeEach(function () {
45 display
= new Display({ target
: document
.createElement('canvas'), prefer_js
: false, viewport
: true });
47 display
.viewportChange(1, 1, 3, 3);
48 display
.getCleanDirtyReset();
51 it('should take viewport location into consideration when drawing images', function () {
53 display
.viewportChange(0, 0, 2, 2);
54 display
.drawImage(make_image_canvas(basic_data
), 1, 1);
56 var expected
= new Uint8Array(16);
58 for (i
= 0; i
< 8; i
++) { expected
[i
] = basic_data
[i
]; }
59 for (i
= 8; i
< 16; i
++) { expected
[i
] = 0; }
60 expect(display
).to
.have
.displayed(expected
);
63 it('should redraw the left side when shifted left', function () {
64 display
.viewportChange(-1, 0, 3, 3);
65 var cdr
= display
.getCleanDirtyReset();
66 expect(cdr
.cleanBox
).to
.deep
.equal({ x
: 1, y
: 1, w
: 2, h
: 3 });
67 expect(cdr
.dirtyBoxes
).to
.have
.length(1);
68 expect(cdr
.dirtyBoxes
[0]).to
.deep
.equal({ x
: 0, y
: 1, w
: 2, h
: 3 });
71 it('should redraw the right side when shifted right', function () {
72 display
.viewportChange(1, 0, 3, 3);
73 var cdr
= display
.getCleanDirtyReset();
74 expect(cdr
.cleanBox
).to
.deep
.equal({ x
: 2, y
: 1, w
: 2, h
: 3 });
75 expect(cdr
.dirtyBoxes
).to
.have
.length(1);
76 expect(cdr
.dirtyBoxes
[0]).to
.deep
.equal({ x
: 4, y
: 1, w
: 1, h
: 3 });
79 it('should redraw the top part when shifted up', function () {
80 display
.viewportChange(0, -1, 3, 3);
81 var cdr
= display
.getCleanDirtyReset();
82 expect(cdr
.cleanBox
).to
.deep
.equal({ x
: 1, y
: 1, w
: 3, h
: 2 });
83 expect(cdr
.dirtyBoxes
).to
.have
.length(1);
84 expect(cdr
.dirtyBoxes
[0]).to
.deep
.equal({ x
: 1, y
: 0, w
: 3, h
: 1 });
87 it('should redraw the bottom part when shifted down', function () {
88 display
.viewportChange(0, 1, 3, 3);
89 var cdr
= display
.getCleanDirtyReset();
90 expect(cdr
.cleanBox
).to
.deep
.equal({ x
: 1, y
: 2, w
: 3, h
: 2 });
91 expect(cdr
.dirtyBoxes
).to
.have
.length(1);
92 expect(cdr
.dirtyBoxes
[0]).to
.deep
.equal({ x
: 1, y
: 4, w
: 3, h
: 1 });
95 it('should reset the entire viewport to being clean after calculating the clean/dirty boxes', function () {
96 display
.viewportChange(0, 1, 3, 3);
97 var cdr1
= display
.getCleanDirtyReset();
98 var cdr2
= display
.getCleanDirtyReset();
99 expect(cdr1
).to
.not
.deep
.equal(cdr2
);
100 expect(cdr2
.cleanBox
).to
.deep
.equal({ x
: 1, y
: 2, w
: 3, h
: 3 });
101 expect(cdr2
.dirtyBoxes
).to
.be
.empty
;
104 it('should simply mark the whole display area as dirty if not using viewports', function () {
105 display
= new Display({ target
: document
.createElement('canvas'), prefer_js
: false, viewport
: false });
106 display
.resize(5, 5);
107 var cdr
= display
.getCleanDirtyReset();
108 expect(cdr
.cleanBox
).to
.deep
.equal({ x
: 0, y
: 0, w
: 0, h
: 0 });
109 expect(cdr
.dirtyBoxes
).to
.have
.length(1);
110 expect(cdr
.dirtyBoxes
[0]).to
.deep
.equal({ x
: 0, y
: 0, w
: 5, h
: 5 });
114 describe('resizing', function () {
116 beforeEach(function () {
117 display
= new Display({ target
: document
.createElement('canvas'), prefer_js
: false, viewport
: true });
118 display
.resize(4, 3);
121 it('should change the size of the logical canvas', function () {
122 display
.resize(5, 7);
123 expect(display
._fb_width
).to
.equal(5);
124 expect(display
._fb_height
).to
.equal(7);
127 it('should update the viewport dimensions', function () {
128 sinon
.spy(display
, 'viewportChange');
129 display
.resize(2, 2);
130 expect(display
.viewportChange
).to
.have
.been
.calledOnce
;
134 describe('drawing', function () {
136 // TODO(directxman12): improve the tests for each of the drawing functions to cover more than just the
138 function drawing_tests (pref_js
) {
140 beforeEach(function () {
141 display
= new Display({ target
: document
.createElement('canvas'), prefer_js
: pref_js
});
142 display
.resize(4, 4);
145 it('should clear the screen on #clear without a logo set', function () {
146 display
.fillRect(0, 0, 4, 4, [0x00, 0x00, 0xff]);
147 display
._logo
= null;
149 display
.resize(4, 4);
151 for (var i
= 0; i
< 4 * display
._fb_width
* display
._fb_height
; i
++) { empty
[i
] = 0; }
152 expect(display
).to
.have
.displayed(new Uint8Array(empty
));
155 it('should draw the logo on #clear with a logo set', function (done
) {
156 display
._logo
= { width
: 4, height
: 4, data
: make_image_canvas(checked_data
).toDataURL() };
157 display
._drawCtx
._act_drawImg
= display
._drawCtx
.drawImage
;
158 display
._drawCtx
.drawImage = function (img
, x
, y
) {
159 this._act_drawImg(img
, x
, y
);
160 expect(display
).to
.have
.displayed(checked_data
);
164 expect(display
._fb_width
).to
.equal(4);
165 expect(display
._fb_height
).to
.equal(4);
168 it('should support filling a rectangle with particular color via #fillRect', function () {
169 display
.fillRect(0, 0, 4, 4, [0, 0xff, 0]);
170 display
.fillRect(0, 0, 2, 2, [0xff, 0, 0]);
171 display
.fillRect(2, 2, 2, 2, [0xff, 0, 0]);
172 expect(display
).to
.have
.displayed(checked_data
);
175 it('should support copying an portion of the canvas via #copyImage', function () {
176 display
.fillRect(0, 0, 4, 4, [0, 0xff, 0]);
177 display
.fillRect(0, 0, 2, 2, [0xff, 0, 0x00]);
178 display
.copyImage(0, 0, 2, 2, 2, 2);
179 expect(display
).to
.have
.displayed(checked_data
);
182 it('should support drawing tile data with a background color and sub tiles', function () {
183 display
.startTile(0, 0, 4, 4, [0, 0xff, 0]);
184 display
.subTile(0, 0, 2, 2, [0xff, 0, 0]);
185 display
.subTile(2, 2, 2, 2, [0xff, 0, 0]);
186 display
.finishTile();
187 expect(display
).to
.have
.displayed(checked_data
);
190 it('should support drawing BGRX blit images with true color via #blitImage', function () {
192 for (var i
= 0; i
< 16; i
++) {
193 data
[i
* 4] = checked_data
[i
* 4 + 2];
194 data
[i
* 4 + 1] = checked_data
[i
* 4 + 1];
195 data
[i
* 4 + 2] = checked_data
[i
* 4];
196 data
[i
* 4 + 3] = checked_data
[i
* 4 + 3];
198 display
.blitImage(0, 0, 4, 4, data
, 0);
199 expect(display
).to
.have
.displayed(checked_data
);
202 it('should support drawing RGB blit images with true color via #blitRgbImage', function () {
204 for (var i
= 0; i
< 16; i
++) {
205 data
[i
* 3] = checked_data
[i
* 4];
206 data
[i
* 3 + 1] = checked_data
[i
* 4 + 1];
207 data
[i
* 3 + 2] = checked_data
[i
* 4 + 2];
209 display
.blitRgbImage(0, 0, 4, 4, data
, 0);
210 expect(display
).to
.have
.displayed(checked_data
);
213 it('should support drawing blit images from a data URL via #blitStringImage', function (done
) {
214 var img_url
= make_image_canvas(checked_data
).toDataURL();
215 display
._drawCtx
._act_drawImg
= display
._drawCtx
.drawImage
;
216 display
._drawCtx
.drawImage = function (img
, x
, y
) {
217 this._act_drawImg(img
, x
, y
);
218 expect(display
).to
.have
.displayed(checked_data
);
221 display
.blitStringImage(img_url
, 0, 0);
224 it('should support drawing solid colors with color maps', function () {
225 display
._true_color
= false;
226 display
.set_colourMap({ 0: [0xff, 0, 0], 1: [0, 0xff, 0] });
227 display
.fillRect(0, 0, 4, 4, [1]);
228 display
.fillRect(0, 0, 2, 2, [0]);
229 display
.fillRect(2, 2, 2, 2, [0]);
230 expect(display
).to
.have
.displayed(checked_data
);
233 it('should support drawing blit images with color maps', function () {
234 display
._true_color
= false;
235 display
.set_colourMap({ 1: [0xff, 0, 0], 0: [0, 0xff, 0] });
236 var data
= [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1].map(function (elem
) { return [elem
]; });
237 display
.blitImage(0, 0, 4, 4, data
, 0);
238 expect(display
).to
.have
.displayed(checked_data
);
241 it('should support drawing an image object via #drawImage', function () {
242 var img
= make_image_canvas(checked_data
);
243 display
.drawImage(img
, 0, 0);
244 expect(display
).to
.have
.displayed(checked_data
);
248 describe('(prefering native methods)', function () { drawing_tests
.call(this, false); });
249 describe('(prefering JavaScript)', function () { drawing_tests
.call(this, true); });
252 describe('the render queue processor', function () {
254 beforeEach(function () {
255 display
= new Display({ target
: document
.createElement('canvas'), prefer_js
: false });
256 display
.resize(4, 4);
257 sinon
.spy(display
, '_scan_renderQ');
258 this.old_requestAnimFrame
= window
.requestAnimFrame
;
259 window
.requestAnimFrame = function (cb
) {
260 this.next_frame_cb
= cb
;
262 this.next_frame = function () { this.next_frame_cb(); };
265 afterEach(function () {
266 window
.requestAnimFrame
= this.old_requestAnimFrame
;
269 it('should try to process an item when it is pushed on, if nothing else is on the queue', function () {
270 display
.renderQ_push({ type
: 'noop' }); // does nothing
271 expect(display
._scan_renderQ
).to
.have
.been
.calledOnce
;
274 it('should not try to process an item when it is pushed on if we are waiting for other items', function () {
275 display
._renderQ
.length
= 2;
276 display
.renderQ_push({ type
: 'noop' });
277 expect(display
._scan_renderQ
).to
.not
.have
.been
.called
;
280 it('should wait until an image is loaded to attempt to draw it and the rest of the queue', function () {
281 var img
= { complete
: false };
282 display
._renderQ
= [{ type
: 'img', x
: 3, y
: 4, img
: img
},
283 { type
: 'fill', x
: 1, y
: 2, width
: 3, height
: 4, color
: 5 }];
284 display
.drawImage
= sinon
.spy();
285 display
.fillRect
= sinon
.spy();
287 display
._scan_renderQ();
288 expect(display
.drawImage
).to
.not
.have
.been
.called
;
289 expect(display
.fillRect
).to
.not
.have
.been
.called
;
291 display
._renderQ
[0].img
.complete
= true;
293 expect(display
.drawImage
).to
.have
.been
.calledOnce
;
294 expect(display
.fillRect
).to
.have
.been
.calledOnce
;
297 it('should draw a blit image on type "blit"', function () {
298 display
.blitImage
= sinon
.spy();
299 display
.renderQ_push({ type
: 'blit', x
: 3, y
: 4, width
: 5, height
: 6, data
: [7, 8, 9] });
300 expect(display
.blitImage
).to
.have
.been
.calledOnce
;
301 expect(display
.blitImage
).to
.have
.been
.calledWith(3, 4, 5, 6, [7, 8, 9], 0);
304 it('should draw a blit RGB image on type "blitRgb"', function () {
305 display
.blitRgbImage
= sinon
.spy();
306 display
.renderQ_push({ type
: 'blitRgb', x
: 3, y
: 4, width
: 5, height
: 6, data
: [7, 8, 9] });
307 expect(display
.blitRgbImage
).to
.have
.been
.calledOnce
;
308 expect(display
.blitRgbImage
).to
.have
.been
.calledWith(3, 4, 5, 6, [7, 8, 9], 0);
311 it('should copy a region on type "copy"', function () {
312 display
.copyImage
= sinon
.spy();
313 display
.renderQ_push({ type
: 'copy', x
: 3, y
: 4, width
: 5, height
: 6, old_x
: 7, old_y
: 8 });
314 expect(display
.copyImage
).to
.have
.been
.calledOnce
;
315 expect(display
.copyImage
).to
.have
.been
.calledWith(7, 8, 3, 4, 5, 6);
318 it('should fill a rect with a given color on type "fill"', function () {
319 display
.fillRect
= sinon
.spy();
320 display
.renderQ_push({ type
: 'fill', x
: 3, y
: 4, width
: 5, height
: 6, color
: [7, 8, 9]});
321 expect(display
.fillRect
).to
.have
.been
.calledOnce
;
322 expect(display
.fillRect
).to
.have
.been
.calledWith(3, 4, 5, 6, [7, 8, 9]);
325 it('should draw an image from an image object on type "img" (if complete)', function () {
326 display
.drawImage
= sinon
.spy();
327 display
.renderQ_push({ type
: 'img', x
: 3, y
: 4, img
: { complete
: true } });
328 expect(display
.drawImage
).to
.have
.been
.calledOnce
;
329 expect(display
.drawImage
).to
.have
.been
.calledWith({ complete
: true }, 3, 4);