Skip to content
This repository was archived by the owner on Apr 18, 2024. It is now read-only.

Commit 1d07d4a

Browse files
authored
feat: DEV-1372: Add visibleWhen choice-unselected option (#489)
* feat: DEV-1372: Add visibleWhen choice-unselected option * test: DEV-1372: Add tests for visibleWhen choice-unselected option * test: DEV-1372: Fix required test
1 parent fbeb884 commit 1d07d4a

File tree

6 files changed

+129
-5
lines changed

6 files changed

+129
-5
lines changed

e2e/tests/nested.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,54 @@ Scenario("Check good nested Choice for Text", async function({ I, AtLabels, AtSi
146146
assert.deepEqual(result[2].value.labels, ["Person"]);
147147
assert.deepEqual(result[3].value.choices, ["Female"]);
148148
});
149+
150+
Scenario("Check removing unexpected results based on visibleWhen parameter", async function({ I, LabelStudio }) {
151+
const params = {
152+
config: `<View>
153+
<Text name="text" value="$reviewText" valueType="text" />
154+
<Choices name="sentiment" toName="text" showInLine="true">
155+
<Choice value="Positive" />
156+
<Choice value="Negative" />
157+
<Choice value="Neutral" />
158+
</Choices>
159+
<Choices
160+
name="rate" toName="text" choice="single" showInLine="true"
161+
visibleWhen="choice-unselected"
162+
whenTagName="sentiment"
163+
whenChoiceValue="Neutral"
164+
>
165+
<Choice value="One" />
166+
<Choice value="Two" />
167+
<Choice value="Three" />
168+
<Choice value="Four" />
169+
<Choice value="Five" />
170+
</Choices>
171+
</View>`,
172+
data: { reviewText },
173+
};
174+
175+
I.amOnPage("/");
176+
LabelStudio.setFeatureFlags({
177+
ff_front_dev_1372_visible_when_choice_unselected_11022022_short: true,
178+
});
179+
LabelStudio.init(params);
180+
181+
I.see("Neutral");
182+
I.see("Five");
183+
// Choose rate
184+
I.click("Five");
185+
// Then hide it by choosing value from the visibleWhen="choice-unselected" dependency
186+
I.click("Neutral");
187+
let result = await I.executeScript(serialize);
188+
189+
// The hidden choose should not make a result
190+
assert.equal(result.length, 1);
191+
assert.deepEqual(result[0].value, { choices: ["Neutral"] });
192+
193+
// Check that it still works in case of no hidding
194+
I.click("Positive");
195+
result = await I.executeScript(serialize);
196+
assert.equal(result.length, 2);
197+
assert.deepEqual(result[0].value, { choices: ["Five"] });
198+
assert.deepEqual(result[1].value, { choices: ["Positive"] });
199+
});

e2e/tests/required.test.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ const { initLabelStudio } = require("./helpers");
44

55
Feature("Test required param");
66

7-
const config = `
7+
const createConfig = ({ visibleWhen = "choice-selected" } = {}) => {
8+
return `
89
<View>
910
<Text name="text" value="$text"></Text>
1011
<Choices name="validation-label" required="true" toName="text">
@@ -16,7 +17,7 @@ const config = `
1617
<Choice value="Me neither" alias="neither"></Choice>
1718
</Choices>
1819
<Choices name="easter-egg" required="true" toName="text"
19-
visibleWhen="choice-selected"
20+
visibleWhen="${visibleWhen}"
2021
whenTagName="second"
2122
whenChoiceValue="Me neither"
2223
>
@@ -25,6 +26,8 @@ const config = `
2526
</Choices>
2627
</View>
2728
`;
29+
};
30+
2831

2932
const complex = `
3033
<View>
@@ -85,7 +88,7 @@ const result = {
8588
const annotations = [{ id: "1", result: [result] }];
8689

8790
Scenario("Check required param", async function({ I }) {
88-
const params = { config, data: { text } };
91+
const params = { config: createConfig(), data: { text } };
8992

9093
const waitForError = name => {
9194
I.waitForText("OK");
@@ -204,3 +207,57 @@ Scenario("Check required param in complex config", async function({ I }) {
204207
I.dontSee("Submit");
205208
I.see("Update");
206209
});
210+
211+
Scenario("Check required param with visibleWhen='choice-unselected'", async function({ I, LabelStudio }) {
212+
const params = { config: createConfig({ visibleWhen: 'choice-unselected' }), data: { text } };
213+
const waitForError = name => {
214+
I.waitForText("OK");
215+
I.see("Warning");
216+
I.see('Checkbox "' + name + '" is required');
217+
I.seeElement(".ant-modal");
218+
I.click("OK");
219+
I.waitToHide(".ant-modal");
220+
};
221+
222+
I.amOnPage("/");
223+
LabelStudio.setFeatureFlags({
224+
ff_front_dev_1372_visible_when_choice_unselected_11022022_short: true,
225+
});
226+
LabelStudio.init(params);
227+
228+
// Add new Annotation to be able to submit it
229+
I.click('[aria-label="Annotations List Toggle"]');
230+
I.click('[aria-label="Create Annotation"]');
231+
232+
// Select one from each choices groups, except the one with visibleWhen condition
233+
I.click("Valid");
234+
I.click("Don't select me");
235+
236+
// We should get error, cause "easter-egg" is visible and required
237+
I.click("Submit");
238+
waitForError("easter-egg");
239+
240+
// Select the "Me neither" option to make the "easter-egg" block not required
241+
I.click("Me neither");
242+
I.click("Submit");
243+
// Annotation is submitted, so now we can only update it
244+
I.dontSee("Submit");
245+
I.see("Update");
246+
247+
// Reset to check another scenario
248+
LabelStudio.init(params);
249+
// LabelStudio is reloaded, there are no new annotation from prev steps
250+
I.dontSee("New annotation");
251+
I.click('[aria-label="Annotations List Toggle"]');
252+
I.click('[aria-label="Create Annotation"]');
253+
254+
// Select all required options we have
255+
I.click("Valid");
256+
I.click("Don't select me");
257+
I.click("Secret level");
258+
259+
I.click("Submit");
260+
// Annotation is submitted, so now we can only update it
261+
I.dontSee("Submit");
262+
I.see("Update");
263+
});

e2e/tests/shortcuts.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,5 @@ Data(configParams).Scenario("Should work with existent regions.", async ({ I, La
200200
// If we got an expected result then we didn't lost focus.
201201
AtSidebar.seeRegions(1);
202202
AtSidebar.see("-A + B!");
203-
}).tag("@this");
203+
});
204204

src/mixins/Visibility.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getParent, types } from "mobx-state-tree";
2+
import { FF_DEV_1372, isFF } from "../utils/feature-flags";
23

34
/*
45
* Per Region Mixin
@@ -59,6 +60,10 @@ const VisibilityMixin = types
5960
"no-region-selected": () => !self.annotation.highlightedNode,
6061
};
6162

63+
if (isFF(FF_DEV_1372)) {
64+
fns["choice-unselected"] = params => !fns["choice-selected"](params);
65+
}
66+
6267
if (Object.keys(fns).includes(self.visiblewhen)) {
6368
const res = fns[self.visiblewhen]({
6469
tagName: self.whentagname,

src/regions/Result.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { guidGenerator } from "../core/Helpers";
33
import Registry from "../core/Registry";
44
import { AnnotationMixin } from "../mixins/AnnotationMixin";
55
import { isDefined } from "../utils/utilities";
6+
import { FF_DEV_1372, isFF } from "../utils/feature-flags";
67

78
const Result = types
89
.model("Result", {
@@ -143,7 +144,7 @@ const Result = types
143144
if (label && !self.area.hasLabel(label)) return false;
144145
}
145146

146-
if (control.visiblewhen === "choice-selected") {
147+
const isChoiceSelected = () => {
147148
const tagName = control.whentagname;
148149
const choiceValues = control.whenchoicevalue ? control.whenchoicevalue.split(",") : null;
149150
const results = self.annotation.results.filter(r => r.type === "choices" && r !== self);
@@ -162,6 +163,13 @@ const Result = types
162163
// if no given choice value is selected in any choice result
163164
if (choiceValues && !choiceValues.some(v => results.some(r => r.mainValue.includes(v)))) return false;
164165
}
166+
return true;
167+
};
168+
169+
if (control.visiblewhen === "choice-selected") {
170+
return isChoiceSelected();
171+
} else if (isFF(FF_DEV_1372) && control.visiblewhen === "choice-unselected") {
172+
return !isChoiceSelected();
165173
}
166174

167175
return true;

src/utils/feature-flags.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ export const FF_DEV_1536 = "ff_front_dev_1536_taxonomy_user_labels_150222_long";
2020
// Show or not dialog for rejection
2121
export const FF_DEV_1593 = "ff_front_1593_rejection_comment_040222_short";
2222

23+
// Add visibleWhen="choice-unselected" option
24+
export const FF_DEV_1372 = "ff_front_dev_1372_visible_when_choice_unselected_11022022_short";
25+
2326
// Add an interactivity flag to the results to make some predictions' results be able to be automatically added to newly created annotations.
2427
export const FF_DEV_1621 = "ff_front_dev_1621_interactive_mode_150222_short";
2528

0 commit comments

Comments
 (0)