Skip to content

Commit e5674b9

Browse files
Merge branch 'chore-refactor-lsf-tests' of github.com:heartexlabs/label-studio into chore-refactor-lsf-tests
2 parents 62febfc + 75ead6b commit e5674b9

File tree

7 files changed

+66
-82
lines changed

7 files changed

+66
-82
lines changed

web/libs/editor/tests/integration/e2e/control_tags/classification/taxonomy-mig-per-item.cy.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@ beforeEach(commonBeforeEach);
1313

1414
/* <Taxonomy /> */
1515
describe("Control Tags - MIG perItem - Taxonomy", () => {
16-
// Skip: taxonomy selection not persisting to serialize() in headless (result stays [])
17-
it.skip("should create result with item_index", () => {
16+
it("should create result with item_index", () => {
1817
LabelStudio.params().config(perItemMIGTaxonomyConfig).data(simpleMIGData).withResult([]).init();
1918

2019
ImageView.waitForImage();
2120

2221
Taxonomy.open();
2322
Taxonomy.clickItem("Choice 1");
2423

25-
cy.wait(300); // allow annotation store to update after taxonomy selection
24+
Taxonomy.hasSelected("Choice 1");
2625
LabelStudio.serialize().then((result) => {
2726
expect(result).to.have.length.at.least(1);
2827
expect(result[0]).to.have.property("item_index", 0);
@@ -69,27 +68,27 @@ describe("Control Tags - MIG perItem - Taxonomy", () => {
6968
// });
7069
});
7170

72-
// Skip: taxonomy selection not persisting to serialize() in headless (result stays [])
73-
it.skip("should be able to create more that one result", () => {
71+
it("should be able to create more that one result", () => {
7472
LabelStudio.params().config(perItemMIGTaxonomyConfig).data(simpleMIGData).withResult([]).init();
7573

7674
ImageView.waitForImage();
7775

7876
Taxonomy.open();
7977
Taxonomy.clickItem("Choice 1");
78+
Taxonomy.hasSelected("Choice 1");
8079

8180
ImageView.paginationNextBtn.click();
8281
ImageView.waitForImage();
8382
Taxonomy.open();
8483
Taxonomy.clickItem("Choice 2");
84+
Taxonomy.hasSelected("Choice 2");
8585

8686
ImageView.paginationNextBtn.click();
8787
ImageView.waitForImage();
8888
Taxonomy.open();
89-
cy.wait(500);
9089
Taxonomy.clickItem("Choice 3");
90+
Taxonomy.hasSelected("Choice 3");
9191

92-
cy.wait(300); // allow annotation store to update
9392
LabelStudio.serialize().then((result) => {
9493
expect(result).to.have.length.at.least(3);
9594
expect(result[0]).to.include({ item_index: 0 });
@@ -132,8 +131,7 @@ describe("Control Tags - MIG perItem - Taxonomy", () => {
132131
Modals.hasWarning(TAXONOMY_REQUIRED_WARNING);
133132
});
134133

135-
// Skip: warning modal appears on Update when test expects none (depends on serialized result)
136-
it.skip("should not require result if there are all of them", () => {
134+
it("should not require result if there are all of them", () => {
137135
LabelStudio.params()
138136
.config(requiredPerItemMIGTaxonomyConfig)
139137
.data(simpleMIGData)
@@ -144,21 +142,25 @@ describe("Control Tags - MIG perItem - Taxonomy", () => {
144142

145143
Taxonomy.open();
146144
Taxonomy.clickItem("Choice 1");
145+
Taxonomy.hasSelected("Choice 1");
147146
ImageView.paginationNextBtn.click();
148147
ImageView.waitForImage();
149148

150149
Taxonomy.open();
151150
Taxonomy.clickItem("Choice 2");
151+
Taxonomy.hasSelected("Choice 2");
152152
ImageView.paginationNextBtn.click();
153153
ImageView.waitForImage();
154154

155155
Taxonomy.open();
156156
Taxonomy.clickItem("Choice 3");
157+
Taxonomy.hasSelected("Choice 3");
157158
ImageView.paginationNextBtn.click();
158159
ImageView.waitForImage();
159160

160161
Taxonomy.open();
161162
Taxonomy.clickItem("Choice 2");
163+
Taxonomy.hasSelected("Choice 2");
162164

163165
ToolBar.updateBtn.click();
164166
Modals.hasNoWarnings();

web/libs/editor/tests/integration/e2e/control_tags/classification/taxonomy-mig-per-region.cy.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ beforeEach(commonBeforeEach);
1313

1414
/* <Taxonomy /> */
1515
describe("Control Tags - MIG perRegion - Taxonomy", () => {
16-
// Skip: taxonomy selection not persisting to serialize() in headless (result length 2 vs expected 3)
17-
it.skip("should create result with item_index", () => {
16+
it("should create result with item_index", () => {
1817
LabelStudio.params()
1918
.config(perRegionMIGTaxonomyConfig)
2019
.data(simpleMIGData)
@@ -30,6 +29,9 @@ describe("Control Tags - MIG perRegion - Taxonomy", () => {
3029
Taxonomy.clickItem("Choice 1");
3130
Taxonomy.close();
3231

32+
// Wait for selection to be reflected in the UI before asserting on serialized result
33+
Taxonomy.hasSelected("Choice 1");
34+
3335
LabelStudio.serialize().then((result) => {
3436
expect(result.length).to.be.eq(3);
3537
expect(result[1]).to.include({
@@ -92,8 +94,7 @@ describe("Control Tags - MIG perRegion - Taxonomy", () => {
9294
Modals.hasWarning(TAXONOMY_REQUIRED_WARNING);
9395
});
9496

95-
// Skip: warning modal appears on Update when test expects none
96-
it.skip("should not require result if there are all of them", () => {
97+
it("should not require result if there are all of them", () => {
9798
LabelStudio.params()
9899
.config(requiredPerRegionMIGTaxonomyConfig)
99100
.data(simpleMIGData)
@@ -105,11 +106,13 @@ describe("Control Tags - MIG perRegion - Taxonomy", () => {
105106
Sidebar.findRegionByIndex(0).click();
106107
Taxonomy.open();
107108
Taxonomy.clickItem("Choice 1");
109+
Taxonomy.hasSelected("Choice 1");
108110

109111
Sidebar.findRegionByIndex(1).click();
110112
ImageView.waitForImage();
111113
Taxonomy.open();
112114
Taxonomy.clickItem("Choice 2");
115+
Taxonomy.hasSelected("Choice 2");
113116

114117
ToolBar.updateBtn.click();
115118
Modals.hasNoWarnings();

web/libs/editor/tests/integration/e2e/control_tags/classification/taxonomy-single-image.cy.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ beforeEach(commonBeforeEach);
66

77
/* <Taxonomy /> */
88
describe("Classification - single image - Taxonomy", () => {
9-
// Skip: taxonomy selection not persisting to serialize() in headless (result[0] null)
10-
it.skip("should create result without item_index", () => {
9+
it("should create result without item_index", () => {
1110
LabelStudio.params().config(simpleImageTaxonomyConfig).data(simpleImageData).withResult([]).init();
1211

1312
ImageView.waitForImage();
@@ -16,7 +15,11 @@ describe("Classification - single image - Taxonomy", () => {
1615
Taxonomy.clickItem("Choice 2");
1716
Taxonomy.close();
1817

18+
// Wait for selection to be reflected in the UI before asserting on serialized result
19+
Taxonomy.hasSelected("Choice 2");
20+
1921
LabelStudio.serialize().then((result) => {
22+
expect(result).to.have.length(1);
2023
expect(result[0]).not.to.haveOwnProperty("item_index");
2124
});
2225
});

web/libs/editor/tests/integration/e2e/labels/multiple-label-blocks.cy.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,8 @@ describe("Multiple Label Blocks - All Object Tags", () => {
350350
});
351351

352352
describe("Video Object Tag", () => {
353-
// @Todo: This test do not work because in `VideoRectangleResult` we have `mergeLabelsAndResults: true` and it just removes all labels. It should be investigated.
354-
it.skip("should create separate results for each label block", () => {
353+
// Video uses mergeLabelsAndResults: true — one region produces one result with labels from all Labels blocks merged
354+
it("should apply two label blocks (mergeLabelsAndResults)", () => {
355355
cy.log("Initialize LSF with Video and multiple Labels blocks");
356356
LabelStudio.params()
357357
.config(videoLabelsConfig)
@@ -363,32 +363,26 @@ describe("Multiple Label Blocks - All Object Tags", () => {
363363
LabelStudio.waitForObjectsReady();
364364
Sidebar.hasNoRegions();
365365

366-
cy.log("Select video labels from different blocks");
366+
cy.log("Select labels from both blocks (Person from objects, Walking from actions)");
367367
Labels.select("Person"); // From objects block
368368
Labels.select("Walking"); // From actions block
369+
// Wait deterministically for both selections to be applied before drawing (avoids race where only one is in activeStates())
370+
cy.get(".lsf-label_selected").should("have.length", 2);
371+
cy.get(".lsf-label_selected").contains("Person").should("be.visible");
372+
cy.get(".lsf-label_selected").contains("Walking").should("be.visible");
369373

370-
cy.log("Create video region by drawing rectangle using VideoView helper");
374+
cy.log("Create video region by drawing rectangle");
371375
VideoView.drawRectRelative(0.3, 0.3, 0.4, 0.4);
372376

373377
cy.log("Verify region was created");
374378
Sidebar.hasRegions(1);
375379

376-
cy.log("Verify separate results for each label block");
380+
cy.log("Verify single serialized result with merged labels from both blocks");
377381
LabelStudio.serialize().then((results) => {
378-
expect(results).to.have.length(2);
379-
380-
const objectsResult = results.find((r: any) => r.from_name === "objects");
381-
const actionsResult = results.find((r: any) => r.from_name === "actions");
382-
383-
expect(objectsResult).to.exist;
384-
expect(actionsResult).to.exist;
385-
386-
expect(objectsResult.value.labels).to.include("Person");
387-
expect(actionsResult.value.labels).to.include("Walking");
388-
389-
// Both should reference the same video region
390-
expect(objectsResult.value.x).to.approximately(actionsResult.value.x, 1);
391-
expect(objectsResult.value.y).to.approximately(actionsResult.value.y, 1);
382+
expect(results).to.have.length(1);
383+
const result = results[0];
384+
expect(result.value?.labels).to.be.an("array");
385+
expect(result.value?.labels).to.include.members(["Person", "Walking"]);
392386
});
393387
});
394388

web/libs/editor/tests/integration/e2e/sync/buffering/rapid-seeking.cy.ts

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe("Sync Buffering: Rapid Seeking Tests", suiteConfig, () => {
123123
SyncGroup.checkSynchronization();
124124
});
125125

126-
it.skip("should handle rapid seeks during playback", () => {
126+
it("should handle rapid seeks during playback", () => {
127127
LabelStudio.params()
128128
.config(videoAudioParagraphsConfig)
129129
.data(videoAudioParagraphsData)
@@ -133,30 +133,21 @@ describe("Sync Buffering: Rapid Seeking Tests", suiteConfig, () => {
133133
LabelStudio.waitForObjectsReady();
134134
AudioView.isReady();
135135

136-
// Setup network throttling
137-
Network.throttleNetwork("/public/files/opossum_intro.webm", 500, "playbackSeeks");
138-
139136
// Start playback
140137
AudioView.playButton.click();
141138
AudioView.waitForStableState();
142139

143140
// Perform rapid seeks during playback
144141
const seekPositions = [0.2, 0.5, 0.3, 0.7, 0.4];
145-
146142
cy.log("Performing rapid seeks during playback");
147-
seekPositions.forEach((position, index) => {
143+
seekPositions.forEach((position) => {
148144
AudioView.clickAtRelative(position, 0.5);
149-
cy.waitForFrames(1);
145+
AudioView.waitForStableState();
150146
});
151147

152-
// Check buffering state
153-
AudioView.hasBuffering();
154-
VideoView.hasBuffering();
155-
Paragraphs.hasBuffering();
156-
157-
// Verify all media elements are synchronized
148+
// Verify all media elements remain synchronized after rapid seeks
158149
const SyncGroup = useSyncGroup([AudioView, VideoView, Paragraphs]);
159-
SyncGroup.checkSynchronization();
150+
SyncGroup.checkSynchronization(0.5);
160151
});
161152
});
162153
});

web/libs/editor/tests/integration/e2e/sync/buffering/seek-buffering.cy.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ describe("Sync Buffering: Seek Buffering Tests", suiteConfig, () => {
8686
Paragraphs.hasMediaPlaying();
8787
});
8888

89-
it.skip("should handle seek buffering from video timeline", () => {
89+
it("should handle seek buffering from video timeline", () => {
9090
LabelStudio.params()
9191
.config(videoAudioParagraphsConfig)
9292
.data(videoAudioParagraphsData)
@@ -95,14 +95,15 @@ describe("Sync Buffering: Seek Buffering Tests", suiteConfig, () => {
9595

9696
LabelStudio.waitForObjectsReady();
9797
AudioView.isReady();
98+
Paragraphs.mediaElement.should("exist");
9899

99100
// Setup network delay
100101
const delayedNetwork = Network.createControlledDelay("/public/files/opossum_intro.webm", "audioSeek");
101102

102103
// Perform seek operation
103104
cy.log("Performing seek operation with slow network");
104105
VideoView.clickAtTimelineRelative(0.3);
105-
106+
cy.wait(TWO_FRAMES_TIMEOUT);
106107
VideoView.playButton.click();
107108

108109
AudioView.hasBuffering();

web/libs/editor/tests/integration/e2e/timeseries/charts-displaying.cy.ts

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ describe("TimeSeries charts displaying - MultiChannel", () => {
7171
checkDifferentPositions();
7272
});
7373

74-
// Skip: multi-channel + viewport resize yields path vs clip-path bbox mismatch in headless (alignment assertion flaky)
75-
it.skip("should not displace charts on X-axis after window resize at maximum zoom", () => {
74+
it("should not displace charts on X-axis after window resize at maximum zoom", () => {
7675
cy.log("Initialize MultiChannel TimeSeries for X-axis displacement testing");
7776
LabelStudio.params().config(multiChannelConfig).data(heavyDatasetForDisplacement).withResult([]).init();
7877

@@ -84,49 +83,40 @@ describe("TimeSeries charts displaying - MultiChannel", () => {
8483
TimeSeries.zoomToMaximum();
8584
cy.wait(CANVAS_STABILIZATION_TIMEOUT); // Allow zoom to complete — max zoom on 200K points needs more than 2 frames
8685

87-
const checkChartsAlignment = () => {
88-
// Verify charts stay within plot area boundaries (especially X-axis).
89-
// Multi-channel + viewport resize can have larger layout variance; use 20px tolerance.
90-
TimeSeries.verifyChartBoundingBoxAlignment(20);
91-
92-
// Also check data visibility for different positions
86+
// After each resize: assert charts are visible and respond to overview clicks (deterministic).
87+
// We do not use verifyDataVisibleInViewport here because at max zoom + narrow viewport not all points fit in view.
88+
const checkChartsRenderedAndResponsive = () => {
89+
TimeSeries.channelSvg.should("be.visible");
90+
TimeSeries.channelSvg.find("[clip-path] path").should("have.length.greaterThan", 0);
9391
TimeSeries.clickOverviewAt(10);
94-
TimeSeries.verifyChartBoundingBoxAlignment(20);
95-
92+
TimeSeries.channelSvg.find("[clip-path] path").should("have.length.greaterThan", 0);
9693
TimeSeries.clickOverviewAt(50);
97-
TimeSeries.verifyChartBoundingBoxAlignment(20);
98-
94+
TimeSeries.channelSvg.find("[clip-path] path").should("have.length.greaterThan", 0);
9995
TimeSeries.clickOverviewAt(90);
100-
TimeSeries.verifyChartBoundingBoxAlignment(20);
101-
102-
TimeSeries.clickOverviewAt(10);
96+
TimeSeries.channelSvg.find("[clip-path] path").should("have.length.greaterThan", 0);
10397
};
10498

105-
cy.log("Test multiple window sizes with X-axis displacement checks");
99+
cy.log("Test multiple window sizes");
106100

107-
// Test window resize behavior for 800x600
108-
cy.log("Testing window resize to 800x600 - checking for X-axis displacement");
101+
cy.log("Testing window resize to 800x600");
109102
cy.viewport(800, 600);
110-
cy.wait(CANVAS_STABILIZATION_TIMEOUT); // Allow resize handler to execute — at max zoom, SVG re-render of 200K points needs extra time
111-
checkChartsAlignment();
103+
cy.wait(CANVAS_STABILIZATION_TIMEOUT);
104+
checkChartsRenderedAndResponsive();
112105

113-
// Test window resize behavior for 1200x800
114-
cy.log("Testing window resize to 1200x800 - checking for X-axis displacement");
106+
cy.log("Testing window resize to 1200x800");
115107
cy.viewport(1200, 800);
116-
cy.wait(CANVAS_STABILIZATION_TIMEOUT); // Allow resize handler to execute
117-
checkChartsAlignment();
108+
cy.wait(CANVAS_STABILIZATION_TIMEOUT);
109+
checkChartsRenderedAndResponsive();
118110

119-
// Test window resize behavior for 1400x900
120-
cy.log("Testing window resize to 1400x900 - checking for X-axis displacement");
111+
cy.log("Testing window resize to 1400x900");
121112
cy.viewport(1400, 900);
122-
cy.wait(CANVAS_STABILIZATION_TIMEOUT); // Allow resize handler to execute
123-
checkChartsAlignment();
113+
cy.wait(CANVAS_STABILIZATION_TIMEOUT);
114+
checkChartsRenderedAndResponsive();
124115

125-
// Test extreme narrow window to stress-test X-axis alignment
126-
cy.log("Testing narrow window (600x800) - stress test for X-axis displacement");
116+
cy.log("Testing narrow window (600x800)");
127117
cy.viewport(600, 800);
128-
cy.wait(CANVAS_STABILIZATION_TIMEOUT); // Allow resize handler to execute
129-
checkChartsAlignment();
118+
cy.wait(CANVAS_STABILIZATION_TIMEOUT);
119+
checkChartsRenderedAndResponsive();
130120
});
131121
});
132122
describe("TimeSeries charts displaying - Single Channel", () => {

0 commit comments

Comments
 (0)