Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const assert = require("assert");
 
Feature("Nested choices");
 
Scenario("Switching states at nested choices", async ({ I, LabelStudio }) => {
  const params = {
    config: `
<View>
  <Text name="text" value="$text"></Text>
  <Choices name="choices" toName="text" allownested="true" >
    <Choice value="Header 1">
      <Choice value="Option 1.1" />
      <Choice value="Option 1.2" />
    </Choice>
    <Choice value="Header 2">
      <Choice value="Option 2.1" />
      <Choice value="Option 2.2" />
      <Choice value="Option 2.3" />
    </Choice>
  </Choices>
</View>`,
    data: {
      text: "Some text",
    },
    annotations: [
      {
        id: "test",
        result: [],
      },
    ],
  };
 
  I.amOnPage("/");
 
  LabelStudio.init(params);
 
  {
    // Select one choice
    I.click("Option 1.1");
    const result = await LabelStudio.serialize();
 
    // Should be checked only one item
    assert.deepStrictEqual(result[0].value.choices.length, 1);
    assert.deepStrictEqual(result[0].value.choices, [["Header 1", "Option 1.1"]]);
 
    // There might be checkbox with indeterminate state
    I.seeElement(".ant-checkbox-indeterminate [name='Header 1']");
  }
 
  {
    // Select a couple of choices by selecting the parent choice
    I.click("Header 1");
    const result = await LabelStudio.serialize();
 
    // Should be checked three items
    assert.deepStrictEqual(result[0].value.choices.length, 3);
    assert.deepStrictEqual(result[0].value.choices, [
      ["Header 1"],
      ["Header 1", "Option 1.1"],
      ["Header 1", "Option 1.2"],
    ]);
    I.dontSeeElement(".ant-checkbox-indeterminate [name='Header 1']");
  }
 
  {
    // Unselect a couple of choices by unselecting the parent choice
    I.click("Header 1");
    const result = await LabelStudio.serialize();
 
    // Should be checked three items
    assert.deepStrictEqual(result.length, 0);
  }
});
 
Scenario("Nested choices states from the annotation", async ({ I, LabelStudio }) => {
  const params = {
    config: `
<View>
  <Text name="text" value="$text"></Text>
  <Choices name="choices" toName="text" allownested="true" >
    <Choice value="Header 1">
      <Choice value="Option 1.1" />
      <Choice value="Option 1.2" />
    </Choice>
    <Choice value="Header 2">
      <Choice value="Option 2.1" />
      <Choice value="Option 2.2" />
    </Choice>
    <Choice value="Header 3">
      <Choice value="Option 3.1" />
      <Choice value="Option 3.2" />
    </Choice>
  </Choices>
</View>`,
    data: {
      text: "Some text",
    },
  };
 
  I.amOnPage("/");
 
  // Load annotation with each type of selection for branches (fully checked, fully unchecked, partly checked)
  LabelStudio.init({
    ...params,
    annotations: [
      {
        id: "test",
        result: [
          {
            id: "choices_test",
            from_name: "choices",
            to_name: "text",
            type: "choices",
            value: {
              choices: [
                ["Header 1"],
                ["Header 1", "Option 1.1"],
                ["Header 1", "Option 1.2"],
                ["Header 3", "Option 3.1"],
              ],
            },
          },
        ],
      },
    ],
  });
 
  // Check loaded results:
 
  // Fully checked branch of choices
  I.dontSeeElement(".ant-checkbox-indeterminate [name='Header 1']");
  I.seeElement(".ant-checkbox-checked [name='Header 1']");
  I.seeElement(".ant-checkbox-checked [name='Option 1.1']");
  I.seeElement(".ant-checkbox-checked [name='Option 1.2']");
 
  // Fully unchecked branch of choices
  I.dontSeeElement(".ant-checkbox-indeterminate [name='Header 2']");
  I.dontSeeElement(".ant-checkbox-checked [name='Header 2']");
  I.dontSeeElement(".ant-checkbox-checked [name='Option 2.1']");
  I.dontSeeElement(".ant-checkbox-checked [name='Option 2.2']");
 
  // Partly checked branch of choices
  I.seeElement(".ant-checkbox-indeterminate [name='Header 3']");
  I.dontSeeElement(".ant-checkbox-checked [name='Header 3']");
  I.seeElement(".ant-checkbox-checked [name='Option 3.1']");
  I.dontSeeElement(".ant-checkbox-checked [name='Option 3.2']");
 
  const result = await LabelStudio.serialize();
 
  // Should be checked only one item
  assert.deepStrictEqual(result[0].value.choices.length, 4);
  assert.deepStrictEqual(result[0].value.choices, [
    ["Header 1"],
    ["Header 1", "Option 1.1"],
    ["Header 1", "Option 1.2"],
    ["Header 3", "Option 3.1"],
  ]);
});