SkipObjectsModal.test.ts 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { describe, expect, it } from 'vitest';
  2. import { pickObjectIdAt, plateClickToMaskPoint } from '../../utils/skipObjects';
  3. function imageData(width: number, height: number, pixels: number[]): ImageData {
  4. return {
  5. width,
  6. height,
  7. data: new Uint8ClampedArray(pixels),
  8. colorSpace: 'srgb',
  9. } as ImageData;
  10. }
  11. describe('pickObjectIdAt', () => {
  12. it('decodes the slicer object ID from RGB channels', () => {
  13. const pick = imageData(2, 1, [
  14. 0, 0, 0, 0,
  15. 52, 18, 1, 255,
  16. ]);
  17. expect(pickObjectIdAt(pick, 1, 0)).toBe(1 * 65536 + 18 * 256 + 52);
  18. });
  19. it('treats transparent and black pixels as empty plate space', () => {
  20. const pick = imageData(2, 1, [
  21. 8, 0, 0, 0,
  22. 0, 0, 0, 255,
  23. ]);
  24. expect(pickObjectIdAt(pick, 0, 0)).toBeNull();
  25. expect(pickObjectIdAt(pick, 1, 0)).toBeNull();
  26. });
  27. it('clamps click coordinates to the image bounds', () => {
  28. const pick = imageData(1, 1, [63, 0, 0, 255]);
  29. expect(pickObjectIdAt(pick, 99, -4)).toBe(63);
  30. });
  31. });
  32. describe('plateClickToMaskPoint', () => {
  33. const square = { left: 100, top: 50, width: 400, height: 400 };
  34. it('maps a click through the display scale when the mask fills the box', () => {
  35. // 400px box, 200px mask: the centre of the box is the centre of the mask.
  36. expect(plateClickToMaskPoint(square, 200, 200, 300, 250)).toEqual({ x: 100, y: 100 });
  37. });
  38. it('offsets by the letterbox bars when the mask is not square', () => {
  39. // A 200x100 mask in a 400x400 box renders 400x200, leaving 100px bars top
  40. // and bottom. Without that offset this click would read 100px too low.
  41. expect(plateClickToMaskPoint(square, 200, 100, 300, 250)).toEqual({ x: 100, y: 50 });
  42. });
  43. it('rejects clicks on a letterbox bar rather than clamping onto an edge object', () => {
  44. expect(plateClickToMaskPoint(square, 200, 100, 300, 100)).toBeNull();
  45. expect(plateClickToMaskPoint(square, 200, 100, 300, 400)).toBeNull();
  46. });
  47. it('rejects clicks outside the plate box', () => {
  48. expect(plateClickToMaskPoint(square, 200, 200, 90, 250)).toBeNull();
  49. expect(plateClickToMaskPoint(square, 200, 200, 300, 460)).toBeNull();
  50. });
  51. it('returns null for a collapsed box instead of dividing by zero', () => {
  52. expect(plateClickToMaskPoint({ left: 0, top: 0, width: 0, height: 0 }, 200, 200, 0, 0)).toBeNull();
  53. });
  54. });