const assert = require("assert");
|
const { centerOfBbox } = require("./helpers");
|
|
Feature("Outliner");
|
|
const IMAGE =
|
"https://htx-pub.s3.us-east-1.amazonaws.com/examples/images/nick-owuor-astro-nic-visuals-wDifg5xc9Z4-unsplash.jpg";
|
|
Scenario("Basic details", async ({ I, LabelStudio, AtOutliner, AtDetails }) => {
|
const RESULT_LABELS = ["a", "b", "c"];
|
const getRectangleRegion = (results) => {
|
const region = results.find((item) => item.from_name === "rect" && item.type === "rectangle");
|
|
assert(region, "Rectangle region not found in serialized results");
|
return region;
|
};
|
const result = [
|
{
|
value: {
|
start: 0,
|
end: 4,
|
labels: ["a", "b", "c"],
|
},
|
id: "test_t_1",
|
from_name: "label",
|
to_name: "text",
|
type: "labels",
|
},
|
{
|
value: {
|
start: 5,
|
end: 6,
|
labels: [],
|
},
|
id: "test_t_2",
|
from_name: "label",
|
to_name: "text",
|
type: "labels",
|
},
|
{
|
value: {
|
x: 25,
|
y: 25,
|
width: 50,
|
height: 50,
|
},
|
id: "test_i_1",
|
from_name: "rect",
|
to_name: "img",
|
type: "rectangle",
|
},
|
{
|
original_width: 2242,
|
original_height: 2802,
|
image_rotation: 0,
|
value: {
|
x: 25,
|
y: 25,
|
width: 50,
|
height: 50,
|
rotation: 0,
|
},
|
id: "test_i_1",
|
from_name: "rect",
|
to_name: "img",
|
type: "rectangle",
|
origin: "manual",
|
},
|
{
|
original_width: 2242,
|
original_height: 2802,
|
image_rotation: 0,
|
value: {
|
x: 25,
|
y: 25,
|
width: 50,
|
height: 50,
|
rotation: 0,
|
rating: 4,
|
},
|
id: "test_i_1",
|
from_name: "rating",
|
to_name: "img",
|
type: "rating",
|
origin: "manual",
|
},
|
{
|
original_width: 2242,
|
original_height: 2802,
|
image_rotation: 0,
|
value: {
|
x: 25,
|
y: 25,
|
width: 50,
|
height: 50,
|
rotation: 0,
|
text: ["text", "area"],
|
},
|
id: "test_i_1",
|
from_name: "textarea",
|
to_name: "img",
|
type: "textarea",
|
origin: "manual",
|
},
|
{
|
original_width: 2242,
|
original_height: 2802,
|
image_rotation: 0,
|
value: {
|
x: 25,
|
y: 25,
|
width: 50,
|
height: 50,
|
rotation: 0,
|
choices: ["option 1", "option 2"],
|
},
|
id: "test_i_1",
|
from_name: "choices",
|
to_name: "img",
|
type: "choices",
|
origin: "manual",
|
},
|
];
|
const fillByPressKeyDown = (keysList) => {
|
for (const keys of keysList) {
|
for (let idx = 0; idx < keys.length; idx++) {
|
I.pressKeyDown(keys[idx]);
|
}
|
for (let idx = keys.length - 1; idx >= 0; idx--) {
|
I.pressKeyUp(keys[idx]);
|
}
|
}
|
};
|
|
I.amOnPage("/");
|
|
LabelStudio.init({
|
config: `
|
<View>
|
<Text name="text" value="$text"/>
|
<Labels name="label" toName="text" choice="multiple">
|
<Label value="a" hotkey="1" />
|
<Label value="b" hotkey="2" />
|
<Label value="c" hotkey="3" />
|
</Labels>
|
<Image name="img" value="$image"/>
|
<Rectangle name="rect" toName="img"/>
|
<Rating name="rating" toName="img" perRegion="true"/>
|
<Textarea name="textarea" toName="img" perRegion="true"/>
|
<Choices name="choices" toName="img" perRegion="true">
|
<Choice value="option 1"/>
|
<Choice value="option 2"/>
|
</Choices>
|
</View>
|
`,
|
data: {
|
text: "Just a text",
|
image: IMAGE,
|
},
|
annotations: [
|
{
|
id: "test",
|
result,
|
},
|
],
|
});
|
|
AtOutliner.seeRegions(3);
|
LabelStudio.waitForObjectsReady();
|
|
I.say("Select text region");
|
AtOutliner.clickRegion(1);
|
I.say("Check it's details");
|
for (const value of RESULT_LABELS) {
|
AtDetails.seeLabel(value);
|
}
|
AtDetails.seeLabels(RESULT_LABELS.length);
|
AtDetails.seeText("Just");
|
|
I.say("Select second text region");
|
AtOutliner.clickRegion(2);
|
I.say("Check it's details");
|
AtDetails.seeLabels(0);
|
AtDetails.seeText("a");
|
|
I.say("Select image region");
|
AtOutliner.clickRegion(3);
|
|
const isRelativeCoords = await LabelStudio.hasFF("fflag_fix_front_dev_3793_relative_coords_short");
|
|
if (isRelativeCoords) {
|
AtDetails.seeFieldWithValue("X", "25");
|
AtDetails.seeFieldWithValue("H", "50");
|
}
|
|
I.say("Check perregions displaying");
|
|
AtDetails.seeResultRating(4);
|
AtDetails.seeResultTextarea(["text", "area"]);
|
AtDetails.seeResultChoices(["option 1", "option 2"]);
|
|
I.say("Add new meta and check result");
|
AtDetails.clickEditMeta();
|
|
fillByPressKeyDown([["M"], ["Space"], ["1"], ["Shift", "Enter"], ["M"], ["Space"], ["2"], ["Enter"]]);
|
AtDetails.seeMeta("M 1");
|
AtDetails.seeMeta("M 2");
|
|
I.say("Add line to meta");
|
AtDetails.clickMeta();
|
fillByPressKeyDown([["Shift", "Enter"], ["3"], ["Enter"]]);
|
AtDetails.seeMeta("3");
|
AtDetails.dontSeeMeta("23");
|
|
I.say("Check that meta is saved correctly");
|
const resultWithMeta = await LabelStudio.serialize();
|
const regionWithMeta = getRectangleRegion(resultWithMeta);
|
|
assert.deepStrictEqual(regionWithMeta.meta?.text, ["M 1\nM 2\n3"]);
|
|
I.say("Remove meta");
|
AtDetails.clickMeta();
|
fillByPressKeyDown([["CommandOrControl", "a"], ["Backspace"], ["Enter"]]);
|
|
I.say("Check that meta is removed correctly");
|
const resultWithoutMeta = await LabelStudio.serialize();
|
const regionWithoutMeta = getRectangleRegion(resultWithoutMeta);
|
|
assert.deepStrictEqual(resultWithoutMeta[2].meta, undefined);
|
}).retry(3);
|
|
Scenario("Panels manipulations", async ({ I, LabelStudio, AtPanels }) => {
|
I.amOnPage("/");
|
LabelStudio.init({
|
config: `
|
<View>
|
<Text name="text" value="$text"/>
|
</View>
|
`,
|
data: {
|
text: "Just a text",
|
},
|
annotations: [
|
{
|
id: "test",
|
result: [],
|
},
|
],
|
});
|
|
const AtOutlinerPanel = AtPanels.usePanel(AtPanels.PANEL.OUTLINER);
|
const AtDetailsPanel = AtPanels.usePanel(AtPanels.PANEL.DETAILS);
|
|
I.say("See panels at default positions");
|
AtOutlinerPanel.seePanelAttachedLeft();
|
AtDetailsPanel.seePanelAttachedRight();
|
|
I.say("They should be fully visible");
|
AtOutlinerPanel.seePanelBody();
|
AtDetailsPanel.seePanelBody();
|
I.say("and not collapsed");
|
AtOutlinerPanel.dontSeeExpandButton();
|
AtDetailsPanel.dontSeeExpandButton();
|
|
I.say("Collapse both panels");
|
AtOutlinerPanel.collapsePanel();
|
AtDetailsPanel.collapsePanel();
|
|
I.say("Make sure there is no body or collapse button");
|
AtOutlinerPanel.dontSeePanelBody();
|
AtDetailsPanel.dontSeePanelBody();
|
AtOutlinerPanel.dontSeeСollapseButton();
|
AtDetailsPanel.dontSeeСollapseButton();
|
AtOutlinerPanel.seeExpandButton();
|
AtDetailsPanel.seeExpandButton();
|
|
I.say("Try to move collapsed panel");
|
await AtOutlinerPanel.dragPanelBy(400, 0);
|
|
I.say("Check that nothing changes");
|
AtOutlinerPanel.seePanelAttachedLeft();
|
AtOutlinerPanel.dontSeePanelBody();
|
AtOutlinerPanel.dontSeeСollapseButton();
|
|
I.say("Expand both panels");
|
AtOutlinerPanel.expandPanel();
|
AtDetailsPanel.expandPanel();
|
|
I.say("Make sure that body and collapse appears");
|
AtOutlinerPanel.seePanelBody();
|
AtDetailsPanel.seePanelBody();
|
AtOutlinerPanel.seeСollapseButton();
|
AtDetailsPanel.seeСollapseButton();
|
AtOutlinerPanel.dontSeeExpandButton();
|
AtDetailsPanel.dontSeeExpandButton();
|
|
I.say("Try to drag one panel over another");
|
await AtOutlinerPanel.dragPanelToElement(AtDetailsPanel.locatePanel());
|
I.say("It should not affect other panel");
|
AtDetailsPanel.seePanelAttachedRight();
|
I.say("But it should detach dragged panel");
|
AtOutlinerPanel.seePanelDetached();
|
{
|
I.say("And x coordinate of panels should be equal due to limitation of moving panel through the border");
|
const panel1HeaderBbox = await AtOutlinerPanel.grabHeaderBbox();
|
const panel2HeaderBbox = await AtOutlinerPanel.grabHeaderBbox();
|
|
assert.strictEqual(panel1HeaderBbox.x, panel2HeaderBbox.x);
|
}
|
I.say("Drag panel somewhere to the center of the screen");
|
{
|
let panelBbox = await AtOutlinerPanel.grabPanelBbox();
|
const panelsContainerBbox = await AtPanels.grabPanelsContainerBbox();
|
const panelsContainerCenter = centerOfBbox(panelsContainerBbox);
|
|
await AtOutlinerPanel.dragPanelTo(panelsContainerCenter.x, panelsContainerCenter.y - panelBbox.height / 2);
|
|
I.say("Try to resize panel in all directions");
|
panelBbox = await AtOutlinerPanel.grabPanelBbox();
|
{
|
I.say("drag TopLeft corner");
|
await AtOutlinerPanel.dragResizerBy(-1, -2, AtOutlinerPanel.resizeTopLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, -1);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, -2);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, 1);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 2);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag TopRight corner");
|
await AtOutlinerPanel.dragResizerBy(-1, -2, AtOutlinerPanel.resizeTopRight);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 0);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, -2);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, -1);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 2);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag BottomRight corner");
|
await AtOutlinerPanel.dragResizerBy(3, 5, AtOutlinerPanel.resizeBottomRight);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 0);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, 0);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, 3);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 5);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag BottomLeft corner");
|
await AtOutlinerPanel.dragResizerBy(3, -5, AtOutlinerPanel.resizeBottomLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 3);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, 0);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, -3);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, -5);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag Top border");
|
await AtOutlinerPanel.dragResizerBy(10, -10, AtOutlinerPanel.resizeTop, 2);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 0);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, -10);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, 0);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 10);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag Right border");
|
await AtOutlinerPanel.dragResizerBy(100, -7, AtOutlinerPanel.resizeRight, 2);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 0);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, 0);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, 100);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 0);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag Bottom border");
|
await AtOutlinerPanel.dragResizerBy(11, 11, AtOutlinerPanel.resizeBottom);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 0);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, 0);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, 0);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 11);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("drag Left border");
|
await AtOutlinerPanel.dragResizerBy(7, -7, AtOutlinerPanel.resizeLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert.strictEqual(newPanelBbox.x - panelBbox.x, 7);
|
assert.strictEqual(newPanelBbox.y - panelBbox.y, 0);
|
assert.strictEqual(newPanelBbox.width - panelBbox.width, -7);
|
assert.strictEqual(newPanelBbox.height - panelBbox.height, 0);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("Check maximal size restriction");
|
await AtOutlinerPanel.dragResizerBy(-1000, -1000, AtOutlinerPanel.resizeTopLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert(newPanelBbox.x - panelBbox.x < 500);
|
assert(newPanelBbox.y - panelBbox.y < 500);
|
assert(newPanelBbox.width - panelBbox.width > -500);
|
assert(newPanelBbox.height - panelBbox.height > -500);
|
panelBbox = newPanelBbox;
|
}
|
{
|
I.say("Check minimal size restriction");
|
await AtOutlinerPanel.dragResizerBy(panelBbox.width, panelBbox.height + 50, AtOutlinerPanel.resizeTopLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert(newPanelBbox.width > 100);
|
assert(newPanelBbox.height > 100);
|
assert(newPanelBbox.x < panelBbox.x + panelBbox.width - 100);
|
assert(newPanelBbox.y < panelBbox.y + panelBbox.height - 100);
|
panelBbox = newPanelBbox;
|
}
|
}
|
|
I.say("Move details to the left socket");
|
await AtDetailsPanel.dragPanelToLeftSocket();
|
AtDetailsPanel.seePanelAttachedLeft();
|
|
{
|
I.say("Move outliner to the right socket by moving to the left (check that there is some gap)");
|
const panelBbox = await AtOutlinerPanel.grabPanelBbox();
|
const panelContainerWidth = await AtOutlinerPanel.grabPanelsContainerBbox("width");
|
const shiftX = 50;
|
|
await AtOutlinerPanel.dragPanelTo(panelContainerWidth - panelBbox.width / 2 - shiftX, panelBbox.y);
|
AtOutlinerPanel.seePanelDetached();
|
await AtOutlinerPanel.dragResizerBy(shiftX, 0, AtOutlinerPanel.resizeRight);
|
AtOutlinerPanel.seePanelDetached();
|
await AtOutlinerPanel.dragPanelBy(-5, 0);
|
AtOutlinerPanel.seePanelAttachedRight();
|
}
|
I.say("Attached panels should be resizable");
|
|
{
|
const panelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
await AtOutlinerPanel.dragResizerBy(-10, 0, AtOutlinerPanel.resizeLeft);
|
const newPanelBbox = await AtOutlinerPanel.grabPanelBbox();
|
|
assert(newPanelBbox.width - panelBbox.width, 10);
|
}
|
{
|
const panelBbox = await AtDetailsPanel.grabPanelBbox();
|
|
await AtDetailsPanel.dragResizerBy(10, 0, AtOutlinerPanel.resizeRight);
|
const newPanelBbox = await AtDetailsPanel.grabPanelBbox();
|
|
assert(newPanelBbox.width - panelBbox.width, 10);
|
}
|
|
I.say("Collapse is still working");
|
AtOutlinerPanel.collapsePanel();
|
AtOutlinerPanel.dontSeePanelBody();
|
AtOutlinerPanel.dontSeeСollapseButton();
|
AtOutlinerPanel.seeExpandButton();
|
I.say("Drag panel somewhere to the center of the screen");
|
{
|
const panelBbox = await AtDetailsPanel.grabPanelBbox();
|
const panelsContainerBbox = await AtPanels.grabPanelsContainerBbox();
|
const panelsContainerCenter = centerOfBbox(panelsContainerBbox);
|
|
await AtDetailsPanel.dragPanelTo(panelsContainerCenter.x, panelsContainerCenter.y - panelBbox.height / 2);
|
AtDetailsPanel.seePanelDetached();
|
}
|
I.say("Collapse detached panel");
|
AtDetailsPanel.collapsePanel();
|
AtDetailsPanel.dontSeePanelBody();
|
AtDetailsPanel.dontSeeСollapseButton();
|
AtDetailsPanel.seeExpandButton();
|
|
I.say("Make sure that it is still movable");
|
await AtDetailsPanel.dragPanelToLeftSocket();
|
I.say("and attachable");
|
AtDetailsPanel.seePanelAttachedLeft();
|
I.say("and expandable");
|
AtDetailsPanel.expandPanel();
|
AtDetailsPanel.seePanelBody();
|
AtDetailsPanel.seeСollapseButton();
|
AtDetailsPanel.dontSeeExpandButton();
|
});
|