@@ -25,6 +25,73 @@ const initLabelStudio = async ({ config, data, completions = [{ result: [] }], p
2525 done ( ) ;
2626} ;
2727
28+ /**
29+ * Wait for the main Image object to be loaded
30+ * @param {function } done codecept async success handler
31+ */
32+ const waitForImage = async done => {
33+ const img = document . querySelector ( "[alt=LS]" ) ;
34+ if ( ! img || img . complete ) return done ( ) ;
35+ img . onload = done ;
36+ } ;
37+
38+ /**
39+ * Float numbers can't be compared strictly, so convert any numbers or structures with numbers
40+ * to same structures but with rounded numbers (int for ints, fixed(2) for floats)
41+ * @param {* } data
42+ */
43+ const convertToFixed = data => {
44+ if ( [ "string" , "number" ] . includes ( typeof data ) ) {
45+ const n = Number ( data ) ;
46+ return Number . isInteger ( n ) ? n : + Number ( n ) . toFixed ( 2 ) ;
47+ }
48+ if ( Array . isArray ( data ) ) {
49+ return data . map ( n => convertToFixed ( n ) ) ;
50+ }
51+ if ( typeof data === "object" ) {
52+ const result = { } ;
53+ for ( let key in data ) {
54+ result [ key ] = convertToFixed ( data [ key ] ) ;
55+ }
56+ return result ;
57+ }
58+ return data ;
59+ } ;
60+
61+ /**
62+ * Create convertor for any measures to relative form on image with given dimensions
63+ * Accepts numbers, arrays ([x, y] treated as a special coords array) and hash objects
64+ * With [706, 882] given as image sizes:
65+ * assert.equal(convertToImageSize(123), 17.42);
66+ * assert.deepEqual(convertToImageSize([123, 123]), [17.42, 13.95]);
67+ * assert.deepEqual(
68+ * convertToImageSize({ width: 123, height: 123, radiusY: 123, coords: [123, 123] }),
69+ * { width: 17.42, height: 13.95, radiusY: 13.95, coords: [17.42, 13.95] }
70+ * );
71+ * @param {number } width
72+ * @param {number } height
73+ */
74+ const getSizeConvertor = ( width , height ) =>
75+ function convert ( data , size = width ) {
76+ if ( typeof data === "number" ) return convertToFixed ( ( data * 100 ) / size ) ;
77+ if ( Array . isArray ( data ) ) {
78+ if ( data . length === 2 ) return [ convert ( data [ 0 ] ) , convert ( data [ 1 ] , height ) ] ;
79+ return data . map ( n => convert ( n ) ) ;
80+ }
81+ if ( typeof data === "object" ) {
82+ const result = { } ;
83+ for ( let key in data ) {
84+ if ( key === "rotation" ) result [ key ] = data [ key ] ;
85+ else if ( key . startsWith ( "height" ) || key === "y" || key . endsWith ( "Y" ) ) result [ key ] = convert ( data [ key ] , height ) ;
86+ else result [ key ] = convert ( data [ key ] ) ;
87+ }
88+ return result ;
89+ }
90+ return data ;
91+ } ;
92+
93+ const delay = n => new Promise ( resolve => setTimeout ( resolve , n ) ) ;
94+
2895// good idea, but it doesn't work :(
2996const emulateClick = source => {
3097 const event = document . createEvent ( "CustomEvent" ) ;
@@ -40,6 +107,93 @@ const clickRect = () => {
40107 rect . fire ( "click" , { clientX : 10 , clientY : 10 } ) ;
41108} ;
42109
110+ /**
111+ * Click once on the main Stage
112+ * @param {number } x
113+ * @param {number } y
114+ * @param {function } done
115+ */
116+ const clickKonva = ( x , y , done ) => {
117+ const stage = window . Konva . stages [ 0 ] ;
118+ stage . fire ( "click" , { clientX : x , clientY : y , evt : { offsetX : x , offsetY : y } } ) ;
119+ done ( ) ;
120+ } ;
121+
122+ /**
123+ * Click multiple times on the Stage
124+ * @param {number[][] } points array of coords arrays ([[x1, y1], [x2, y2], ...])
125+ * @param {function } done
126+ */
127+ const clickMultipleKonva = async ( points , done ) => {
128+ const stage = window . Konva . stages [ 0 ] ;
129+ for ( let point of points ) {
130+ stage . fire ( "click" , { evt : { offsetX : point [ 0 ] , offsetY : point [ 1 ] } } ) ;
131+ // await delay(10);
132+ }
133+ done ( ) ;
134+ } ;
135+
136+ /**
137+ * Create Polygon on Stage by clicking multiple times and click on the first point at the end
138+ * @param {number[][] } points array of coords arrays ([[x1, y1], [x2, y2], ...])
139+ * @param {function } done
140+ */
141+ const polygonKonva = async ( points , done ) => {
142+ const delay = ( ) => new Promise ( resolve => setTimeout ( resolve , 10 ) ) ;
143+ const stage = window . Konva . stages [ 0 ] ;
144+ const firstCoords = points [ 0 ] ;
145+ for ( let point of points ) {
146+ stage . fire ( "click" , { evt : { offsetX : point [ 0 ] , offsetY : point [ 1 ] } } ) ;
147+ await delay ( ) ;
148+ }
149+
150+ // for closing the Polygon we should place cursor over the first point
151+ const firstPoint = stage . getIntersection ( { x : firstCoords [ 0 ] , y : firstCoords [ 1 ] } ) ;
152+ firstPoint . fire ( "mouseover" ) ;
153+ await delay ( ) ;
154+ // and only after that we can click on it
155+ firstPoint . fire ( "click" ) ;
156+ done ( ) ;
157+ } ;
158+
159+ /**
160+ * Click and hold, move the cursor (with one pause in the middle) and release the mouse
161+ * @param {number } x
162+ * @param {number } y
163+ * @param {number } shiftX
164+ * @param {number } shiftY
165+ * @param {function } done
166+ */
167+ const dragKonva = async ( x , y , shiftX , shiftY , done ) => {
168+ const stage = window . Konva . stages [ 0 ] ;
169+ stage . fire ( "mousedown" , { evt : { offsetX : x , offsetY : y } } ) ;
170+ // await delay(10);
171+ stage . fire ( "mousemove" , { evt : { offsetX : x + ( shiftX >> 1 ) , offsetY : y + ( shiftY >> 1 ) } } ) ;
172+ // await delay(10);
173+ // we should move the cursor to the last point and only after that release the mouse
174+ stage . fire ( "mousemove" , { evt : { offsetX : x + shiftX , offsetY : y + shiftY } } ) ;
175+ // await delay(10);
176+ // because some events work on mousemove and not on mouseup
177+ stage . fire ( "mouseup" , { evt : { offsetX : x + shiftX , offsetY : y + shiftY } } ) ;
178+ done ( ) ;
179+ } ;
180+
43181const serialize = ( ) => window . Htx . completionStore . selected . serializeCompletion ( ) ;
44182
45- module . exports = { initLabelStudio, emulateClick, clickRect, serialize } ;
183+ module . exports = {
184+ initLabelStudio,
185+ waitForImage,
186+ delay,
187+
188+ getSizeConvertor,
189+ convertToFixed,
190+
191+ emulateClick,
192+ clickRect,
193+ clickKonva,
194+ clickMultipleKonva,
195+ polygonKonva,
196+ dragKonva,
197+
198+ serialize,
199+ } ;
0 commit comments