const assert = require("assert");
|
|
Feature("Skip duplicates (textarea)");
|
|
const SKIP_DUPLICATES_ERROR = "There is already an entry with that text. Please enter unique text.";
|
|
const scenarioDataTable = new DataTable(["scenarioKey"]);
|
|
const SK_SIMPLE = "Simple textarea";
|
const SK_PER_REGION = "Per region";
|
const SK_OCR = "Ocr";
|
|
scenarioDataTable.add([SK_SIMPLE]);
|
scenarioDataTable.add([SK_PER_REGION]);
|
scenarioDataTable.add([SK_OCR]);
|
|
const SCENARIO_PARAMS = {
|
[SK_SIMPLE]: {
|
data: { question: "Is it a question?" },
|
config: `<View>
|
<Text name="question" value="$question"/>
|
<TextArea name="answer" toName="question" skipDuplicates="true" required="true"/>
|
</View>`,
|
fieldSelector: '[name="answer"]',
|
text: "Isn't it?",
|
textAlt: "isn't IT?",
|
textOther: "Maybe",
|
},
|
[SK_PER_REGION]: {
|
data: {
|
image: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Html_headers.png/640px-Html_headers.png",
|
},
|
config: `<View>
|
<Image name="image" value="$image"></Image>
|
<Rectangle name="imageRectangle" toName="image"/>
|
<TextArea name="text" toName="image" editable="true" perRegion="true"
|
placeholder="Recognized Text" skipDuplicates="true" />
|
</View>
|
`,
|
annotations: [
|
{
|
id: "test",
|
result: [
|
{
|
id: "id_1",
|
from_name: "imageRectangle",
|
to_name: "image",
|
type: "rectangle",
|
value: {
|
x: 0.625,
|
y: 1.183431952662722,
|
width: 34.375,
|
height: 5.719921104536489,
|
},
|
},
|
],
|
},
|
],
|
shouldSelectRegion: true,
|
fieldSelector: '[name="text"]',
|
text: 'The "H1" Header',
|
textAlt: 'the "h1" HEADER',
|
textOther: "Wrong text",
|
},
|
[SK_OCR]: {
|
data: {
|
image: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Html_headers.png/640px-Html_headers.png",
|
},
|
config: `<View>
|
<Image name="image" value="$image"></Image>
|
<Rectangle name="imageRectangle" toName="image"/>
|
<TextArea name="ocr" toName="image" editable="true" perRegion="true"
|
placeholder="Recognized Text" displayMode="region-list" skipDuplicates="true" maxsubmissions="5"/>
|
</View>
|
`,
|
annotations: [
|
{
|
id: "test",
|
result: [
|
{
|
id: "id_1",
|
from_name: "imageRectangle",
|
to_name: "image",
|
type: "rectangle",
|
value: {
|
x: 0.625,
|
y: 1.183431952662722,
|
width: 34.375,
|
height: 5.719921104536489,
|
},
|
},
|
],
|
},
|
],
|
shouldSelectRegion: true,
|
fieldSelector: ".lsf-textarea-tag__form input",
|
text: 'The "H1" Header',
|
textAlt: 'the "h1" HEADER',
|
textOther: "Wrong text",
|
},
|
};
|
|
Data(scenarioDataTable).Scenario(
|
"Skip duplicate values on entering",
|
async ({ I, LabelStudio, AtOutliner, Modals, current }) => {
|
const scenarioKey = current.scenarioKey;
|
const { data, config, annotations, shouldSelectRegion, fieldSelector, text, textAlt, textOther } =
|
SCENARIO_PARAMS[scenarioKey];
|
|
I.amOnPage("/");
|
LabelStudio.init({
|
data,
|
config,
|
annotations,
|
});
|
LabelStudio.waitForObjectsReady();
|
|
if (shouldSelectRegion) AtOutliner.clickRegion(1);
|
|
I.fillField(fieldSelector, text);
|
I.pressKey("Enter");
|
|
I.fillField(fieldSelector, text);
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.fillField(fieldSelector, textAlt);
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.fillField(fieldSelector, textOther);
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
I.fillField(fieldSelector, textOther);
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.fillField(fieldSelector, text);
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
// check that there are no warnings and errors
|
I.updateAnnotation();
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
},
|
);
|
|
Scenario("Independent skip duplicate values", async ({ I, LabelStudio, AtOutliner, Modals }) => {
|
I.amOnPage("/");
|
LabelStudio.init({
|
data: { letter: "Aa" },
|
config: `<View>
|
<Text name="letter" value="$letter"/>
|
<Labels name="label" toName="letter">
|
<Label value="Letter A" background="yellow"/>
|
</Labels>
|
<TextArea name="perText" toName="letter" skipDuplicates="true"/>
|
<TextArea name="perText2" toName="letter" skipDuplicates="true"/>
|
<TextArea name="perRegion" toName="letter" skipDuplicates="true" perRegion="true" maxsubmissions="5"/>
|
<TextArea name="perRegionAndAside" toName="letter" skipDuplicates="true" perRegion="true" maxsubmissions="5" displayMode="region-list"/>
|
</View>`,
|
annotations: [
|
{
|
id: "test",
|
result: [
|
{
|
id: "letter_A",
|
from_name: "label",
|
to_name: "letter",
|
type: "labels",
|
value: { start: 0, end: 1, labels: ["Letter A"], text: "A" },
|
},
|
{
|
id: "letter_a",
|
from_name: "label",
|
to_name: "letter",
|
type: "labels",
|
value: { start: 1, end: 2, labels: ["Letter A"], text: "a" },
|
},
|
],
|
},
|
],
|
});
|
|
I.fillField('[name="perText"]', "A");
|
I.pressKey("Enter");
|
|
I.fillField('[name="perText2"]', "A");
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
AtOutliner.clickRegion(1);
|
|
I.fillField('[name="perRegion"]', "A");
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "A");
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
AtOutliner.clickRegion(2);
|
|
I.fillField('[name="perRegion"]', "A");
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "A");
|
I.pressKey("Enter");
|
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
});
|
|
/**
|
* @TODO: Do something with lost functionality of removing textarea item in `region-list` displayed mode
|
*/
|
Scenario.skip("Skip duplicate values on editing", async ({ I, LabelStudio, AtOutliner, Modals }) => {
|
I.amOnPage("/");
|
LabelStudio.init({
|
data: { letter: "Aa" },
|
config: `<View>
|
<Text name="letter" value="$letter"/>
|
<Labels name="label" toName="letter">
|
<Label value="Letter A" background="yellow"/>
|
</Labels>
|
<TextArea name="perText" toName="letter" skipDuplicates="true" editable="true"/>
|
<TextArea name="perRegion" toName="letter" skipDuplicates="true" perRegion="true" maxsubmissions="5" editable="true"/>
|
<TextArea name="perRegionAndAside" toName="letter" skipDuplicates="true" perRegion="true" maxsubmissions="5" displayMode="region-list" editable="true"/>
|
</View>`,
|
annotations: [
|
{
|
id: "test",
|
result: [
|
{
|
id: "letter_A",
|
from_name: "label",
|
to_name: "letter",
|
type: "labels",
|
value: { start: 0, end: 1, labels: ["Letter A"], text: "A" },
|
},
|
{
|
id: "letter_a",
|
from_name: "label",
|
to_name: "letter",
|
type: "labels",
|
value: { start: 1, end: 2, labels: ["Letter A"], text: "a" },
|
},
|
],
|
},
|
],
|
});
|
LabelStudio.waitForObjectsReady();
|
AtOutliner.seeRegions(2);
|
|
I.say("Check perText Textarea regions editing");
|
I.say("Create some random values in perText Textarea");
|
I.fillField('[name="perText"]', "A");
|
I.pressKey("Enter");
|
I.fillField('[name="perText"]', "1");
|
I.pressKey("Enter");
|
I.fillField('[name="perText"]', "letter");
|
I.pressKey("Enter");
|
I.fillField('[name="perText"]', "last");
|
I.pressKey("Enter");
|
|
I.say("Try to create duplicate value by editing");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(1),
|
);
|
I.pressKey("Backspace");
|
I.pressKey("A");
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.say("Check that these changes were not committed");
|
|
I.see("1", locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
I.dontSee("A", locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
|
I.say("Delete second region and check results after that");
|
I.click(
|
locate('[aria-label="Delete Region"]'),
|
locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
|
I.see("A", locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=1]")));
|
I.see(
|
"letter",
|
locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
I.see("last", locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=3]")));
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[2].value.text,
|
["A", "letter", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["A", "letter", "last"])} but ${
|
result[2].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to keep the same value after editing without errors");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(1),
|
);
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("letter").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.see(
|
"letter",
|
locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[2].value.text,
|
["A", "letter", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["A", "letter", "last"])} but ${
|
result[2].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to set different value by editing and do not get errors");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(1),
|
);
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("other").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.see("other", locate(".lsf-text-area").at(1).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[2].value.text,
|
["A", "other", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["A", "other", "last"])} but ${
|
result[2].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check perRegion Textarea regions editing");
|
AtOutliner.clickRegion(1);
|
I.say("Create some random values in perRegion Textarea");
|
I.fillField('[name="perRegion"]', "a");
|
I.pressKey("Enter");
|
I.fillField('[name="perRegion"]', "1");
|
I.pressKey("Enter");
|
I.fillField('[name="perRegion"]', "letter");
|
I.pressKey("Enter");
|
I.fillField('[name="perRegion"]', "last");
|
I.pressKey("Enter");
|
|
I.say("Try to create duplicate value by editing");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(2),
|
);
|
I.pressKey("Backspace");
|
I.pressKey("a");
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.say("Check that these changes were not committed");
|
I.see("1", locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
I.dontSee("a", locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
|
I.say("Delete second region and check results after that");
|
I.click(
|
locate('[aria-label="Delete Region"]'),
|
locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
|
I.see("a", locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=1]")));
|
I.see(
|
"letter",
|
locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
I.see("last", locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=3]")));
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[1].value.text,
|
["a", "letter", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["a", "letter", "last"])} but ${
|
result[1].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to keep the same value after editing without errors");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(2),
|
);
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("letter").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.see(
|
"letter",
|
locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")),
|
);
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[1].value.text,
|
["a", "letter", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["a", "letter", "last"])} but ${
|
result[1].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to set different value by editing and do not get errors");
|
|
I.click(
|
locate('[aria-label="Edit Region"]').inside('[data-testid="textarea-region"]').at(2),
|
locate(".lsf-text-area").at(2),
|
);
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("other").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.see("other", locate(".lsf-text-area").at(2).find(locate(".//*[./@data-testid = 'textarea-region'][position()=2]")));
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[1].value.text,
|
["a", "other", "last"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["a", "other", "last"])} but ${
|
result[1].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check ocr-like perRegion Textarea regions editing");
|
AtOutliner.clickRegion(2);
|
|
I.say("Create some random values in ocr-like perRegion Textarea");
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "One");
|
I.pressKey("Enter");
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "Two");
|
I.pressKey("Enter");
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "Three");
|
I.pressKey("Enter");
|
I.fillField(AtOutliner.locateSelectedItem(".lsf-textarea-tag__form input"), "Four");
|
I.pressKey("Enter");
|
|
I.say("Try to create duplicate value by editing");
|
|
I.click(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")));
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
I.pressKey("O");
|
I.pressKey("n");
|
I.pressKey("e");
|
I.pressKey("Enter");
|
|
Modals.seeWarning(SKIP_DUPLICATES_ERROR);
|
Modals.closeWarning();
|
|
I.say("Check that these changes were not committed");
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")), "Two");
|
I.dontSeeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")), "One");
|
|
I.say("Delete second region and check results after that");
|
I.click(
|
locate('[aria-label="Delete Region"]'),
|
AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2)")),
|
);
|
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(1) input")), "One");
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")), "Three");
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(3) input")), "Four");
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[3].value.text,
|
["One", "Three", "Four"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["One", "Three", "Four"])} but ${
|
result[3].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to keep the same value after editing without errors");
|
|
I.click(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")));
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("Three").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")), "Three");
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[3].value.text,
|
["One", "Three", "Four"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["One", "Three", "Four"])} but ${
|
result[3].value.text
|
} was given.`,
|
);
|
}
|
|
I.say("Check that skip duplication allow us to set different value by editing and do not get errors");
|
|
I.click(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")));
|
I.pressKey(["CommandOrControl", "a"]);
|
I.pressKey("Backspace");
|
Array.from("other").forEach((v) => {
|
I.pressKey(v);
|
});
|
I.pressKey("Enter");
|
|
I.seeInField(AtOutliner.locateSelectedItem(locate(".lsf-textarea-tag__item:nth-child(2) input")), "other");
|
Modals.dontSeeWarning(SKIP_DUPLICATES_ERROR);
|
|
{
|
const result = await LabelStudio.serialize();
|
|
assert.deepStrictEqual(
|
result[3].value.text,
|
["One", "other", "Four"],
|
`There should be 3 specific text lines in the textarea result: ${JSON.stringify(["One", "other", "Four"])} but ${
|
result[3].value.text
|
} was given.`,
|
);
|
}
|
});
|