// Copyright (C) 2020-2022 Intel Corporation // Copyright (C) 2022 CVAT.ai Corporation // // SPDX-License-Identifier: MIT // Setup mock for a server jest.mock('../../src/server-proxy', () => { return { __esModule: true, default: require('../mocks/server-proxy.mock'), }; }); // Initialize api window.cvat = require('../../src/api').default; describe('Feature: set attributes for an object state', () => { test('set a valid value', () => { const state = new window.cvat.classes.ObjectState({ label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }), objectType: window.cvat.enums.ObjectType.SHAPE, shapeType: window.cvat.enums.ShapeType.RECTANGLE, frame: 5, }); const attributes = { 5: 'man', 6: 'glasses', }; state.attributes = attributes; expect(state.attributes).toEqual(attributes); }); test('trying to set a bad value', () => { const state = new window.cvat.classes.ObjectState({ label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }), objectType: window.cvat.enums.ObjectType.SHAPE, shapeType: window.cvat.enums.ShapeType.RECTANGLE, frame: 5, }); let attributes = 'bad attribute'; expect(() => { state.attributes = attributes; }).toThrow(window.cvat.exceptions.ArgumentError); attributes = 5; expect(() => { state.attributes = attributes; }).toThrow(window.cvat.exceptions.ArgumentError); attributes = false; expect(() => { state.attributes = attributes; }).toThrow(window.cvat.exceptions.ArgumentError); }); }); describe('Feature: set points for an object state', () => { test('set a valid value', () => { const state = new window.cvat.classes.ObjectState({ label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }), objectType: window.cvat.enums.ObjectType.SHAPE, shapeType: window.cvat.enums.ShapeType.RECTANGLE, frame: 5, }); const points = [1, 2, 3, 4]; state.points = points; expect(state.points).toEqual(points); }); test('trying to set a bad value', () => { const state = new window.cvat.classes.ObjectState({ label: new window.cvat.classes.Label({ name: 'test label', id: 1, color: '#000000', attributes: [] }), objectType: window.cvat.enums.ObjectType.SHAPE, shapeType: window.cvat.enums.ShapeType.RECTANGLE, frame: 5, }); let points = 'bad points'; expect(() => { state.points = points; }).toThrow(window.cvat.exceptions.ArgumentError); points = 5; expect(() => { state.points = points; }).toThrow(window.cvat.exceptions.ArgumentError); points = false; expect(() => { state.points = points; }).toThrow(window.cvat.exceptions.ArgumentError); points = {}; expect(() => { state.points = points; }).toThrow(window.cvat.exceptions.ArgumentError); }); }); describe('Feature: save object from its state', () => { test('save valid values for a shape', async () => { const task = (await window.cvat.tasks.get({ id: 100 }))[0]; const annotations = await task.annotations.get(0); let state = annotations[0]; expect(state.objectType).toBe(window.cvat.enums.ObjectType.SHAPE); expect(state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE); state.points = [0, 0, 100, 100]; state.occluded = true; [, state.label] = task.labels; state.lock = true; state = await state.save(); expect(state).toBeInstanceOf(window.cvat.classes.ObjectState); expect(state.label.id).toBe(task.labels[1].id); expect(state.lock).toBe(true); expect(state.occluded).toBe(true); expect(state.points).toEqual([0, 0, 100, 100]); }); test('save valid values for a track', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotations = await task.annotations.get(10); let state = annotations[1]; expect(state.objectType).toBe(window.cvat.enums.ObjectType.TRACK); expect(state.shapeType).toBe(window.cvat.enums.ShapeType.RECTANGLE); state.occluded = true; state.lock = true; state.points = [100, 200, 200, 400]; state.attributes = { 1: 'sitting', 3: 'female', 2: '10', 4: 'true', }; state = await state.save(); expect(state).toBeInstanceOf(window.cvat.classes.ObjectState); expect(state.lock).toBe(true); expect(state.occluded).toBe(true); expect(state.points).toEqual([100, 200, 200, 400]); expect(state.attributes[1]).toBe('sitting'); expect(state.attributes[2]).toBe('10'); expect(state.attributes[3]).toBe('female'); expect(state.attributes[4]).toBe('true'); state.lock = false; [state.label] = task.labels; state = await state.save(); expect(state.label.id).toBe(task.labels[0].id); state.outside = true; state = await state.save(); expect(state.lock).toBe(false); expect(state.outside).toBe(true); state.keyframe = false; state = await state.save(); expect(state.keyframe).toBe(false); }); test('save bad values for a shape', async () => { const task = (await window.cvat.tasks.get({ id: 100 }))[0]; const annotations = await task.annotations.get(0); const state = annotations[0]; state.occluded = 'false'; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.occluded = false; expect(() => state.points = ['100', '50', '100', {}]).toThrow(window.cvat.exceptions.ArgumentError); state.lock = 'true'; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); const oldLabel = state.label; state.lock = false; state.label = 1; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.label = oldLabel; state.attributes = { 1: {}, 2: false, 3: () => {} }; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); }); test('save bad values for a track', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotations = await task.annotations.get(0); const state = annotations[0]; state.occluded = 'false'; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.occluded = false; expect(() => state.points = ['100', '50', '100', {}]).toThrow(window.cvat.exceptions.ArgumentError); state.lock = 'true'; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); const oldLabel = state.label; state.lock = false; state.label = 1; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.label = oldLabel; state.outside = 5; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.outside = false; state.keyframe = '10'; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); state.keyframe = true; state.attributes = { 1: {}, 2: false, 3: () => {} }; await expect(state.save()).rejects.toThrow(window.cvat.exceptions.ArgumentError); }); test('trying to change locked shape', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotations = await task.annotations.get(0); let state = annotations[0]; state.lock = true; state = await state.save(); const { points } = state; state.points = [0, 0, 500, 500]; state = await state.save(); expect(state.points).toEqual(points); }); test('trying to set too small area of a shape', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotations = await task.annotations.get(0); let state = annotations[0]; const { points } = state; state.points = [0, 0, 2, 2]; // area is 4 state = await state.save(); expect(state.points).toEqual(points); }); test('trying to set too small area of a track', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotations = await task.annotations.get(0); let state = annotations[0]; const { points } = state; state.points = [0, 0, 2, 2]; // area is 4 state = await state.save(); expect(state.points).toEqual(points); }); test('trying to set too small length of a shape', async () => { const task = (await window.cvat.tasks.get({ id: 100 }))[0]; const annotations = await task.annotations.get(0); let state = annotations[8]; const { points } = state; state.points = [0, 0, 2, 2]; // length is 2 state = await state.save(); expect(state.points).toEqual(points); }); }); describe('Feature: delete object', () => { test('delete a shape', async () => { const task = (await window.cvat.tasks.get({ id: 100 }))[0]; const annotationsBefore = await task.annotations.get(0); const { length } = annotationsBefore; await annotationsBefore[0].delete(0); const annotationsAfter = await task.annotations.get(0); expect(annotationsAfter).toHaveLength(length - 1); }); test('delete a track', async () => { const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const annotationsBefore = await task.annotations.get(0); const { length } = annotationsBefore; await annotationsBefore[0].delete(0); const annotationsAfter = await task.annotations.get(0); expect(annotationsAfter).toHaveLength(length - 1); }); }); describe('Feature: skeletons', () => { test('lock, hide, occluded, outside for skeletons', async () => { const job = (await window.cvat.jobs.get({ jobID: 40 }))[0]; let [skeleton] = await job.annotations.get(0, false, JSON.parse('[{"and":[{"==":[{"var":"shape"},"skeleton"]}]}]')); expect(skeleton.shapeType).toBe('skeleton'); skeleton.lock = true; skeleton.outside = true; skeleton.occluded = true; skeleton.hidden = true; skeleton = await skeleton.save(); expect(skeleton.lock).toBe(true); expect(skeleton.outside).toBe(true); expect(skeleton.occluded).toBe(true); expect(skeleton.hidden).toBe(true); expect(skeleton.elements).toBeInstanceOf(Array); expect(skeleton.elements.length).toBe(skeleton.label.structure.sublabels.length); for (const element of skeleton.elements) { expect(element.lock).toBe(true); expect(element.outside).toBe(true); expect(element.occluded).toBe(true); expect(element.hidden).toBe(true); } skeleton.elements[0].lock = false; skeleton.elements[0].outside = false; skeleton.elements[0].occluded = false; skeleton.elements[0].hidden = false; skeleton.elements[0].save(); [skeleton] = await job.annotations.get(0, false, JSON.parse('[{"and":[{"==":[{"var":"shape"},"skeleton"]}]}]')); expect(skeleton.lock).toBe(false); expect(skeleton.outside).toBe(false); expect(skeleton.occluded).toBe(false); expect(skeleton.hidden).toBe(false); }); });